diff options
Diffstat (limited to 'JavaScriptCore')
345 files changed, 44122 insertions, 20329 deletions
diff --git a/JavaScriptCore/API/APICast.h b/JavaScriptCore/API/APICast.h index ecd524c..1344a16 100644 --- a/JavaScriptCore/API/APICast.h +++ b/JavaScriptCore/API/APICast.h @@ -26,8 +26,15 @@ #ifndef APICast_h #define APICast_h -#include "ustring.h" -#include "ExecState.h" +#include "JSValue.h" + +namespace JSC { + class ExecState; + class PropertyNameArray; + class JSGlobalData; + class JSObject; + class JSValuePtr; +} typedef const struct OpaqueJSContextGroup* JSContextGroupRef; typedef const struct OpaqueJSContext* JSContextRef; @@ -48,9 +55,9 @@ inline JSC::ExecState* toJS(JSGlobalContextRef c) return reinterpret_cast<JSC::ExecState*>(c); } -inline JSC::JSValue* toJS(JSValueRef v) +inline JSC::JSValuePtr toJS(JSValueRef v) { - return reinterpret_cast<JSC::JSValue*>(const_cast<OpaqueJSValue*>(v)); + return JSC::JSValuePtr::decode(reinterpret_cast<JSC::JSValueEncodedAsPointer*>(const_cast<OpaqueJSValue*>(v))); } inline JSC::JSObject* toJS(JSObjectRef o) @@ -68,14 +75,14 @@ inline JSC::JSGlobalData* toJS(JSContextGroupRef g) return reinterpret_cast<JSC::JSGlobalData*>(const_cast<OpaqueJSContextGroup*>(g)); } -inline JSValueRef toRef(JSC::JSValue* v) +inline JSValueRef toRef(JSC::JSValuePtr v) { - return reinterpret_cast<JSValueRef>(v); + return reinterpret_cast<JSValueRef>(JSC::JSValuePtr::encode(v)); } -inline JSValueRef* toRef(JSC::JSValue** v) +inline JSValueRef* toRef(JSC::JSValuePtr* v) { - return reinterpret_cast<JSValueRef*>(const_cast<const JSC::JSValue**>(v)); + return reinterpret_cast<JSValueRef*>(v); } inline JSObjectRef toRef(JSC::JSObject* o) diff --git a/JavaScriptCore/API/JSBase.cpp b/JavaScriptCore/API/JSBase.cpp index bd2935c..2ffe345 100644 --- a/JavaScriptCore/API/JSBase.cpp +++ b/JavaScriptCore/API/JSBase.cpp @@ -28,12 +28,12 @@ #include "JSBasePrivate.h" #include "APICast.h" -#include "completion.h" +#include "Completion.h" #include "OpaqueJSString.h" #include "SourceCode.h" -#include <runtime/ExecState.h> +#include <interpreter/CallFrame.h> #include <runtime/InitializeThreading.h> -#include <kjs/interpreter.h> +#include <runtime/Completion.h> #include <runtime/JSGlobalObject.h> #include <runtime/JSLock.h> #include <runtime/JSObject.h> @@ -48,10 +48,10 @@ JSValueRef JSEvaluateScript(JSContextRef ctx, JSStringRef script, JSObjectRef th JSObject* jsThisObject = toJS(thisObject); - // Interpreter::evaluate sets "this" to the global object if it is NULL + // evaluate sets "this" to the global object if it is NULL JSGlobalObject* globalObject = exec->dynamicGlobalObject(); SourceCode source = makeSource(script->ustring(), sourceURL->ustring(), startingLineNumber); - Completion completion = Interpreter::evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), source, jsThisObject); + Completion completion = evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), source, jsThisObject); if (completion.complType() == Throw) { if (exception) @@ -73,7 +73,7 @@ bool JSCheckScriptSyntax(JSContextRef ctx, JSStringRef script, JSStringRef sourc JSLock lock(exec); SourceCode source = makeSource(script->ustring(), sourceURL->ustring(), startingLineNumber); - Completion completion = Interpreter::checkSyntax(exec->dynamicGlobalObject()->globalExec(), source); + Completion completion = checkSyntax(exec->dynamicGlobalObject()->globalExec(), source); if (completion.complType() == Throw) { if (exception) *exception = toRef(completion.value()); diff --git a/JavaScriptCore/API/JSCallbackConstructor.cpp b/JavaScriptCore/API/JSCallbackConstructor.cpp index 29c26ea..e10733e 100644 --- a/JavaScriptCore/API/JSCallbackConstructor.cpp +++ b/JavaScriptCore/API/JSCallbackConstructor.cpp @@ -36,7 +36,7 @@ namespace JSC { const ClassInfo JSCallbackConstructor::info = { "CallbackConstructor", 0, 0, 0 }; -JSCallbackConstructor::JSCallbackConstructor(PassRefPtr<StructureID> structure, JSClassRef jsClass, JSObjectCallAsConstructorCallback callback) +JSCallbackConstructor::JSCallbackConstructor(PassRefPtr<Structure> structure, JSClassRef jsClass, JSObjectCallAsConstructorCallback callback) : JSObject(structure) , m_class(jsClass) , m_callback(callback) diff --git a/JavaScriptCore/API/JSCallbackConstructor.h b/JavaScriptCore/API/JSCallbackConstructor.h index 01f15a8..cb8307f 100644 --- a/JavaScriptCore/API/JSCallbackConstructor.h +++ b/JavaScriptCore/API/JSCallbackConstructor.h @@ -33,15 +33,15 @@ namespace JSC { class JSCallbackConstructor : public JSObject { public: - JSCallbackConstructor(PassRefPtr<StructureID>, JSClassRef, JSObjectCallAsConstructorCallback); + JSCallbackConstructor(PassRefPtr<Structure>, JSClassRef, JSObjectCallAsConstructorCallback); virtual ~JSCallbackConstructor(); JSClassRef classRef() const { return m_class; } JSObjectCallAsConstructorCallback callback() const { return m_callback; } static const ClassInfo info; - static PassRefPtr<StructureID> createStructureID(JSValue* proto) + static PassRefPtr<Structure> createStructure(JSValuePtr proto) { - return StructureID::create(proto, TypeInfo(ObjectType, ImplementsHasInstance | HasStandardGetOwnPropertySlot)); + return Structure::create(proto, TypeInfo(ObjectType, ImplementsHasInstance | HasStandardGetOwnPropertySlot)); } private: diff --git a/JavaScriptCore/API/JSCallbackFunction.cpp b/JavaScriptCore/API/JSCallbackFunction.cpp index 45d726a..86a2ebc 100644 --- a/JavaScriptCore/API/JSCallbackFunction.cpp +++ b/JavaScriptCore/API/JSCallbackFunction.cpp @@ -46,11 +46,11 @@ JSCallbackFunction::JSCallbackFunction(ExecState* exec, JSObjectCallAsFunctionCa { } -JSValue* JSCallbackFunction::call(ExecState* exec, JSObject* functionObject, JSValue* thisValue, const ArgList& args) +JSValuePtr JSCallbackFunction::call(ExecState* exec, JSObject* functionObject, JSValuePtr thisValue, const ArgList& args) { JSContextRef execRef = toRef(exec); JSObjectRef functionRef = toRef(functionObject); - JSObjectRef thisObjRef = toRef(thisValue->toThisObject(exec)); + JSObjectRef thisObjRef = toRef(thisValue.toThisObject(exec)); int argumentCount = static_cast<int>(args.size()); Vector<JSValueRef, 16> arguments(argumentCount); diff --git a/JavaScriptCore/API/JSCallbackFunction.h b/JavaScriptCore/API/JSCallbackFunction.h index 806a992..46f6fcc 100644 --- a/JavaScriptCore/API/JSCallbackFunction.h +++ b/JavaScriptCore/API/JSCallbackFunction.h @@ -39,16 +39,16 @@ public: // InternalFunction mish-mashes constructor and function behavior -- we should // refactor the code so this override isn't necessary - static PassRefPtr<StructureID> createStructureID(JSValue* proto) + static PassRefPtr<Structure> createStructure(JSValuePtr proto) { - return StructureID::create(proto, TypeInfo(ObjectType, HasStandardGetOwnPropertySlot)); + return Structure::create(proto, TypeInfo(ObjectType, HasStandardGetOwnPropertySlot)); } private: virtual CallType getCallData(CallData&); virtual const ClassInfo* classInfo() const { return &info; } - static JSValue* call(ExecState*, JSObject*, JSValue*, const ArgList&); + static JSValuePtr call(ExecState*, JSObject*, JSValuePtr, const ArgList&); JSObjectCallAsFunctionCallback m_callback; }; diff --git a/JavaScriptCore/API/JSCallbackObject.cpp b/JavaScriptCore/API/JSCallbackObject.cpp index 4be35bd..2fde0f8 100644 --- a/JavaScriptCore/API/JSCallbackObject.cpp +++ b/JavaScriptCore/API/JSCallbackObject.cpp @@ -27,7 +27,7 @@ #include "config.h" #include "JSCallbackObject.h" -#include "collector.h" +#include "Collector.h" namespace JSC { diff --git a/JavaScriptCore/API/JSCallbackObject.h b/JavaScriptCore/API/JSCallbackObject.h index 7543e17..9001c43 100644 --- a/JavaScriptCore/API/JSCallbackObject.h +++ b/JavaScriptCore/API/JSCallbackObject.h @@ -36,7 +36,7 @@ namespace JSC { template <class Base> class JSCallbackObject : public Base { public: - JSCallbackObject(ExecState*, PassRefPtr<StructureID>, JSClassRef, void* data); + JSCallbackObject(ExecState*, PassRefPtr<Structure>, JSClassRef, void* data); JSCallbackObject(JSClassRef); virtual ~JSCallbackObject(); @@ -48,9 +48,9 @@ public: JSClassRef classRef() const { return m_callbackObjectData->jsClass; } bool inherits(JSClassRef) const; - static PassRefPtr<StructureID> createStructureID(JSValue* proto) + static PassRefPtr<Structure> createStructure(JSValuePtr proto) { - return StructureID::create(proto, TypeInfo(ObjectType, ImplementsHasInstance | OverridesHasInstance)); + return Structure::create(proto, TypeInfo(ObjectType, ImplementsHasInstance | OverridesHasInstance)); } private: @@ -59,12 +59,12 @@ private: virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&); virtual bool getOwnPropertySlot(ExecState*, unsigned, PropertySlot&); - virtual void put(ExecState*, const Identifier&, JSValue*, PutPropertySlot&); + virtual void put(ExecState*, const Identifier&, JSValuePtr, PutPropertySlot&); virtual bool deleteProperty(ExecState*, const Identifier&); virtual bool deleteProperty(ExecState*, unsigned); - virtual bool hasInstance(ExecState* exec, JSValue* value, JSValue* proto); + virtual bool hasInstance(ExecState* exec, JSValuePtr value, JSValuePtr proto); virtual void getPropertyNames(ExecState*, PropertyNameArray&); @@ -77,15 +77,14 @@ private: void init(ExecState*); - static JSCallbackObject* asCallbackObject(JSValue*); + static JSCallbackObject* asCallbackObject(JSValuePtr); - static JSValue* call(ExecState*, JSObject* functionObject, JSValue* thisValue, const ArgList&); + static JSValuePtr call(ExecState*, JSObject* functionObject, JSValuePtr thisValue, const ArgList&); static JSObject* construct(ExecState*, JSObject* constructor, const ArgList&); - static JSValue* cachedValueGetter(ExecState*, const Identifier&, const PropertySlot&); - static JSValue* staticValueGetter(ExecState*, const Identifier&, const PropertySlot&); - static JSValue* staticFunctionGetter(ExecState*, const Identifier&, const PropertySlot&); - static JSValue* callbackGetter(ExecState*, const Identifier&, const PropertySlot&); + static JSValuePtr staticValueGetter(ExecState*, const Identifier&, const PropertySlot&); + static JSValuePtr staticFunctionGetter(ExecState*, const Identifier&, const PropertySlot&); + static JSValuePtr callbackGetter(ExecState*, const Identifier&, const PropertySlot&); struct JSCallbackObjectData { JSCallbackObjectData(void* privateData, JSClassRef jsClass) diff --git a/JavaScriptCore/API/JSCallbackObjectFunctions.h b/JavaScriptCore/API/JSCallbackObjectFunctions.h index f008987..23f941d 100644 --- a/JavaScriptCore/API/JSCallbackObjectFunctions.h +++ b/JavaScriptCore/API/JSCallbackObjectFunctions.h @@ -40,14 +40,14 @@ namespace JSC { template <class Base> -inline JSCallbackObject<Base>* JSCallbackObject<Base>::asCallbackObject(JSValue* value) +inline JSCallbackObject<Base>* JSCallbackObject<Base>::asCallbackObject(JSValuePtr value) { ASSERT(asObject(value)->inherits(&info)); return static_cast<JSCallbackObject*>(asObject(value)); } template <class Base> -JSCallbackObject<Base>::JSCallbackObject(ExecState* exec, PassRefPtr<StructureID> structure, JSClassRef jsClass, void* data) +JSCallbackObject<Base>::JSCallbackObject(ExecState* exec, PassRefPtr<Structure> structure, JSClassRef jsClass, void* data) : Base(structure) , m_callbackObjectData(new JSCallbackObjectData(data, jsClass)) { @@ -127,10 +127,7 @@ bool JSCallbackObject<Base>::getOwnPropertySlot(ExecState* exec, const Identifie propertyNameRef = OpaqueJSString::create(propertyName.ustring()); JSLock::DropAllLocks dropAllLocks(exec); if (JSValueRef value = getProperty(ctx, thisRef, propertyNameRef.get(), toRef(exec->exceptionSlot()))) { - // cache the value so we don't have to compute it again - // FIXME: This violates the PropertySlot design a little bit. - // We should either use this optimization everywhere, or nowhere. - slot.setCustom(asObject(toJS(value)), cachedValueGetter); + slot.setValue(toJS(value)); return true; } } @@ -160,7 +157,7 @@ bool JSCallbackObject<Base>::getOwnPropertySlot(ExecState* exec, unsigned proper } template <class Base> -void JSCallbackObject<Base>::put(ExecState* exec, const Identifier& propertyName, JSValue* value, PutPropertySlot& slot) +void JSCallbackObject<Base>::put(ExecState* exec, const Identifier& propertyName, JSValuePtr value, PutPropertySlot& slot) { JSContextRef ctx = toRef(exec); JSObjectRef thisRef = toRef(this); @@ -280,7 +277,7 @@ JSObject* JSCallbackObject<Base>::construct(ExecState* exec, JSObject* construct } template <class Base> -bool JSCallbackObject<Base>::hasInstance(ExecState* exec, JSValue* value, JSValue*) +bool JSCallbackObject<Base>::hasInstance(ExecState* exec, JSValuePtr value, JSValuePtr) { JSContextRef execRef = toRef(exec); JSObjectRef thisRef = toRef(this); @@ -307,11 +304,11 @@ CallType JSCallbackObject<Base>::getCallData(CallData& callData) } template <class Base> -JSValue* JSCallbackObject<Base>::call(ExecState* exec, JSObject* functionObject, JSValue* thisValue, const ArgList& args) +JSValuePtr JSCallbackObject<Base>::call(ExecState* exec, JSObject* functionObject, JSValuePtr thisValue, const ArgList& args) { JSContextRef execRef = toRef(exec); JSObjectRef functionRef = toRef(functionObject); - JSObjectRef thisObjRef = toRef(thisValue->toThisObject(exec)); + JSObjectRef thisObjRef = toRef(thisValue.toThisObject(exec)); for (JSClassRef jsClass = static_cast<JSCallbackObject<Base>*>(functionObject)->classRef(); jsClass; jsClass = jsClass->parentClass) { if (JSObjectCallAsFunctionCallback callAsFunction = jsClass->callAsFunction) { @@ -380,8 +377,10 @@ double JSCallbackObject<Base>::toNumber(ExecState* exec) const for (JSClassRef jsClass = classRef(); jsClass; jsClass = jsClass->parentClass) if (JSObjectConvertToTypeCallback convertToType = jsClass->convertToType) { JSLock::DropAllLocks dropAllLocks(exec); - if (JSValueRef value = convertToType(ctx, thisRef, kJSTypeNumber, toRef(exec->exceptionSlot()))) - return toJS(value)->getNumber(); + if (JSValueRef value = convertToType(ctx, thisRef, kJSTypeNumber, toRef(exec->exceptionSlot()))) { + double dValue; + return toJS(value).getNumber(dValue) ? dValue : NaN; + } } return Base::toNumber(exec); @@ -401,7 +400,7 @@ UString JSCallbackObject<Base>::toString(ExecState* exec) const value = convertToType(ctx, thisRef, kJSTypeString, toRef(exec->exceptionSlot())); } if (value) - return toJS(value)->getString(); + return toJS(value).getString(); } return Base::toString(exec); @@ -430,15 +429,7 @@ bool JSCallbackObject<Base>::inherits(JSClassRef c) const } template <class Base> -JSValue* JSCallbackObject<Base>::cachedValueGetter(ExecState*, const Identifier&, const PropertySlot& slot) -{ - JSValue* v = slot.slotBase(); - ASSERT(v); - return v; -} - -template <class Base> -JSValue* JSCallbackObject<Base>::staticValueGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot) +JSValuePtr JSCallbackObject<Base>::staticValueGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot) { JSCallbackObject* thisObj = asCallbackObject(slot.slotBase()); @@ -460,7 +451,7 @@ JSValue* JSCallbackObject<Base>::staticValueGetter(ExecState* exec, const Identi } template <class Base> -JSValue* JSCallbackObject<Base>::staticFunctionGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot) +JSValuePtr JSCallbackObject<Base>::staticFunctionGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot) { JSCallbackObject* thisObj = asCallbackObject(slot.slotBase()); @@ -485,7 +476,7 @@ JSValue* JSCallbackObject<Base>::staticFunctionGetter(ExecState* exec, const Ide } template <class Base> -JSValue* JSCallbackObject<Base>::callbackGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot) +JSValuePtr JSCallbackObject<Base>::callbackGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot) { JSCallbackObject* thisObj = asCallbackObject(slot.slotBase()); diff --git a/JavaScriptCore/API/JSClassRef.cpp b/JavaScriptCore/API/JSClassRef.cpp index 88fd70d..afde7ce 100644 --- a/JavaScriptCore/API/JSClassRef.cpp +++ b/JavaScriptCore/API/JSClassRef.cpp @@ -32,7 +32,7 @@ #include <runtime/InitializeThreading.h> #include <runtime/JSGlobalObject.h> #include <runtime/ObjectPrototype.h> -#include <kjs/identifier.h> +#include <runtime/Identifier.h> using namespace JSC; @@ -111,7 +111,7 @@ PassRefPtr<OpaqueJSClass> OpaqueJSClass::createNoAutomaticPrototype(const JSClas return adoptRef(new OpaqueJSClass(definition, 0)); } -void clearReferenceToPrototype(JSObjectRef prototype) +static void clearReferenceToPrototype(JSObjectRef prototype) { OpaqueJSClassContextData* jsClassData = static_cast<OpaqueJSClassContextData*>(JSObjectGetPrivate(prototype)); ASSERT(jsClassData); diff --git a/JavaScriptCore/API/JSClassRef.h b/JavaScriptCore/API/JSClassRef.h index 71fae18..4f67618 100644 --- a/JavaScriptCore/API/JSClassRef.h +++ b/JavaScriptCore/API/JSClassRef.h @@ -29,8 +29,8 @@ #include "JSObjectRef.h" #include <runtime/JSObject.h> -#include <kjs/protect.h> -#include <kjs/ustring.h> +#include <runtime/Protect.h> +#include <runtime/UString.h> #include <wtf/HashMap.h> #include <wtf/RefCounted.h> diff --git a/JavaScriptCore/API/JSContextRef.cpp b/JavaScriptCore/API/JSContextRef.cpp index ee7286d..c331179 100644 --- a/JavaScriptCore/API/JSContextRef.cpp +++ b/JavaScriptCore/API/JSContextRef.cpp @@ -34,10 +34,17 @@ #include "JSObject.h" #include <wtf/Platform.h> +#if PLATFORM(DARWIN) +#include <mach-o/dyld.h> + +static const int32_t webkitFirstVersionWithConcurrentGlobalContexts = 0x2100500; // 528.5.0 +#endif + using namespace JSC; JSContextGroupRef JSContextGroupCreate() { + initializeThreading(); return toRef(JSGlobalData::create().releaseRef()); } @@ -54,8 +61,21 @@ void JSContextGroupRelease(JSContextGroupRef group) JSGlobalContextRef JSGlobalContextCreate(JSClassRef globalObjectClass) { - JSLock lock(true); - return JSGlobalContextCreateInGroup(toRef(&JSGlobalData::sharedInstance()), globalObjectClass); + initializeThreading(); +#if PLATFORM(DARWIN) + // When running on Tiger or Leopard, or if the application was linked before JSGlobalContextCreate was changed + // to use a unique JSGlobalData, we use a shared one for compatibility. +#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) + if (NSVersionOfLinkTimeLibrary("JavaScriptCore") <= webkitFirstVersionWithConcurrentGlobalContexts) { +#else + { +#endif + JSLock lock(true); + return JSGlobalContextCreateInGroup(toRef(&JSGlobalData::sharedInstance()), globalObjectClass); + } +#endif // PLATFORM(DARWIN) + + return JSGlobalContextCreateInGroup(0, globalObjectClass); } JSGlobalContextRef JSGlobalContextCreateInGroup(JSContextGroupRef group, JSClassRef globalObjectClass) @@ -66,6 +86,10 @@ JSGlobalContextRef JSGlobalContextCreateInGroup(JSContextGroupRef group, JSClass RefPtr<JSGlobalData> globalData = group ? PassRefPtr<JSGlobalData>(toJS(group)) : JSGlobalData::create(); +#if ENABLE(JSC_MULTIPLE_THREADS) + globalData->makeUsableFromMultipleThreads(); +#endif + if (!globalObjectClass) { JSGlobalObject* globalObject = new (globalData.get()) JSGlobalObject; return JSGlobalContextRetain(toGlobalRef(globalObject->globalExec())); @@ -73,7 +97,7 @@ JSGlobalContextRef JSGlobalContextCreateInGroup(JSContextGroupRef group, JSClass JSGlobalObject* globalObject = new (globalData.get()) JSCallbackObject<JSGlobalObject>(globalObjectClass); ExecState* exec = globalObject->globalExec(); - JSValue* prototype = globalObjectClass->prototype(exec); + JSValuePtr prototype = globalObjectClass->prototype(exec); if (!prototype) prototype = jsNull(); globalObject->resetPrototype(prototype); diff --git a/JavaScriptCore/API/JSContextRef.h b/JavaScriptCore/API/JSContextRef.h index bb6ea6e..bc89511 100644 --- a/JavaScriptCore/API/JSContextRef.h +++ b/JavaScriptCore/API/JSContextRef.h @@ -71,13 +71,14 @@ JS_EXPORT void JSContextGroupRelease(JSContextGroupRef group) AVAILABLE_AFTER_WE @discussion JSGlobalContextCreate allocates a global object and populates it with all the built-in JavaScript objects, such as Object, Function, String, and Array. - The created context can only be used on the main thread. JavaScript values cannot be - shared or exchanged between contexts. + In WebKit version 4.0 and later, the context is created in a unique context group. + Therefore, scripts may execute in it concurrently with scripts executing in other contexts. + However, you may not use values created in the context in other contexts. @param globalObjectClass The class to use when creating the global object. Pass NULL to use the default object class. @result A JSGlobalContext with a global object of class globalObjectClass. */ -JS_EXPORT JSGlobalContextRef JSGlobalContextCreate(JSClassRef globalObjectClass) AVAILABLE_WEBKIT_VERSION_3_0_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_3_1; +JS_EXPORT JSGlobalContextRef JSGlobalContextCreate(JSClassRef globalObjectClass) AVAILABLE_WEBKIT_VERSION_3_0_AND_LATER; /*! @function diff --git a/JavaScriptCore/API/JSObjectRef.cpp b/JavaScriptCore/API/JSObjectRef.cpp index a4f32ba..67bb2a5 100644 --- a/JavaScriptCore/API/JSObjectRef.cpp +++ b/JavaScriptCore/API/JSObjectRef.cpp @@ -31,6 +31,8 @@ #include "DateConstructor.h" #include "ErrorConstructor.h" #include "FunctionConstructor.h" +#include "Identifier.h" +#include "InitializeThreading.h" #include "JSArray.h" #include "JSCallbackConstructor.h" #include "JSCallbackFunction.h" @@ -45,13 +47,13 @@ #include "ObjectPrototype.h" #include "PropertyNameArray.h" #include "RegExpConstructor.h" -#include "identifier.h" #include <wtf/Platform.h> using namespace JSC; JSClassRef JSClassCreate(const JSClassDefinition* definition) { + initializeThreading(); RefPtr<OpaqueJSClass> jsClass = (definition->attributes & kJSClassAttributeNoAutomaticPrototype) ? OpaqueJSClass::createNoAutomaticPrototype(definition) : OpaqueJSClass::create(definition); @@ -103,7 +105,7 @@ JSObjectRef JSObjectMakeConstructor(JSContextRef ctx, JSClassRef jsClass, JSObje exec->globalData().heap.registerThread(); JSLock lock(exec); - JSValue* jsPrototype = jsClass + JSValuePtr jsPrototype = jsClass ? jsClass->prototype(exec) : exec->lexicalGlobalObject()->objectPrototype(); @@ -233,9 +235,9 @@ JSValueRef JSObjectGetPrototype(JSContextRef, JSObjectRef object) void JSObjectSetPrototype(JSContextRef, JSObjectRef object, JSValueRef value) { JSObject* jsObject = toJS(object); - JSValue* jsValue = toJS(value); + JSValuePtr jsValue = toJS(value); - jsObject->setPrototype(jsValue->isObject() ? jsValue : jsNull()); + jsObject->setPrototype(jsValue.isObject() ? jsValue : jsNull()); } bool JSObjectHasProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName) @@ -257,7 +259,7 @@ JSValueRef JSObjectGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef JSObject* jsObject = toJS(object); - JSValue* jsValue = jsObject->get(exec, propertyName->identifier(&exec->globalData())); + JSValuePtr jsValue = jsObject->get(exec, propertyName->identifier(&exec->globalData())); if (exec->hadException()) { if (exception) *exception = toRef(exec->exception()); @@ -274,7 +276,7 @@ void JSObjectSetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef prope JSObject* jsObject = toJS(object); Identifier name(propertyName->identifier(&exec->globalData())); - JSValue* jsValue = toJS(value); + JSValuePtr jsValue = toJS(value); if (attributes && !jsObject->hasProperty(exec, name)) jsObject->putWithAttributes(exec, name, jsValue, attributes); @@ -298,7 +300,7 @@ JSValueRef JSObjectGetPropertyAtIndex(JSContextRef ctx, JSObjectRef object, unsi JSObject* jsObject = toJS(object); - JSValue* jsValue = jsObject->get(exec, propertyIndex); + JSValuePtr jsValue = jsObject->get(exec, propertyIndex); if (exec->hadException()) { if (exception) *exception = toRef(exec->exception()); @@ -315,7 +317,7 @@ void JSObjectSetPropertyAtIndex(JSContextRef ctx, JSObjectRef object, unsigned p JSLock lock(exec); JSObject* jsObject = toJS(object); - JSValue* jsValue = toJS(value); + JSValuePtr jsValue = toJS(value); jsObject->put(exec, propertyIndex, jsValue); if (exec->hadException()) { diff --git a/JavaScriptCore/API/JSStringRef.cpp b/JavaScriptCore/API/JSStringRef.cpp index 6452ffc..8e236e4 100644 --- a/JavaScriptCore/API/JSStringRef.cpp +++ b/JavaScriptCore/API/JSStringRef.cpp @@ -26,6 +26,7 @@ #include "config.h" #include "JSStringRef.h" +#include "InitializeThreading.h" #include "OpaqueJSString.h" #include <wtf/unicode/UTF8.h> @@ -34,11 +35,13 @@ using namespace WTF::Unicode; JSStringRef JSStringCreateWithCharacters(const JSChar* chars, size_t numChars) { + initializeThreading(); return OpaqueJSString::create(chars, numChars).releaseRef(); } JSStringRef JSStringCreateWithUTF8CString(const char* string) { + initializeThreading(); if (string) { size_t length = strlen(string); Vector<UChar, 1024> buffer(length); diff --git a/JavaScriptCore/API/JSStringRefCF.cpp b/JavaScriptCore/API/JSStringRefCF.cpp index 3a37866..2b8fd9e 100644 --- a/JavaScriptCore/API/JSStringRefCF.cpp +++ b/JavaScriptCore/API/JSStringRefCF.cpp @@ -27,14 +27,16 @@ #include "JSStringRefCF.h" #include "APICast.h" +#include "InitializeThreading.h" #include "JSStringRef.h" #include "OpaqueJSString.h" -#include <kjs/ustring.h> +#include <runtime/UString.h> #include <runtime/JSValue.h> #include <wtf/OwnArrayPtr.h> JSStringRef JSStringCreateWithCFString(CFStringRef string) { + JSC::initializeThreading(); CFIndex length = CFStringGetLength(string); if (length) { OwnArrayPtr<UniChar> buffer(new UniChar[length]); @@ -44,7 +46,7 @@ JSStringRef JSStringCreateWithCFString(CFStringRef string) } else { return OpaqueJSString::create(0, 0).releaseRef(); } - } +} CFStringRef JSStringCopyCFString(CFAllocatorRef alloc, JSStringRef string) { diff --git a/JavaScriptCore/API/JSValueRef.cpp b/JavaScriptCore/API/JSValueRef.cpp index 15dd633..7080952 100644 --- a/JavaScriptCore/API/JSValueRef.cpp +++ b/JavaScriptCore/API/JSValueRef.cpp @@ -32,9 +32,9 @@ #include <runtime/JSGlobalObject.h> #include <runtime/JSString.h> -#include <kjs/operations.h> -#include <kjs/protect.h> -#include <kjs/ustring.h> +#include <runtime/Operations.h> +#include <runtime/Protect.h> +#include <runtime/UString.h> #include <runtime/JSValue.h> #include <wtf/Assertions.h> @@ -43,18 +43,18 @@ JSType JSValueGetType(JSContextRef, JSValueRef value) { - JSC::JSValue* jsValue = toJS(value); - if (jsValue->isUndefined()) + JSC::JSValuePtr jsValue = toJS(value); + if (jsValue.isUndefined()) return kJSTypeUndefined; - if (jsValue->isNull()) + if (jsValue.isNull()) return kJSTypeNull; - if (jsValue->isBoolean()) + if (jsValue.isBoolean()) return kJSTypeBoolean; - if (jsValue->isNumber()) + if (jsValue.isNumber()) return kJSTypeNumber; - if (jsValue->isString()) + if (jsValue.isString()) return kJSTypeString; - ASSERT(jsValue->isObject()); + ASSERT(jsValue.isObject()); return kJSTypeObject; } @@ -62,45 +62,45 @@ using namespace JSC; // placed here to avoid conflict between JSC::JSType and JS bool JSValueIsUndefined(JSContextRef, JSValueRef value) { - JSValue* jsValue = toJS(value); - return jsValue->isUndefined(); + JSValuePtr jsValue = toJS(value); + return jsValue.isUndefined(); } bool JSValueIsNull(JSContextRef, JSValueRef value) { - JSValue* jsValue = toJS(value); - return jsValue->isNull(); + JSValuePtr jsValue = toJS(value); + return jsValue.isNull(); } bool JSValueIsBoolean(JSContextRef, JSValueRef value) { - JSValue* jsValue = toJS(value); - return jsValue->isBoolean(); + JSValuePtr jsValue = toJS(value); + return jsValue.isBoolean(); } bool JSValueIsNumber(JSContextRef, JSValueRef value) { - JSValue* jsValue = toJS(value); - return jsValue->isNumber(); + JSValuePtr jsValue = toJS(value); + return jsValue.isNumber(); } bool JSValueIsString(JSContextRef, JSValueRef value) { - JSValue* jsValue = toJS(value); - return jsValue->isString(); + JSValuePtr jsValue = toJS(value); + return jsValue.isString(); } bool JSValueIsObject(JSContextRef, JSValueRef value) { - JSValue* jsValue = toJS(value); - return jsValue->isObject(); + JSValuePtr jsValue = toJS(value); + return jsValue.isObject(); } bool JSValueIsObjectOfClass(JSContextRef, JSValueRef value, JSClassRef jsClass) { - JSValue* jsValue = toJS(value); + JSValuePtr jsValue = toJS(value); - if (JSObject* o = jsValue->getObject()) { + if (JSObject* o = jsValue.getObject()) { if (o->inherits(&JSCallbackObject<JSGlobalObject>::info)) return static_cast<JSCallbackObject<JSGlobalObject>*>(o)->inherits(jsClass); else if (o->inherits(&JSCallbackObject<JSObject>::info)) @@ -115,10 +115,10 @@ bool JSValueIsEqual(JSContextRef ctx, JSValueRef a, JSValueRef b, JSValueRef* ex exec->globalData().heap.registerThread(); JSLock lock(exec); - JSValue* jsA = toJS(a); - JSValue* jsB = toJS(b); + JSValuePtr jsA = toJS(a); + JSValuePtr jsB = toJS(b); - bool result = equal(exec, jsA, jsB); // false if an exception is thrown + bool result = JSValuePtr::equal(exec, jsA, jsB); // false if an exception is thrown if (exec->hadException()) { if (exception) *exception = toRef(exec->exception()); @@ -129,10 +129,10 @@ bool JSValueIsEqual(JSContextRef ctx, JSValueRef a, JSValueRef b, JSValueRef* ex bool JSValueIsStrictEqual(JSContextRef, JSValueRef a, JSValueRef b) { - JSValue* jsA = toJS(a); - JSValue* jsB = toJS(b); + JSValuePtr jsA = toJS(a); + JSValuePtr jsB = toJS(b); - bool result = strictEqual(jsA, jsB); + bool result = JSValuePtr::strictEqual(jsA, jsB); return result; } @@ -142,9 +142,9 @@ bool JSValueIsInstanceOfConstructor(JSContextRef ctx, JSValueRef value, JSObject exec->globalData().heap.registerThread(); JSLock lock(exec); - JSValue* jsValue = toJS(value); + JSValuePtr jsValue = toJS(value); JSObject* jsConstructor = toJS(constructor); - if (!jsConstructor->structureID()->typeInfo().implementsHasInstance()) + if (!jsConstructor->structure()->typeInfo().implementsHasInstance()) return false; bool result = jsConstructor->hasInstance(exec, jsValue, jsConstructor->get(exec, exec->propertyNames().prototype)); // false if an exception is thrown if (exec->hadException()) { @@ -191,8 +191,8 @@ JSValueRef JSValueMakeString(JSContextRef ctx, JSStringRef string) bool JSValueToBoolean(JSContextRef ctx, JSValueRef value) { ExecState* exec = toJS(ctx); - JSValue* jsValue = toJS(value); - return jsValue->toBoolean(exec); + JSValuePtr jsValue = toJS(value); + return jsValue.toBoolean(exec); } double JSValueToNumber(JSContextRef ctx, JSValueRef value, JSValueRef* exception) @@ -201,9 +201,9 @@ double JSValueToNumber(JSContextRef ctx, JSValueRef value, JSValueRef* exception exec->globalData().heap.registerThread(); JSLock lock(exec); - JSValue* jsValue = toJS(value); + JSValuePtr jsValue = toJS(value); - double number = jsValue->toNumber(exec); + double number = jsValue.toNumber(exec); if (exec->hadException()) { if (exception) *exception = toRef(exec->exception()); @@ -219,9 +219,9 @@ JSStringRef JSValueToStringCopy(JSContextRef ctx, JSValueRef value, JSValueRef* exec->globalData().heap.registerThread(); JSLock lock(exec); - JSValue* jsValue = toJS(value); + JSValuePtr jsValue = toJS(value); - RefPtr<OpaqueJSString> stringRef(OpaqueJSString::create(jsValue->toString(exec))); + RefPtr<OpaqueJSString> stringRef(OpaqueJSString::create(jsValue.toString(exec))); if (exec->hadException()) { if (exception) *exception = toRef(exec->exception()); @@ -237,9 +237,9 @@ JSObjectRef JSValueToObject(JSContextRef ctx, JSValueRef value, JSValueRef* exce exec->globalData().heap.registerThread(); JSLock lock(exec); - JSValue* jsValue = toJS(value); + JSValuePtr jsValue = toJS(value); - JSObjectRef objectRef = toRef(jsValue->toObject(exec)); + JSObjectRef objectRef = toRef(jsValue.toObject(exec)); if (exec->hadException()) { if (exception) *exception = toRef(exec->exception()); @@ -255,7 +255,7 @@ void JSValueProtect(JSContextRef ctx, JSValueRef value) exec->globalData().heap.registerThread(); JSLock lock(exec); - JSValue* jsValue = toJS(value); + JSValuePtr jsValue = toJS(value); gcProtect(jsValue); } @@ -265,6 +265,6 @@ void JSValueUnprotect(JSContextRef ctx, JSValueRef value) exec->globalData().heap.registerThread(); JSLock lock(exec); - JSValue* jsValue = toJS(value); + JSValuePtr jsValue = toJS(value); gcUnprotect(jsValue); } diff --git a/JavaScriptCore/API/OpaqueJSString.cpp b/JavaScriptCore/API/OpaqueJSString.cpp index 0819141..7c7b1af 100644 --- a/JavaScriptCore/API/OpaqueJSString.cpp +++ b/JavaScriptCore/API/OpaqueJSString.cpp @@ -26,9 +26,9 @@ #include "config.h" #include "OpaqueJSString.h" -#include <runtime/ExecState.h> +#include <interpreter/CallFrame.h> #include <runtime/JSGlobalObject.h> -#include <kjs/identifier.h> +#include <runtime/Identifier.h> using namespace JSC; diff --git a/JavaScriptCore/API/OpaqueJSString.h b/JavaScriptCore/API/OpaqueJSString.h index da05b06..473c815 100644 --- a/JavaScriptCore/API/OpaqueJSString.h +++ b/JavaScriptCore/API/OpaqueJSString.h @@ -26,7 +26,7 @@ #ifndef OpaqueJSString_h #define OpaqueJSString_h -#include <kjs/ustring.h> +#include <runtime/UString.h> namespace JSC { class Identifier; diff --git a/JavaScriptCore/API/WebKitAvailability.h b/JavaScriptCore/API/WebKitAvailability.h index fae3904..1273360 100644 --- a/JavaScriptCore/API/WebKitAvailability.h +++ b/JavaScriptCore/API/WebKitAvailability.h @@ -43,7 +43,9 @@ #ifdef __APPLE__ #import <AvailabilityMacros.h> #else -// For non-Mac platforms, require the newest version. +/* + * For non-Mac platforms, require the newest version. + */ #define WEBKIT_VERSION_MIN_REQUIRED WEBKIT_VERSION_LATEST /* * only certain compilers support __attribute__((deprecated)) diff --git a/JavaScriptCore/AllInOneFile.cpp b/JavaScriptCore/AllInOneFile.cpp index ffee367..904734f 100644 --- a/JavaScriptCore/AllInOneFile.cpp +++ b/JavaScriptCore/AllInOneFile.cpp @@ -44,49 +44,48 @@ #include "runtime/BooleanConstructor.cpp" #include "runtime/BooleanObject.cpp" #include "runtime/BooleanPrototype.cpp" -#include "kjs/collector.cpp" +#include "runtime/Collector.cpp" #include "runtime/CommonIdentifiers.cpp" #include "runtime/DateConstructor.cpp" #include "runtime/DateMath.cpp" #include "runtime/DatePrototype.cpp" #include "runtime/DateInstance.cpp" -#include "kjs/dtoa.cpp" +#include "wtf/dtoa.cpp" #include "runtime/ErrorInstance.cpp" #include "runtime/ErrorPrototype.cpp" #include "runtime/ErrorConstructor.cpp" #include "runtime/FunctionConstructor.cpp" #include "runtime/FunctionPrototype.cpp" -#include "grammar.cpp" -#include "kjs/identifier.cpp" +#include "Grammar.cpp" +#include "runtime/Identifier.cpp" #include "runtime/JSString.cpp" #include "runtime/JSNumberCell.cpp" #include "runtime/GetterSetter.cpp" #include "runtime/InternalFunction.cpp" -#include "kjs/interpreter.cpp" +#include "runtime/Completion.cpp" #include "runtime/JSImmediate.cpp" #include "runtime/JSLock.cpp" #include "runtime/JSWrapperObject.cpp" -#include "kjs/lexer.cpp" +#include "parser/Lexer.cpp" #include "runtime/ArgList.cpp" -#include "kjs/lookup.cpp" +#include "runtime/Lookup.cpp" #include "runtime/MathObject.cpp" #include "runtime/NativeErrorConstructor.cpp" #include "runtime/NativeErrorPrototype.cpp" #include "runtime/NumberConstructor.cpp" #include "runtime/NumberObject.cpp" #include "runtime/NumberPrototype.cpp" -#include "kjs/nodes.cpp" -#include "kjs/nodes2string.cpp" +#include "parser/Nodes.cpp" #include "runtime/JSObject.cpp" #include "runtime/Error.cpp" #include "runtime/JSGlobalObject.cpp" #include "runtime/ObjectConstructor.cpp" #include "runtime/ObjectPrototype.cpp" -#include "kjs/operations.cpp" -#include "kjs/Parser.cpp" +#include "runtime/Operations.cpp" +#include "parser/Parser.cpp" #include "runtime/PropertySlot.cpp" #include "runtime/PropertyNameArray.cpp" -#include "kjs/regexp.cpp" +#include "runtime/RegExp.cpp" #include "runtime/RegExpConstructor.cpp" #include "runtime/RegExpObject.cpp" #include "runtime/RegExpPrototype.cpp" @@ -94,7 +93,7 @@ #include "runtime/StringConstructor.cpp" #include "runtime/StringObject.cpp" #include "runtime/StringPrototype.cpp" -#include "kjs/ustring.cpp" +#include "runtime/UString.cpp" #include "runtime/JSValue.cpp" #include "runtime/CallData.cpp" #include "runtime/ConstructData.cpp" @@ -102,5 +101,5 @@ #include "runtime/JSVariableObject.cpp" #include "wtf/FastMalloc.cpp" #include "wtf/TCSystemAlloc.cpp" -#include "VM/CodeGenerator.cpp" -#include "VM/RegisterFile.cpp" +#include "bytecompiler/BytecodeGenerator.cpp" +#include "interpreter/RegisterFile.cpp" diff --git a/JavaScriptCore/Android.mk b/JavaScriptCore/Android.mk index 98f87c1..f8b568b 100644 --- a/JavaScriptCore/Android.mk +++ b/JavaScriptCore/Android.mk @@ -23,10 +23,10 @@ # # The following files are intentionally not included # LOCAL_SRC_FILES_EXCLUDED := \ -# kjs/AllInOneFile.cpp \ -# kjs/CollectorHeapIntrospector.cpp \ -# kjs/grammar.y \ -# kjs/testkjs.cpp \ +# JSC/AllInOneFile.cpp \ +# JSC/CollectorHeapIntrospector.cpp \ +# JSC/grammar.y \ +# JSC/testJSC.cpp \ # pcre/dftables.c \ # pcre/pcre_maketables.c \ # pcre/ucptable.cpp \ @@ -51,32 +51,25 @@ LOCAL_SRC_FILES := \ \ - VM/CTI.cpp \ - VM/CodeBlock.cpp \ - VM/CodeGenerator.cpp \ - VM/ExceptionHelpers.cpp \ - VM/Machine.cpp \ - VM/Opcode.cpp \ - VM/RegisterFile.cpp \ - VM/SamplingTool.cpp \ + \ + bytecode/CodeBlock.cpp \ + bytecode/JumpTable.cpp \ + bytecode/Opcode.cpp \ + bytecode/SamplingTool.cpp \ + bytecode/StructureStubInfo.cpp \ + bytecompiler/BytecodeGenerator.cpp \ \ debugger/Debugger.cpp \ + debugger/DebuggerActivation.cpp \ debugger/DebuggerCallFrame.cpp \ \ - kjs/Parser.cpp \ - kjs/Shell.cpp \ - kjs/collector.cpp \ - kjs/dtoa.cpp \ - kjs/identifier.cpp \ - kjs/interpreter.cpp \ - kjs/lexer.cpp \ - kjs/lookup.cpp \ - kjs/nodes.cpp \ - kjs/nodes2string.cpp \ - kjs/operations.cpp \ - kjs/regexp.cpp \ - kjs/ustring.cpp \ + interpreter/CallFrame.cpp \ + interpreter/Interpreter.cpp \ + interpreter/RegisterFile.cpp \ \ + parser/Lexer.cpp \ + parser/Nodes.cpp \ + parser/Parser.cpp \ pcre/pcre_compile.cpp \ pcre/pcre_exec.cpp \ pcre/pcre_tables.cpp \ @@ -98,7 +91,9 @@ LOCAL_SRC_FILES := \ runtime/BooleanObject.cpp \ runtime/BooleanPrototype.cpp \ runtime/CallData.cpp \ + runtime/Collector.cpp \ runtime/CommonIdentifiers.cpp \ + runtime/Completion.cpp \ runtime/ConstructData.cpp \ runtime/DateConstructor.cpp \ runtime/DateInstance.cpp \ @@ -108,15 +103,17 @@ LOCAL_SRC_FILES := \ runtime/ErrorConstructor.cpp \ runtime/ErrorInstance.cpp \ runtime/ErrorPrototype.cpp \ - runtime/ExecState.cpp \ + runtime/ExceptionHelpers.cpp \ runtime/FunctionConstructor.cpp \ runtime/FunctionPrototype.cpp \ runtime/GetterSetter.cpp \ runtime/GlobalEvalFunction.cpp \ + runtime/Identifier.cpp \ runtime/InitializeThreading.cpp \ runtime/InternalFunction.cpp \ runtime/JSActivation.cpp \ runtime/JSArray.cpp \ + runtime/JSByteArray.cpp \ runtime/JSCell.cpp \ runtime/JSFunction.cpp \ runtime/JSGlobalData.cpp \ @@ -133,6 +130,7 @@ LOCAL_SRC_FILES := \ runtime/JSValue.cpp \ runtime/JSVariableObject.cpp \ runtime/JSWrapperObject.cpp \ + runtime/Lookup.cpp \ runtime/MathObject.cpp \ runtime/NativeErrorConstructor.cpp \ runtime/NativeErrorPrototype.cpp \ @@ -141,9 +139,11 @@ LOCAL_SRC_FILES := \ runtime/NumberPrototype.cpp \ runtime/ObjectConstructor.cpp \ runtime/ObjectPrototype.cpp \ + runtime/Operations.cpp \ runtime/PropertyNameArray.cpp \ runtime/PropertySlot.cpp \ runtime/PrototypeFunction.cpp \ + runtime/RegExp.cpp \ runtime/RegExpConstructor.cpp \ runtime/RegExpObject.cpp \ runtime/RegExpPrototype.cpp \ @@ -152,34 +152,44 @@ LOCAL_SRC_FILES := \ runtime/StringConstructor.cpp \ runtime/StringObject.cpp \ runtime/StringPrototype.cpp \ - runtime/StructureID.cpp \ - runtime/StructureIDChain.cpp \ + runtime/Structure.cpp \ + runtime/StructureChain.cpp \ + runtime/UString.cpp \ \ + wrec/CharacterClass.cpp \ wrec/CharacterClassConstructor.cpp \ wrec/WREC.cpp \ + wrec/WRECFunctors.cpp \ + wrec/WRECGenerator.cpp \ + wrec/WRECParser.cpp \ \ wtf/android/MainThreadAndroid.cpp \ wtf/Assertions.cpp \ + wtf/ByteArray.cpp \ + wtf/CurrentTime.cpp \ + wtf/dtoa.cpp \ wtf/FastMalloc.cpp \ wtf/HashTable.cpp \ wtf/MainThread.cpp \ + wtf/RandomNumber.cpp \ wtf/RefCountedLeakCounter.cpp \ wtf/TCSystemAlloc.cpp \ + wtf/Threading.cpp \ wtf/ThreadingPthreads.cpp \ wtf/unicode/CollatorDefault.cpp \ wtf/unicode/UTF8.cpp \ wtf/unicode/icu/CollatorICU.cpp # Rule to build grammar.y with our custom bison. -GEN := $(intermediates)/kjs/grammar.cpp -$(GEN) : PRIVATE_YACCFLAGS := -p kjsyy -$(GEN) : $(LOCAL_PATH)/kjs/grammar.y +GEN := $(intermediates)/parser/Grammar.cpp +$(GEN) : PRIVATE_YACCFLAGS := -p jscyy +$(GEN) : $(LOCAL_PATH)/parser/Grammar.y $(call local-transform-y-to-cpp,.cpp) $(GEN) : $(LOCAL_BISON) LOCAL_GENERATED_SOURCES += $(GEN) # generated headers -KJS_OBJECTS := $(addprefix $(intermediates)/runtime/, \ +JSC_OBJECTS := $(addprefix $(intermediates)/runtime/, \ ArrayPrototype.lut.h \ DatePrototype.lut.h \ MathObject.lut.h \ @@ -188,18 +198,18 @@ KJS_OBJECTS := $(addprefix $(intermediates)/runtime/, \ RegExpObject.lut.h \ StringPrototype.lut.h \ ) -$(KJS_OBJECTS): PRIVATE_PATH := $(LOCAL_PATH) -$(KJS_OBJECTS): PRIVATE_CUSTOM_TOOL = perl $(PRIVATE_PATH)/kjs/create_hash_table $< -i > $@ -$(KJS_OBJECTS): $(LOCAL_PATH)/kjs/create_hash_table -$(KJS_OBJECTS): $(intermediates)/%.lut.h : $(LOCAL_PATH)/%.cpp +$(JSC_OBJECTS): PRIVATE_PATH := $(LOCAL_PATH) +$(JSC_OBJECTS): PRIVATE_CUSTOM_TOOL = perl $(PRIVATE_PATH)/create_hash_table $< -i > $@ +$(JSC_OBJECTS): $(LOCAL_PATH)/create_hash_table +$(JSC_OBJECTS): $(intermediates)/%.lut.h : $(LOCAL_PATH)/%.cpp $(transform-generated-source) -LEXER_HEADER := $(intermediates)/lexer.lut.h +LEXER_HEADER := $(intermediates)/Lexer.lut.h $(LEXER_HEADER): PRIVATE_PATH := $(LOCAL_PATH) -$(LEXER_HEADER): PRIVATE_CUSTOM_TOOL = perl $(PRIVATE_PATH)/kjs/create_hash_table $< -i > $@ -$(LEXER_HEADER): $(LOCAL_PATH)/kjs/create_hash_table -$(LEXER_HEADER): $(intermediates)/%.lut.h : $(LOCAL_PATH)/kjs/keywords.table +$(LEXER_HEADER): PRIVATE_CUSTOM_TOOL = perl $(PRIVATE_PATH)/create_hash_table $< -i > $@ +$(LEXER_HEADER): $(LOCAL_PATH)/create_hash_table +$(LEXER_HEADER): $(intermediates)/%.lut.h : $(LOCAL_PATH)/parser/Keywords.table $(transform-generated-source) CHARTABLES := $(intermediates)/chartables.c @@ -211,4 +221,4 @@ $(CHARTABLES): $(LOCAL_PATH)/pcre/pcre_internal.h $(intermediates)/pcre/pcre_tables.o : $(CHARTABLES) -LOCAL_GENERATED_SOURCES += $(KJS_OBJECTS) $(LEXER_HEADER) $(CHARTABLES) +LOCAL_GENERATED_SOURCES += $(JSC_OBJECTS) $(LEXER_HEADER) $(CHARTABLES) diff --git a/JavaScriptCore/ChangeLog b/JavaScriptCore/ChangeLog index ea47411..5b9cc4b 100644 --- a/JavaScriptCore/ChangeLog +++ b/JavaScriptCore/ChangeLog @@ -1,3 +1,13537 @@ +2009-02-13 Mark Rowe <mrowe@apple.com> + + Merge r40975. + + 2009-02-12 Darin Adler <darin@apple.com> + + Reviewed by Oliver Hunt and Alexey Proskuryakov. + + Speed up a couple string functions. + + * runtime/StringPrototype.cpp: + (JSC::stringProtoFuncIndexOf): Added a fast path for cases where the second + argument is either missing or an integer. + (JSC::stringProtoFuncBig): Use jsNontrivialString since the string is guaranteed + to be 2 or more characters long. + (JSC::stringProtoFuncSmall): Ditto. + (JSC::stringProtoFuncBlink): Ditto. + (JSC::stringProtoFuncBold): Ditto. + (JSC::stringProtoFuncItalics): Ditto. + (JSC::stringProtoFuncStrike): Ditto. + (JSC::stringProtoFuncSub): Ditto. + (JSC::stringProtoFuncSup): Ditto. + (JSC::stringProtoFuncFontcolor): Ditto. + (JSC::stringProtoFuncFontsize): Make the fast path Sam recently added even faster + by avoiding all but the minimum memory allocation. + (JSC::stringProtoFuncAnchor): Use jsNontrivialString. + (JSC::stringProtoFuncLink): Added a fast path. + + * runtime/UString.cpp: + (JSC::UString::find): Added a fast path for single-character search strings. + +2009-02-13 Mark Rowe <mrowe@apple.com> + + Merge r40945. + + 2009-02-12 Sam Weinig <sam@webkit.org> + + Reviewed by Geoffrey Garen. + + Speed up String.prototype.fontsize. + + * runtime/StringPrototype.cpp: + (JSC::stringProtoFuncFontsize): Specialize for defined/commonly used values. + +2009-02-13 Mark Rowe <mrowe@apple.com> + + Merge r41000. + + 2009-02-13 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Darin Adler. + + Some data in the instruction stream is potentially uninitialized - fix this. + + Change the OperandTypes constructor so that uninitialized memory in the int + is zeroed, and modify the Instruction constructor taking an Opcode so that + if !HAVE(COMPUTED_GOTO) (i.e. when Opcode is an enum, and is potentially only + a byte) it zeros the Instruction first before writing the opcode. + + * bytecode/Instruction.h: + (JSC::Instruction::Instruction): + * parser/ResultType.h: + (JSC::OperandTypes::OperandTypes): + +2009-02-13 Mark Rowe <mrowe@apple.com> + + Merge r40995. + + 2009-02-13 Geoffrey Garen <ggaren@apple.com> + + Build fix for non_JIT platforms. + + * bytecode/CodeBlock.h: + (JSC::CodeBlock::setIsNumericCompareFunction): + (JSC::CodeBlock::isNumericCompareFunction): + +2009-02-13 Mark Rowe <mrowe@apple.com> + + Merge r40993. + + 2009-02-13 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Darin Adler. + + Fixed <rdar://problem/6584057> Optimize sort by JS numeric comparison + function not to run the comparison function + + * bytecode/CodeBlock.cpp: + (JSC::CodeBlock::CodeBlock): + * bytecode/CodeBlock.h: + (JSC::CodeBlock::setIsNumericCompareFunction): + (JSC::CodeBlock::isNumericCompareFunction): Added the ability to track + whether a CodeBlock performs a sort-like numeric comparison. + + * bytecompiler/BytecodeGenerator.cpp: + (JSC::BytecodeGenerator::generate): Set the isNumericCompareFunction bit + after compiling. + + * parser/Nodes.cpp: + (JSC::FunctionBodyNode::emitBytecode): Fixed a bug that caused us to + codegen an extra return at the end of all functions (eek!), since this + made it harder / weirder to detect the numeric comparison pattern in + bytecode. + + * runtime/ArrayPrototype.cpp: + (JSC::arrayProtoFuncSort): Use the isNumericCompareFunction bit to do + a faster sort if we can. + + * runtime/FunctionConstructor.cpp: + (JSC::extractFunctionBody): + (JSC::constructFunction): + * runtime/FunctionConstructor.h: Renamed and exported extractFunctionBody for + use in initializing lazyNumericCompareFunction. + + * runtime/JSArray.cpp: + (JSC::compareNumbersForQSort): + (JSC::compareByStringPairForQSort): + (JSC::JSArray::sortNumeric): + (JSC::JSArray::sort): + * runtime/JSArray.h: Added a fast numeric sort. Renamed ArrayQSortPair + to be more specific since we do different kinds of qsort now. + + * runtime/JSGlobalData.cpp: + (JSC::JSGlobalData::JSGlobalData): + (JSC::JSGlobalData::numericCompareFunction): + (JSC::JSGlobalData::ClientData::~ClientData): + * runtime/JSGlobalData.h: Added helper data for computing the + isNumericCompareFunction bit. + +2009-02-13 Mark Rowe <mrowe@apple.com> + + Merge r40968. + + 2009-02-13 Oliver Hunt <oliver@apple.com> + + Reviewed by Jon Honeycutt. + + Math.random is really slow on windows. + + Math.random calls WTF::randomNumber which is implemented as + the secure rand_s on windows. Unfortunately rand_s is an order + of magnitude slower than arc4random. For this reason I've + added "weakRandomNumber" for use by JavaScript's Math Object. + In the long term we should look at using our own secure PRNG + in place of the system, but this will do for now. + + 30% win on SunSpider on Windows, resolving most of the remaining + disparity vs. Mac. + + * runtime/MathObject.cpp: + (JSC::MathObject::MathObject): + (JSC::mathProtoFuncRandom): + * wtf/RandomNumber.cpp: + (WTF::weakRandomNumber): + (WTF::randomNumber): + * wtf/RandomNumber.h: + * wtf/RandomNumberSeed.h: + (WTF::initializeWeakRandomNumberGenerator): + +2009-02-13 Mark Rowe <mrowe@apple.com> + + Merge r40967. + + 2009-02-12 Mark Rowe <mrowe@apple.com> + + Fix the build for other platforms. + + * wtf/RandomNumber.cpp: + (WTF::randomNumber): + +2009-02-13 Mark Rowe <mrowe@apple.com> + + Merge r40937. + + 2009-02-12 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Sam Weinig. + + Correctness fix. + + * wtf/RandomNumber.cpp: + (WTF::randomNumber): Divide by the maximum representable value, which + is different on each platform now, to get values between 0 and 1. + +2009-02-13 Mark Rowe <mrowe@apple.com> + + Merge r40935. + + 2009-02-12 Geoffrey Garen <ggaren@apple.com> + + Build fix. + + * wtf/RandomNumber.cpp: + (WTF::randomNumber): + +2009-02-13 Mark Rowe <mrowe@apple.com> + + Merge r40932. + + 2009-02-12 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Sam Weinig. + + Fixed <rdar://problem/6582048>. + + * wtf/RandomNumber.cpp: + (WTF::randomNumber): Make only one call to the random number generator + on platforms where the generator is cryptographically secure. The value + of randomness over and above cryptographically secure randomness is not + clear, and it caused some performance problems. + +2009-02-03 Mark Rowe <mrowe@apple.com> + + Merge r40522. + + 2009-02-02 Oliver Hunt <oliver@apple.com> + + Reviewed by Gavin Barraclough. + + <https://bugs.webkit.org/show_bug.cgi?id=21414> REGRESSION: Regular Expressions and character classes, shorthands and ranges + <rdar://problem/6543487> + + In certain circumstances when WREC::Generator::generateCharacterClassInvertedRange invokes + itself recursively, it will incorrectly emit (and thus consume) the next single character + match in the current character class. As WREC uses a binary search this out of sequence + codegen could result in a character match being missed and so cause the regex to produce + incorrect results. + + * wrec/WRECGenerator.cpp: + (JSC::WREC::Generator::generateCharacterClassInvertedRange): + +2009-02-03 Mark Rowe <mrowe@apple.com> + + Merge r40397. + + 2009-01-29 Stephanie Lewis <slewis@apple.com> + + RS by Oliver Hunt. + + Update the order files. + + * JavaScriptCore.order: + +2009-02-03 Mark Rowe <mrowe@apple.com> + + Merge r40396. + + 2009-01-29 Cameron Zwarich <cwzwarich@uwaterloo.ca> + + Reviewed by Oliver Hunt. + + Bug 23551: Crash on page load with profiler enabled and running + <https://bugs.webkit.org/show_bug.cgi?id=23551> + <rdar://problem/6529521> + + Interpreter::execute(FunctionBodyNode*, ...) calls Profiler::didExecute() + with a stale CallFrame. If some part of the scope chain has already been + freed, Profiler::didExecute() will crash when attempting to get the lexical + global object. The fix is to make the didExecute() call use the caller's + CallFrame, not the one made for the function call. In this case, the + willExecute() call should also be changed to match. + + Since this occurs in the actual inspector JS, it is difficult to reduce. + I couldn't make a layout test. + + * interpreter/Interpreter.cpp: + (JSC::Interpreter::execute): + +2009-02-03 Mark Rowe <mrowe@apple.com> + + Merge r40345. + + 2009-01-28 Sam Weinig <sam@webkit.org> + + Reviewed by Gavin Barraclough. + + Fix for <rdar://problem/6525537> + Hang occurs when closing Installer window (iTunes, Aperture) + + * JavaScriptCore.exp: Export JSGlobalData::sharedInstance. + +2009-02-03 Mark Rowe <mrowe@apple.com> + + Merge r40339. + + 2009-01-28 Sam Weinig <sam@webkit.org> + + Reviewed by Geoff Garen. + + Initial patch by Mark Rowe. + + <rdar://problem/6519356> + REGRESSION (r36006): "out of memory" alert running dromaeo on Windows + + Report the cost of the ArrayStorage vector more accurately/often. + + * runtime/JSArray.cpp: + (JSC::JSArray::JSArray): Report the extra cost even for a filled array + because JSString using the single character optimization and immediates + wont increase the cost themselves. + (JSC::JSArray::putSlowCase): Update the cost when increasing the size of + the array. + (JSC::JSArray::increaseVectorLength): Ditto. + +2009-02-03 Mark Rowe <mrowe@apple.com> + + Merge r40332. + + 2009-01-28 Sam Weinig <sam@webkit.org> + + Reviewed by Geoff Garen. + + Fix for <rdar://problem/6129678> + REGRESSION (Safari 3-4): Local variable not accessible from Dashcode console or variables view + + Iterating the properties of activation objects accessed through the WebKit debugging + APIs was broken by forced conversion of JSActivation to the global object. To fix this, + we use a proxy activation object that acts more like a normal JSObject. + + * debugger/DebuggerActivation.cpp: Added. + (JSC::DebuggerActivation::DebuggerActivation): + (JSC::DebuggerActivation::mark): + (JSC::DebuggerActivation::className): + (JSC::DebuggerActivation::getOwnPropertySlot): + (JSC::DebuggerActivation::put): + (JSC::DebuggerActivation::putWithAttributes): + (JSC::DebuggerActivation::deleteProperty): + (JSC::DebuggerActivation::getPropertyNames): + (JSC::DebuggerActivation::getPropertyAttributes): + (JSC::DebuggerActivation::defineGetter): + (JSC::DebuggerActivation::defineSetter): + (JSC::DebuggerActivation::lookupGetter): + (JSC::DebuggerActivation::lookupSetter): + * debugger/DebuggerActivation.h: Added. + Proxy JSActivation object for Debugging. + + * runtime/JSActivation.h: + (JSC::JSActivation::isActivationObject): Added. + * runtime/JSObject.h: + (JSC::JSObject::isActivationObject): Added. + +2009-01-26 Adele Peterson <adele@apple.com> + + Build fix. + + * debugger/Debugger.cpp: + +2009-01-26 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Darin Adler. + + Fixes for eq null & neq null, on 64-bit JIT. + https://bugs.webkit.org/show_bug.cgi?id=23559 + + This patch degrades 64-bit JIT performance on some benchmarks, + due to the whole not-being-incorrect thing. + + * jit/JIT.cpp: + (JSC::JIT::privateCompileMainPass): + +2009-01-26 Cameron Zwarich <cwzwarich@uwaterloo.ca> + + Reviewed by Gavin Barraclough. + + Bug 23552: Dashcode evaluator no longer works after making ExecStates actual call frames + <https://bugs.webkit.org/show_bug.cgi?id=23552> + <rdar://problem/6398839> + + * JavaScriptCore.exp: + * debugger/Debugger.cpp: + (JSC::evaluateInGlobalCallFrame): Added so that WebScriptCallFrame can + evaluate JS starting from a global call frame. + * debugger/Debugger.h: + +2009-01-25 Mark Rowe <mrowe@apple.com> + + Rubber-stamped by Dan Bernstein. + + Improve the consistency of settings in our .xcconfig files. + + * Configurations/Base.xcconfig: Enable GCC_OBJC_CALL_CXX_CDTORS to match other projects. + +2009-01-25 Darin Adler <darin@apple.com> + + Reviewed by Mark Rowe. + + Bug 23352: Turn on more compiler warnings in the Mac build + https://bugs.webkit.org/show_bug.cgi?id=23352 + + Turn on the following warnings: + + -Wcast-qual + -Wextra-tokens + -Wformat=2 + -Winit-self + -Wmissing-noreturn + -Wpacked + -Wrendundant-decls + + * Configurations/Base.xcconfig: Added the new warnings. Switched to -Wextra instead of + -W for clarity since we don't have to support the older versions of gcc that require the + old -W syntax. Since we now use -Wformat=2, removed -Wformat-security. Also removed + -Wno-format-y2k since we can have that one on now. + +2009-01-25 Judit Jasz <jasy@inf.u-szeged.hu> + + Reviewed by Darin Adler. + + Compilation problem fixing + http://bugs.webkit.org/show_bug.cgi?id=23497 + + * jit/JITCall.cpp: + (JSC::JIT::compileOpCall): Use JSValuePtr::encode. + +2009-01-25 Darin Adler <darin@apple.com> + + Reviewed by Sam Weinig. + + Bug 23352: Turn on more compiler warnings in the Mac build + https://bugs.webkit.org/show_bug.cgi?id=23352 + + Fourth patch: Deal with the last few stray warnings. + + * parser/Parser.cpp: Only declare jscyyparse if it's not already declared. + This makes both separate compilation and all-in-one compilation work with the + -Wredundant-decls warning. + +2009-01-25 Darin Adler <darin@apple.com> + + Reviewed by Sam Weinig. + + Bug 23352: Turn on more compiler warnings in the Mac build + https://bugs.webkit.org/show_bug.cgi?id=23352 + + Third patch: Use the noreturn attribute on functions that don't + return to prepare for the use of the -Wmissing-noreturn warning. + + * jit/JITCall.cpp: + (JSC::unreachable): Added NO_RETURN. + * jsc.cpp: + (functionQuit): Ditto. + (printUsageStatement): Ditto. + * wtf/AlwaysInline.h: Added definition of NO_RETURN. + +2009-01-24 Oliver Hunt <oliver@apple.com> + + Reviewed by Maciej Stachowiak. + + Force inlining of Lexer::matchPunctuator + + 2.2% win when parsing jQuery, Mootools, Prototype, etc + + * parser/Lexer.h: + +2009-01-23 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Geoff Garen. + + Fix for <rdar://problem/6126212> + Ensure that callbacks out from the JSC interface are only allowed + to return in reverse-chronological order to that in which they were + made. If we allow earlier callbacks to return first, then this may + result in setions of the RegisterFile in use by another thread + being trampled. + + See uber-comment in JSLock.h for details. + + * runtime/JSLock.cpp: + (JSC::JSLock::DropAllLocks::DropAllLocks): + (JSC::JSLock::DropAllLocks::~DropAllLocks): + +2009-01-23 Darin Adler <darin@apple.com> + + Try to fix WX build. + + * runtime/JSGlobalObjectFunctions.h: Include <wtf/unicode/Unicode.h> + for the definition of UChar. + +2009-01-23 Anders Carlsson <andersca@apple.com> + + * Configurations/Base.xcconfig: + GCC 4.0 build fix. + + * runtime/JSNumberCell.h: + 64-bit build fix. + +2009-01-23 Anders Carlsson <andersca@apple.com> + + Reviewed by Sam Weinig. + + Turn on -Wmissing-prototypes and fix the warnings. + + * API/JSClassRef.cpp: + (clearReferenceToPrototype): + * Configurations/Base.xcconfig: + * runtime/Collector.cpp: + (JSC::getPlatformThreadRegisters): + * runtime/ExceptionHelpers.cpp: + (JSC::createError): + * runtime/JSGlobalObjectFunctions.h: + * runtime/JSNumberCell.h: + * runtime/UString.cpp: + (JSC::initializeStaticBaseString): + (JSC::createRep): + * wtf/FastMalloc.cpp: + * wtf/Threading.cpp: + +2009-01-22 Mark Rowe <mrowe@apple.com> + + Rubber-stamped by Anders Carlsson. + + Disable GCC_WARN_ABOUT_MISSING_PROTOTYPES temporarily. + + Current versions of Xcode only respect it for C and Objective-C files, + and our code doesn't currently compile if it is applied to C++ and + Objective-C++ files. + + * Configurations/Base.xcconfig: + +2009-01-22 Steve Falkenburg <sfalken@apple.com> + + https://bugs.webkit.org/show_bug.cgi?id=23489 + + Return currentTime() in correct units for the two early return cases. + + Reviewed by Mark Rowe. + + * wtf/CurrentTime.cpp: + (WTF::currentTime): + +2009-01-22 Sam Weinig <sam@webkit.org> + + Reviewed by Mark Rowe. + + Fix for <rdar://problem/6439247> + FastMalloc allocating an extra 4MB of meta-data on 64-bit + + Rely on the fact that on all known x86-64 platforms only use 48 bits of + address space to shrink the initial size of the PageMap from ~4MB to 120K. + For 64-bit we still use a 3-level radix tree, but now each level is only 12 + bits wide. + + No performance change. + + * wtf/FastMalloc.cpp: + (WTF::MapSelector): Add specialization for 64 bit that takes into account the + 16 bits of unused address space on x86-64. + +2009-01-22 Beth Dakin <bdakin@apple.com> + + Reviewed by Sam Weinig. + + Fix for https://bugs.webkit.org/show_bug.cgi?id=23461 LayoutTests/ + fast/js/numeric-conversion.html is broken, and corresponding + <rdar://problem/6514842> + + The basic problem here is that parseInt(Infinity) should be NaN, + but we were returning 0. NaN matches Safari 3.2.1 and Firefox. + + * runtime/JSGlobalObjectFunctions.cpp: + (JSC::globalFuncParseInt): + +2009-01-22 Oliver Hunt <oliver@apple.com> + + Reviewed by Geoff Garen. + + <rdar://problem/6516853> (r39682-r39736) JSFunFuzz: crash on "(function(){({ x2: x }), })()" + <https://bugs.webkit.org/show_bug.cgi?id=23479> + + Automatic semicolon insertion was resulting in this being accepted in the initial + nodeless parsing, but subsequent reparsing for code generation would fail, leading + to a crash. The solution is to ensure that reparsing a function performs parsing + in the same state as the initial parse. We do this by modifying the saved source + ranges to include rather than exclude the opening and closing braces. + + * bytecode/CodeBlock.cpp: + (JSC::CodeBlock::reparseForExceptionInfoIfNecessary): add an assertion for successful recompile + * parser/Lexer.h: + (JSC::Lexer::sourceCode): include rather than exclude braces. + * parser/Nodes.h: + (JSC::FunctionBodyNode::toSourceString): No need to append braces anymore. + +2009-01-22 Dmitry Titov <dimich@chromium.org> + + Reviewed by Alexey Proskuryakov. + + https://bugs.webkit.org/show_bug.cgi?id=23373 + + Implement ThreadCondition::timedWait(). + Since we borrow the code for condition variables from other sources, + I did the same for timedWait(). See comments in ThreadingWin.cpp for + rationale and more info. + + * wtf/CONTRIBUTORS.pthreads-win32: + Added. A list of Pthreads-win32 contributors mentioned in their license. The license itself + is included into wtf/ThreadingWin32.cpp. + + * wtf/Threading.h: + * wtf/ThreadingWin.cpp: + Additional info and Pthreads-win32 license at the beginning. + (WTF::PlatformCondition::timedWait): new method, derived from Pthreads-win32. + (WTF::PlatformCondition::signal): same + (WTF::ThreadCondition::ThreadCondition): + (WTF::ThreadCondition::~ThreadCondition): + (WTF::ThreadCondition::wait): this now calls PlatformCondition::timedWait. + (WTF::ThreadCondition::timedWait): same + (WTF::ThreadCondition::signal): this now calls PlatformCondition::signal. + (WTF::ThreadCondition::broadcast): same + +2009-01-21 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Oliver Hunt. + + Fix for https://bugs.webkit.org/show_bug.cgi?id=23469. + + We need to check all numbers in integer switches, not just those + represented as integer JSImmediates. + + * interpreter/Interpreter.cpp: + (JSC::Interpreter::privateExecute): + (JSC::Interpreter::cti_op_switch_imm): + +2009-01-21 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Geoff Garen. + + Fix for https://bugs.webkit.org/show_bug.cgi?id=23468. + + * interpreter/Interpreter.cpp: + (JSC::Interpreter::privateExecute): + +2009-01-21 Alexey Proskuryakov <ap@webkit.org> + + Suggested by Oliver Hunt. Reviewed by Oliver Hunt. + + https://bugs.webkit.org/show_bug.cgi?id=23456 + Function argument names leak + + * parser/Nodes.cpp: (JSC::FunctionBodyNode::~FunctionBodyNode): Destruct parameter names. + +2009-01-20 Oliver Hunt <oliver@apple.com> + + Reviewed by NOBODY (Build fix). + + Windows build fix + + * JavaScriptCore.vcproj/WTF/WTF.vcproj: + +2009-01-20 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Mark Rowe. + + Structure property table deleted offset maps are being leaked. + Probably shouldn't be doing that. + + https://bugs.webkit.org/show_bug.cgi?id=23442 + + * runtime/Structure.cpp: + (JSC::Structure::~Structure): + +2009-01-20 Oliver Hunt <oliver@apple.com> + + Reviewed by NOBODY (build fix). + + Attempt to fix gtk build + + * GNUmakefile.am: + +2009-01-20 Darin Adler <darin@apple.com> + + * runtime/StringPrototype.cpp: + (JSC::substituteBackreferences): Add back the initialization to fix the build. + +2009-01-20 Darin Adler <darin@apple.com> + + Reviewed by Mark Rowe. + + Bug 23352: Turn on more compiler warnings in the Mac build + https://bugs.webkit.org/show_bug.cgi?id=23352 + + First patch: Fix some simple cases of various warnings. + + * pcre/pcre_compile.cpp: + (jsRegExpCompile): Use const_cast to change const-ness. + + * runtime/StringPrototype.cpp: + (JSC::substituteBackreferences): Remove unneeded initialization and + use UChar instead of unsigned short for UTF-16 values. + + * wtf/dtoa.cpp: + (WTF::strtod): Use const_cast to change const-ness. + +2009-01-20 Oliver Hunt <oliver@apple.com> + + Reviewed by NOBODY (build fix). + + Whoops, remove runtime/ByteArray references from .pri and .scons builds, update .bkl + + * JavaScriptCore.pri: + * JavaScriptCore.scons: + * JavaScriptCoreSources.bkl: + +2009-01-20 Oliver Hunt <oliver@apple.com> + + RS=Dan Bernstein. + + Move runtime/ByteArray to wtf/ByteArray + + * GNUmakefile.am: + * JavaScriptCore.exp: + * JavaScriptCore.pri: + * JavaScriptCore.scons: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: + * JavaScriptCore.vcproj/WTF/WTF.vcproj: + * JavaScriptCore.xcodeproj/project.pbxproj: + * runtime/JSByteArray.cpp: + * runtime/JSByteArray.h: + * wtf/ByteArray.cpp: Renamed from JavaScriptCore/runtime/ByteArray.cpp. + (WTF::ByteArray::create): + * wtf/ByteArray.h: Renamed from JavaScriptCore/runtime/ByteArray.h. + (WTF::ByteArray::length): + (WTF::ByteArray::set): + (WTF::ByteArray::get): + (WTF::ByteArray::data): + (WTF::ByteArray::deref): + (WTF::ByteArray::ByteArray): + +2009-01-19 Sam Weinig <sam@webkit.org> + + Rubber-stamped by Gavin Barraclough. + + Remove temporary operator-> from JSValuePtr. + + * API/JSCallbackFunction.cpp: + (JSC::JSCallbackFunction::call): + * API/JSCallbackObjectFunctions.h: + (JSC::::call): + (JSC::::toNumber): + (JSC::::toString): + * API/JSObjectRef.cpp: + (JSObjectSetPrototype): + * API/JSValueRef.cpp: + (JSValueGetType): + (JSValueIsUndefined): + (JSValueIsNull): + (JSValueIsBoolean): + (JSValueIsNumber): + (JSValueIsString): + (JSValueIsObject): + (JSValueIsObjectOfClass): + (JSValueToBoolean): + (JSValueToNumber): + (JSValueToStringCopy): + (JSValueToObject): + * bytecode/CodeBlock.cpp: + (JSC::valueToSourceString): + (JSC::CodeBlock::mark): + * bytecode/CodeBlock.h: + (JSC::CodeBlock::isKnownNotImmediate): + * bytecompiler/BytecodeGenerator.cpp: + (JSC::BytecodeGenerator::emitEqualityOp): + (JSC::keyForImmediateSwitch): + * interpreter/Interpreter.cpp: + (JSC::jsLess): + (JSC::jsLessEq): + (JSC::jsAddSlowCase): + (JSC::jsAdd): + (JSC::jsTypeStringForValue): + (JSC::jsIsObjectType): + (JSC::jsIsFunctionType): + (JSC::isNotObject): + (JSC::Interpreter::callEval): + (JSC::Interpreter::throwException): + (JSC::cachePrototypeChain): + (JSC::Interpreter::tryCachePutByID): + (JSC::countPrototypeChainEntriesAndCheckForProxies): + (JSC::Interpreter::tryCacheGetByID): + (JSC::Interpreter::privateExecute): + (JSC::Interpreter::tryCTICachePutByID): + (JSC::Interpreter::tryCTICacheGetByID): + (JSC::Interpreter::cti_op_convert_this): + (JSC::Interpreter::cti_op_add): + (JSC::Interpreter::cti_op_pre_inc): + (JSC::Interpreter::cti_op_put_by_id_generic): + (JSC::Interpreter::cti_op_get_by_id_generic): + (JSC::Interpreter::cti_op_put_by_id): + (JSC::Interpreter::cti_op_put_by_id_second): + (JSC::Interpreter::cti_op_put_by_id_fail): + (JSC::Interpreter::cti_op_get_by_id): + (JSC::Interpreter::cti_op_get_by_id_second): + (JSC::Interpreter::cti_op_get_by_id_self_fail): + (JSC::Interpreter::cti_op_get_by_id_proto_list): + (JSC::Interpreter::cti_op_get_by_id_proto_list_full): + (JSC::Interpreter::cti_op_get_by_id_proto_fail): + (JSC::Interpreter::cti_op_get_by_id_array_fail): + (JSC::Interpreter::cti_op_get_by_id_string_fail): + (JSC::Interpreter::cti_op_instanceof): + (JSC::Interpreter::cti_op_del_by_id): + (JSC::Interpreter::cti_op_mul): + (JSC::Interpreter::cti_op_call_JSFunction): + (JSC::Interpreter::cti_op_call_NotJSFunction): + (JSC::Interpreter::cti_op_construct_JSConstruct): + (JSC::Interpreter::cti_op_construct_NotJSConstruct): + (JSC::Interpreter::cti_op_get_by_val): + (JSC::Interpreter::cti_op_get_by_val_byte_array): + (JSC::Interpreter::cti_op_sub): + (JSC::Interpreter::cti_op_put_by_val): + (JSC::Interpreter::cti_op_put_by_val_array): + (JSC::Interpreter::cti_op_put_by_val_byte_array): + (JSC::Interpreter::cti_op_loop_if_true): + (JSC::Interpreter::cti_op_negate): + (JSC::Interpreter::cti_op_div): + (JSC::Interpreter::cti_op_pre_dec): + (JSC::Interpreter::cti_op_not): + (JSC::Interpreter::cti_op_jtrue): + (JSC::Interpreter::cti_op_post_inc): + (JSC::Interpreter::cti_op_lshift): + (JSC::Interpreter::cti_op_bitand): + (JSC::Interpreter::cti_op_rshift): + (JSC::Interpreter::cti_op_bitnot): + (JSC::Interpreter::cti_op_mod): + (JSC::Interpreter::cti_op_post_dec): + (JSC::Interpreter::cti_op_urshift): + (JSC::Interpreter::cti_op_bitxor): + (JSC::Interpreter::cti_op_bitor): + (JSC::Interpreter::cti_op_push_scope): + (JSC::Interpreter::cti_op_is_undefined): + (JSC::Interpreter::cti_op_is_boolean): + (JSC::Interpreter::cti_op_is_number): + (JSC::Interpreter::cti_op_to_jsnumber): + (JSC::Interpreter::cti_op_in): + (JSC::Interpreter::cti_op_put_by_index): + (JSC::Interpreter::cti_op_switch_imm): + (JSC::Interpreter::cti_op_switch_char): + (JSC::Interpreter::cti_op_switch_string): + (JSC::Interpreter::cti_op_del_by_val): + (JSC::Interpreter::cti_op_put_getter): + (JSC::Interpreter::cti_op_put_setter): + (JSC::Interpreter::cti_op_new_error): + * interpreter/Interpreter.h: + (JSC::Interpreter::isJSArray): + (JSC::Interpreter::isJSString): + (JSC::Interpreter::isJSByteArray): + * interpreter/Register.h: + (JSC::Register::marked): + (JSC::Register::mark): + * jit/JITInlineMethods.h: + (JSC::JIT::getConstantOperandImmediateInt): + (JSC::JIT::isOperandConstantImmediateInt): + * jsc.cpp: + (functionPrint): + (functionDebug): + (functionRun): + (functionLoad): + (runWithScripts): + (runInteractive): + * parser/Nodes.cpp: + (JSC::processClauseList): + * profiler/ProfileGenerator.cpp: + (JSC::ProfileGenerator::addParentForConsoleStart): + * profiler/Profiler.cpp: + (JSC::Profiler::createCallIdentifier): + * runtime/ArrayConstructor.cpp: + (JSC::constructArrayWithSizeQuirk): + * runtime/ArrayPrototype.cpp: + (JSC::arrayProtoFuncToString): + (JSC::arrayProtoFuncToLocaleString): + (JSC::arrayProtoFuncJoin): + (JSC::arrayProtoFuncConcat): + (JSC::arrayProtoFuncPop): + (JSC::arrayProtoFuncPush): + (JSC::arrayProtoFuncReverse): + (JSC::arrayProtoFuncShift): + (JSC::arrayProtoFuncSlice): + (JSC::arrayProtoFuncSort): + (JSC::arrayProtoFuncSplice): + (JSC::arrayProtoFuncUnShift): + (JSC::arrayProtoFuncFilter): + (JSC::arrayProtoFuncMap): + (JSC::arrayProtoFuncEvery): + (JSC::arrayProtoFuncForEach): + (JSC::arrayProtoFuncSome): + (JSC::arrayProtoFuncIndexOf): + (JSC::arrayProtoFuncLastIndexOf): + * runtime/BooleanConstructor.cpp: + (JSC::constructBoolean): + (JSC::callBooleanConstructor): + * runtime/BooleanPrototype.cpp: + (JSC::booleanProtoFuncToString): + (JSC::booleanProtoFuncValueOf): + * runtime/Collector.cpp: + (JSC::Heap::protect): + (JSC::Heap::unprotect): + (JSC::Heap::heap): + (JSC::Heap::collect): + (JSC::typeName): + * runtime/Completion.cpp: + (JSC::evaluate): + * runtime/DateConstructor.cpp: + (JSC::constructDate): + (JSC::dateParse): + (JSC::dateUTC): + * runtime/DateInstance.h: + (JSC::DateInstance::internalNumber): + * runtime/DatePrototype.cpp: + (JSC::formatLocaleDate): + (JSC::fillStructuresUsingTimeArgs): + (JSC::fillStructuresUsingDateArgs): + (JSC::dateProtoFuncToString): + (JSC::dateProtoFuncToUTCString): + (JSC::dateProtoFuncToDateString): + (JSC::dateProtoFuncToTimeString): + (JSC::dateProtoFuncToLocaleString): + (JSC::dateProtoFuncToLocaleDateString): + (JSC::dateProtoFuncToLocaleTimeString): + (JSC::dateProtoFuncGetTime): + (JSC::dateProtoFuncGetFullYear): + (JSC::dateProtoFuncGetUTCFullYear): + (JSC::dateProtoFuncToGMTString): + (JSC::dateProtoFuncGetMonth): + (JSC::dateProtoFuncGetUTCMonth): + (JSC::dateProtoFuncGetDate): + (JSC::dateProtoFuncGetUTCDate): + (JSC::dateProtoFuncGetDay): + (JSC::dateProtoFuncGetUTCDay): + (JSC::dateProtoFuncGetHours): + (JSC::dateProtoFuncGetUTCHours): + (JSC::dateProtoFuncGetMinutes): + (JSC::dateProtoFuncGetUTCMinutes): + (JSC::dateProtoFuncGetSeconds): + (JSC::dateProtoFuncGetUTCSeconds): + (JSC::dateProtoFuncGetMilliSeconds): + (JSC::dateProtoFuncGetUTCMilliseconds): + (JSC::dateProtoFuncGetTimezoneOffset): + (JSC::dateProtoFuncSetTime): + (JSC::setNewValueFromTimeArgs): + (JSC::setNewValueFromDateArgs): + (JSC::dateProtoFuncSetYear): + (JSC::dateProtoFuncGetYear): + * runtime/ErrorConstructor.cpp: + (JSC::constructError): + * runtime/ErrorPrototype.cpp: + (JSC::errorProtoFuncToString): + * runtime/ExceptionHelpers.cpp: + (JSC::createError): + (JSC::createErrorMessage): + * runtime/FunctionConstructor.cpp: + (JSC::constructFunction): + * runtime/FunctionPrototype.cpp: + (JSC::functionProtoFuncToString): + (JSC::functionProtoFuncApply): + (JSC::functionProtoFuncCall): + * runtime/GetterSetter.cpp: + (JSC::GetterSetter::toObject): + * runtime/JSActivation.cpp: + (JSC::JSActivation::getOwnPropertySlot): + * runtime/JSArray.cpp: + (JSC::JSArray::put): + (JSC::JSArray::mark): + (JSC::JSArray::sort): + (JSC::AVLTreeAbstractorForArrayCompare::compare_key_key): + (JSC::JSArray::compactForSorting): + * runtime/JSByteArray.h: + (JSC::JSByteArray::setIndex): + * runtime/JSCell.h: + (JSC::asCell): + * runtime/JSFunction.cpp: + (JSC::JSFunction::call): + (JSC::JSFunction::construct): + * runtime/JSGlobalObject.cpp: + (JSC::markIfNeeded): + (JSC::lastInPrototypeChain): + * runtime/JSGlobalObjectFunctions.cpp: + (JSC::encode): + (JSC::decode): + (JSC::globalFuncEval): + (JSC::globalFuncParseInt): + (JSC::globalFuncParseFloat): + (JSC::globalFuncIsNaN): + (JSC::globalFuncIsFinite): + (JSC::globalFuncEscape): + (JSC::globalFuncUnescape): + (JSC::globalFuncJSCPrint): + * runtime/JSImmediate.cpp: + (JSC::JSImmediate::toThisObject): + (JSC::JSImmediate::toObject): + (JSC::JSImmediate::prototype): + (JSC::JSImmediate::toString): + * runtime/JSImmediate.h: + * runtime/JSObject.cpp: + (JSC::JSObject::mark): + (JSC::JSObject::put): + (JSC::callDefaultValueFunction): + (JSC::JSObject::getPrimitiveNumber): + (JSC::JSObject::defineGetter): + (JSC::JSObject::defineSetter): + (JSC::JSObject::lookupGetter): + (JSC::JSObject::lookupSetter): + (JSC::JSObject::hasInstance): + (JSC::JSObject::toNumber): + (JSC::JSObject::toString): + * runtime/JSObject.h: + (JSC::JSObject::JSObject): + (JSC::JSObject::inlineGetOwnPropertySlot): + (JSC::JSObject::getOwnPropertySlotForWrite): + (JSC::JSObject::getPropertySlot): + (JSC::JSValuePtr::get): + * runtime/JSPropertyNameIterator.h: + (JSC::JSPropertyNameIterator::create): + * runtime/JSString.cpp: + (JSC::JSString::getOwnPropertySlot): + * runtime/JSValue.h: + * runtime/JSWrapperObject.cpp: + (JSC::JSWrapperObject::mark): + * runtime/JSWrapperObject.h: + (JSC::JSWrapperObject::setInternalValue): + * runtime/MathObject.cpp: + (JSC::mathProtoFuncAbs): + (JSC::mathProtoFuncACos): + (JSC::mathProtoFuncASin): + (JSC::mathProtoFuncATan): + (JSC::mathProtoFuncATan2): + (JSC::mathProtoFuncCeil): + (JSC::mathProtoFuncCos): + (JSC::mathProtoFuncExp): + (JSC::mathProtoFuncFloor): + (JSC::mathProtoFuncLog): + (JSC::mathProtoFuncMax): + (JSC::mathProtoFuncMin): + (JSC::mathProtoFuncPow): + (JSC::mathProtoFuncRound): + (JSC::mathProtoFuncSin): + (JSC::mathProtoFuncSqrt): + (JSC::mathProtoFuncTan): + * runtime/NativeErrorConstructor.cpp: + (JSC::NativeErrorConstructor::NativeErrorConstructor): + (JSC::NativeErrorConstructor::construct): + * runtime/NumberConstructor.cpp: + (JSC::constructWithNumberConstructor): + (JSC::callNumberConstructor): + * runtime/NumberPrototype.cpp: + (JSC::numberProtoFuncToString): + (JSC::numberProtoFuncToLocaleString): + (JSC::numberProtoFuncValueOf): + (JSC::numberProtoFuncToFixed): + (JSC::numberProtoFuncToExponential): + (JSC::numberProtoFuncToPrecision): + * runtime/ObjectConstructor.cpp: + (JSC::constructObject): + * runtime/ObjectPrototype.cpp: + (JSC::objectProtoFuncValueOf): + (JSC::objectProtoFuncHasOwnProperty): + (JSC::objectProtoFuncIsPrototypeOf): + (JSC::objectProtoFuncDefineGetter): + (JSC::objectProtoFuncDefineSetter): + (JSC::objectProtoFuncLookupGetter): + (JSC::objectProtoFuncLookupSetter): + (JSC::objectProtoFuncPropertyIsEnumerable): + (JSC::objectProtoFuncToLocaleString): + (JSC::objectProtoFuncToString): + * runtime/Operations.h: + (JSC::JSValuePtr::equalSlowCaseInline): + (JSC::JSValuePtr::strictEqual): + (JSC::JSValuePtr::strictEqualSlowCaseInline): + * runtime/Protect.h: + (JSC::gcProtect): + (JSC::gcUnprotect): + * runtime/RegExpConstructor.cpp: + (JSC::setRegExpConstructorInput): + (JSC::setRegExpConstructorMultiline): + (JSC::constructRegExp): + * runtime/RegExpObject.cpp: + (JSC::setRegExpObjectLastIndex): + (JSC::RegExpObject::match): + * runtime/RegExpPrototype.cpp: + (JSC::regExpProtoFuncTest): + (JSC::regExpProtoFuncExec): + (JSC::regExpProtoFuncCompile): + (JSC::regExpProtoFuncToString): + * runtime/StringConstructor.cpp: + (JSC::stringFromCharCodeSlowCase): + (JSC::stringFromCharCode): + (JSC::constructWithStringConstructor): + (JSC::callStringConstructor): + * runtime/StringPrototype.cpp: + (JSC::stringProtoFuncReplace): + (JSC::stringProtoFuncToString): + (JSC::stringProtoFuncCharAt): + (JSC::stringProtoFuncCharCodeAt): + (JSC::stringProtoFuncConcat): + (JSC::stringProtoFuncIndexOf): + (JSC::stringProtoFuncLastIndexOf): + (JSC::stringProtoFuncMatch): + (JSC::stringProtoFuncSearch): + (JSC::stringProtoFuncSlice): + (JSC::stringProtoFuncSplit): + (JSC::stringProtoFuncSubstr): + (JSC::stringProtoFuncSubstring): + (JSC::stringProtoFuncToLowerCase): + (JSC::stringProtoFuncToUpperCase): + (JSC::stringProtoFuncLocaleCompare): + (JSC::stringProtoFuncBig): + (JSC::stringProtoFuncSmall): + (JSC::stringProtoFuncBlink): + (JSC::stringProtoFuncBold): + (JSC::stringProtoFuncFixed): + (JSC::stringProtoFuncItalics): + (JSC::stringProtoFuncStrike): + (JSC::stringProtoFuncSub): + (JSC::stringProtoFuncSup): + (JSC::stringProtoFuncFontcolor): + (JSC::stringProtoFuncFontsize): + (JSC::stringProtoFuncAnchor): + (JSC::stringProtoFuncLink): + * runtime/Structure.cpp: + (JSC::Structure::Structure): + (JSC::Structure::getEnumerablePropertyNames): + (JSC::Structure::createCachedPrototypeChain): + * runtime/Structure.h: + (JSC::Structure::mark): + * runtime/StructureChain.cpp: + (JSC::StructureChain::StructureChain): + +2009-01-19 Darin Adler <darin@apple.com> + + Reviewed by Sam Weinig. + + Bug 23409: REGRESSION: RegExp 'replace()' function improperly processes '$$' + <https://bugs.webkit.org/show_bug.cgi?id=23409> + <rdar://problem/6505723> + + Test: fast/js/string-replace-3.html + + * runtime/StringPrototype.cpp: + (JSC::substituteBackreferences): Remove code that adds an extra $ -- not sure + how this ever worked. + +2009-01-16 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Oliver Hunt. + + On x86-64 jit, cache JSImmedate::TagMask & JSImmedate::TagTypeNumber in + registers, save reloading them every time they're used. + + Draws x86-64 jit performance close to that of i386 jit. + + * assembler/MacroAssembler.h: + (JSC::MacroAssembler::subPtr): + (JSC::MacroAssembler::jnzPtr): + (JSC::MacroAssembler::jzPtr): + * jit/JIT.cpp: + (JSC::JIT::privateCompileMainPass): + * jit/JIT.h: + * jit/JITArithmetic.cpp: + (JSC::JIT::compileBinaryArithOpSlowCase): + * jit/JITInlineMethods.h: + (JSC::JIT::emitJumpIfJSCell): + (JSC::JIT::emitJumpIfNotJSCell): + (JSC::JIT::emitJumpIfImmediateNumber): + (JSC::JIT::emitJumpIfNotImmediateNumber): + (JSC::JIT::emitJumpIfImmediateInteger): + (JSC::JIT::emitJumpIfNotImmediateInteger): + (JSC::JIT::emitFastArithIntToImmNoCheck): + +2009-01-16 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Oliver Hunt. + + Add support to x86-64 JIT for inline double precision arithmetic ops. + +5/6% on x86-64, JIT enabled, sunspider. + + * assembler/MacroAssembler.h: + (JSC::MacroAssembler::addPtr): + * assembler/X86Assembler.h: + (JSC::X86Assembler::movq_rr): + * jit/JIT.h: + * jit/JITArithmetic.cpp: + (JSC::JIT::compileFastArith_op_pre_inc): + (JSC::JIT::compileBinaryArithOp): + (JSC::JIT::compileBinaryArithOpSlowCase): + (JSC::JIT::compileFastArith_op_add): + (JSC::JIT::compileFastArithSlow_op_add): + (JSC::JIT::compileFastArith_op_mul): + (JSC::JIT::compileFastArithSlow_op_mul): + (JSC::JIT::compileFastArith_op_sub): + (JSC::JIT::compileFastArithSlow_op_sub): + * parser/ResultType.h: + (JSC::ResultType::isReusable): + (JSC::ResultType::isInt32): + (JSC::ResultType::definitelyIsNumber): + (JSC::ResultType::mightBeNumber): + (JSC::ResultType::isNotNumber): + (JSC::ResultType::unknownType): + +2009-01-16 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Geoff Garen. + + Fixes for SamplingTool. + + https://bugs.webkit.org/show_bug.cgi?id=23390 + + * assembler/MacroAssembler.h: + (JSC::MacroAssembler::storePtr): + * bytecode/SamplingTool.cpp: + (JSC::SamplingTool::run): + (JSC::SamplingTool::dump): + * bytecode/SamplingTool.h: + (JSC::SamplingTool::encodeSample): + * jit/JIT.cpp: + (JSC::JIT::privateCompileMainPass): + (JSC::JIT::privateCompile): + * jit/JIT.h: + (JSC::JIT::samplingToolTrackCodeBlock): + * jit/JITCall.cpp: + (JSC::JIT::compileOpCall): + (JSC::JIT::compileOpCallSlowCase): + * jit/JITInlineMethods.h: + (JSC::JIT::emitCTICall_internal): + +2009-01-16 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Darin Adler. + + Fixed <rdar://problem/6452301> REGRESSION: Latest WebKit nightlies + turn "c" into "" when stripping \\c_ character + + * wrec/WRECParser.cpp: + (JSC::WREC::Parser::consumeEscape): Mimic a Firefox quirk when parsing + control escapes inside character classes. + +2009-01-16 Adam Roben <aroben@apple.com> + + Windows build fix + + * wrec/WRECParser.cpp: + (JSC::WREC::Parser::parseParentheses): Removed unreachable code. + +2009-01-15 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Cameron Zwarich. + + Fixed <rdar://problem/6471394> REGRESSION (r39164): Discarding quantifier + on assertion gives incorrect result (23075) + + https://bugs.webkit.org/show_bug.cgi?id=23075 + + * pcre/pcre_compile.cpp: + (compileBranch): Throw away an assertion if it's followed by a quantifier + with a 0 minimum, to match SpiderMonkey, v8, and the ECMA spec. + + * wrec/WRECParser.cpp: + (JSC::WREC::Parser::parseParentheses): Fall back on PCRE for the rare + case of an assertion with a quantifier with a 0 minimum, since we + don't handle quantified subexpressions yet, and in this special case, + we can't just throw away the quantifier. + +2009-01-15 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Oliver Hunt. + + Add support in ResultType to track that the results of bitops + are always of type int32_t. + + * parser/Nodes.cpp: + (JSC::ReadModifyResolveNode::emitBytecode): + (JSC::ReadModifyDotNode::emitBytecode): + (JSC::ReadModifyBracketNode::emitBytecode): + * parser/Nodes.h: + (JSC::ExpressionNode::): + (JSC::BooleanNode::): + (JSC::NumberNode::): + (JSC::StringNode::): + (JSC::PrePostResolveNode::): + (JSC::TypeOfResolveNode::): + (JSC::TypeOfValueNode::): + (JSC::UnaryPlusNode::): + (JSC::NegateNode::): + (JSC::BitwiseNotNode::): + (JSC::LogicalNotNode::): + (JSC::MultNode::): + (JSC::DivNode::): + (JSC::ModNode::): + (JSC::SubNode::): + (JSC::LeftShiftNode::): + (JSC::RightShiftNode::): + (JSC::UnsignedRightShiftNode::): + (JSC::LessNode::): + (JSC::GreaterNode::): + (JSC::LessEqNode::): + (JSC::GreaterEqNode::): + (JSC::InstanceOfNode::): + (JSC::EqualNode::): + (JSC::NotEqualNode::): + (JSC::StrictEqualNode::): + (JSC::NotStrictEqualNode::): + (JSC::BitAndNode::): + (JSC::BitOrNode::): + (JSC::BitXOrNode::): + (JSC::LogicalOpNode::): + * parser/ResultType.h: + (JSC::ResultType::isInt32): + (JSC::ResultType::isNotNumber): + (JSC::ResultType::booleanType): + (JSC::ResultType::numberType): + (JSC::ResultType::numberTypeCanReuse): + (JSC::ResultType::numberTypeCanReuseIsInt32): + (JSC::ResultType::stringOrNumberTypeCanReuse): + (JSC::ResultType::stringType): + (JSC::ResultType::unknownType): + (JSC::ResultType::forAdd): + (JSC::ResultType::forBitOp): + (JSC::OperandTypes::OperandTypes): + +2009-01-15 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Oliver Hunt. + + Add support for integer addition, subtraction and multiplication + in JIT code on x86-64. + + * assembler/MacroAssembler.h: + (JSC::MacroAssembler::mul32): + (JSC::MacroAssembler::sub32): + (JSC::MacroAssembler::joMul32): + (JSC::MacroAssembler::joSub32): + * jit/JIT.cpp: + (JSC::JIT::privateCompileMainPass): + (JSC::JIT::privateCompileSlowCases): + * jit/JIT.h: + * jit/JITArithmetic.cpp: + (JSC::JIT::compileFastArith_op_add): + (JSC::JIT::compileFastArithSlow_op_add): + (JSC::JIT::compileFastArith_op_mul): + (JSC::JIT::compileFastArithSlow_op_mul): + (JSC::JIT::compileFastArith_op_sub): + (JSC::JIT::compileFastArithSlow_op_sub): + +2009-01-15 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Geoff Garen. + + On x86-64 allow JSImmediate to encode 64-bit double precision values. + This patch only affects builds that set USE(ALTERNATE_JSIMMEDIATE). + Updates the implementation of JSValuePtr:: and JSImmediate:: methods + that operate on neumeric values to be be aware of the new representation. + When this representation is in use, the class JSNumberCell is redundant + and is compiled out. + + The format of the new immediate representation is documented in JSImmediate.h. + + * JavaScriptCore.exp: + * assembler/MacroAssembler.h: + (JSC::MacroAssembler::subPtr): + * assembler/X86Assembler.h: + (JSC::X86Assembler::): + (JSC::X86Assembler::subq_rr): + (JSC::X86Assembler::movq_rr): + (JSC::X86Assembler::ucomisd_rr): + (JSC::X86Assembler::X86InstructionFormatter::twoByteOp64): + * interpreter/Interpreter.cpp: + (JSC::Interpreter::cti_op_stricteq): + (JSC::Interpreter::cti_op_nstricteq): + * jit/JIT.cpp: + (JSC::JIT::compileOpStrictEq): + (JSC::JIT::privateCompileMainPass): + (JSC::JIT::privateCompileSlowCases): + * jit/JIT.h: + * jit/JITArithmetic.cpp: + (JSC::JIT::compileFastArith_op_lshift): + (JSC::JIT::compileFastArith_op_rshift): + (JSC::JIT::compileFastArith_op_bitand): + (JSC::JIT::compileFastArith_op_mod): + (JSC::JIT::compileFastArith_op_add): + (JSC::JIT::compileFastArith_op_mul): + (JSC::JIT::compileFastArith_op_post_inc): + (JSC::JIT::compileFastArith_op_post_dec): + (JSC::JIT::compileFastArith_op_pre_inc): + (JSC::JIT::compileFastArith_op_pre_dec): + (JSC::JIT::putDoubleResultToJSNumberCellOrJSImmediate): + (JSC::JIT::compileBinaryArithOp): + * jit/JITInlineMethods.h: + (JSC::JIT::emitJumpIfBothJSCells): + (JSC::JIT::emitJumpIfEitherNumber): + (JSC::JIT::emitJumpIfNotEitherNumber): + (JSC::JIT::emitJumpIfImmediateIntegerNumber): + (JSC::JIT::emitJumpIfNotImmediateIntegerNumber): + (JSC::JIT::emitJumpIfNotImmediateIntegerNumbers): + (JSC::JIT::emitJumpSlowCaseIfNotImmediateIntegerNumber): + (JSC::JIT::emitJumpSlowCaseIfNotImmediateIntegerNumbers): + (JSC::JIT::emitFastArithDeTagImmediate): + (JSC::JIT::emitFastArithDeTagImmediateJumpIfZero): + (JSC::JIT::emitFastArithReTagImmediate): + (JSC::JIT::emitFastArithIntToImmNoCheck): + * runtime/JSCell.h: + * runtime/JSGlobalData.cpp: + (JSC::JSGlobalData::JSGlobalData): + * runtime/JSImmediate.cpp: + (JSC::JSImmediate::toThisObject): + (JSC::JSImmediate::toObject): + (JSC::JSImmediate::toString): + * runtime/JSImmediate.h: + (JSC::wtf_reinterpret_cast): + (JSC::JSImmediate::isNumber): + (JSC::JSImmediate::isIntegerNumber): + (JSC::JSImmediate::isDoubleNumber): + (JSC::JSImmediate::isPositiveIntegerNumber): + (JSC::JSImmediate::areBothImmediateIntegerNumbers): + (JSC::JSImmediate::makeInt): + (JSC::JSImmediate::makeDouble): + (JSC::JSImmediate::doubleValue): + (JSC::doubleToBoolean): + (JSC::JSImmediate::toBoolean): + (JSC::JSImmediate::getTruncatedUInt32): + (JSC::JSImmediate::makeOutOfIntegerRange): + (JSC::JSImmediate::from): + (JSC::JSImmediate::getTruncatedInt32): + (JSC::JSImmediate::toDouble): + (JSC::JSImmediate::getUInt32): + (JSC::JSValuePtr::isInt32Fast): + (JSC::JSValuePtr::isUInt32Fast): + (JSC::JSValuePtr::areBothInt32Fast): + (JSC::JSFastMath::canDoFastBitwiseOperations): + (JSC::JSFastMath::xorImmediateNumbers): + (JSC::JSFastMath::canDoFastRshift): + (JSC::JSFastMath::canDoFastUrshift): + (JSC::JSFastMath::rightShiftImmediateNumbers): + (JSC::JSFastMath::canDoFastAdditiveOperations): + (JSC::JSFastMath::addImmediateNumbers): + (JSC::JSFastMath::subImmediateNumbers): + * runtime/JSNumberCell.cpp: + (JSC::jsNumberCell): + * runtime/JSNumberCell.h: + (JSC::createNumberStructure): + (JSC::isNumberCell): + (JSC::asNumberCell): + (JSC::jsNumber): + (JSC::JSValuePtr::isDoubleNumber): + (JSC::JSValuePtr::getDoubleNumber): + (JSC::JSValuePtr::isNumber): + (JSC::JSValuePtr::uncheckedGetNumber): + (JSC::jsNaN): + (JSC::JSValuePtr::getNumber): + (JSC::JSValuePtr::numberToInt32): + (JSC::JSValuePtr::numberToUInt32): + * runtime/JSValue.h: + * runtime/NumberConstructor.cpp: + (JSC::numberConstructorNegInfinity): + (JSC::numberConstructorPosInfinity): + (JSC::numberConstructorMaxValue): + (JSC::numberConstructorMinValue): + * runtime/NumberObject.cpp: + (JSC::constructNumber): + * runtime/NumberObject.h: + * runtime/Operations.h: + (JSC::JSValuePtr::equal): + (JSC::JSValuePtr::equalSlowCaseInline): + (JSC::JSValuePtr::strictEqual): + (JSC::JSValuePtr::strictEqualSlowCaseInline): + * wtf/Platform.h: + +2009-01-15 Sam Weinig <sam@webkit.org> + + Reviewed by Geoffrey Garen. + + <rdar://problem/6045018> + REGRESSION (r34838): JavaScript objects appear to be leaked after loading google.com + + Subtract the number of JSStrings cached in SmallStrings when calculating the + number of live JSObjects. + + * runtime/Collector.cpp: + (JSC::Heap::objectCount): + * runtime/SmallStrings.cpp: + (JSC::SmallStrings::count): + * runtime/SmallStrings.h: + +2009-01-15 Sam Weinig <sam@webkit.org> + + Fix Qt build. + + * runtime/Collector.cpp: + +2009-01-15 Sam Weinig <sam@webkit.org> + + Reviewed by Gavin Barraclough. + + Fix crash seen running fast/canvas. + + Make sure to mark the ScopeNode and CodeBlock being created + in the re-parse for exception information. + + * bytecode/CodeBlock.cpp: + (JSC::CodeBlock::reparseForExceptionInfoIfNecessary): + * parser/Nodes.h: + (JSC::ScopeNode::mark): + * runtime/Collector.cpp: + (JSC::Heap::collect): + * runtime/JSGlobalData.cpp: + (JSC::JSGlobalData::JSGlobalData): + * runtime/JSGlobalData.h: + +2009-01-15 Craig Schlenter <craig.schlenter@gmail.com> + + Reviewed by Darin Adler. + + https://bugs.webkit.org/show_bug.cgi?id=23347 + Compilation of JavaScriptCore/wtf/ThreadingPthreads.cpp fails on Linux + + * wtf/ThreadingPthreads.cpp: included limits.h as INT_MAX is defined there. + +2009-01-15 Oliver Hunt <oliver@apple.com> + + Reviewed by Geoff Garen. + + Bug 23225: REGRESSION: Assertion failure in reparseInPlace() (m_sourceElements) at sfgate.com + <https://bugs.webkit.org/show_bug.cgi?id=23225> <rdar://problem/6487432> + + Character position for open and closing brace was incorrectly referencing m_position to + record their position in a source document, however this is unsafe as BOMs may lead to + m_position being an arbitrary position from the real position of the current character. + + * parser/Lexer.cpp: + (JSC::Lexer::matchPunctuator): + +2009-01-14 David Kilzer <ddkilzer@apple.com> + + Bug 23153: JSC build always touches JavaScriptCore/docs/bytecode.html + + <https://bugs.webkit.org/show_bug.cgi?id=23153> + + Reviewed by Darin Adler. + + Instead of building bytecode.html into ${SRCROOT}/docs/bytecode.html, build it + into ${BUILT_PRODUCTS_DIR}/DerivedSources/JavaScriptCore/docs/bytecode.html. + + Also fixes make-bytecode-docs.pl to actually generate documentation. + + * DerivedSources.make: Changed bytecode.html to be built into local docs + directory in ${BUILT_PRODUCTS_DIR}/DerivedSources/JavaScriptCore. + * JavaScriptCore.xcodeproj/project.pbxproj: Added "/docs" to the end of the + "mkdir -p" command so that the docs subdirectory is automatically created. + * docs/make-bytecode-docs.pl: Changed BEGIN_OPCODE to DEFINE_OPCODE so that + documentation is actually generated. + +2009-01-14 Adam Treat <adam.treat@torchmobile.com> + + Build fix for Qt from Dmitry Titov. + + * wtf/ThreadingQt.cpp: + (WTF::ThreadCondition::timedWait): + +2009-01-14 Oliver Hunt <oliver@apple.com> + + Reviewed by Cameron Zwarich. + + Bug 22903: REGRESSION (r36267): visiting this site reliably crashes WebKit nightly + + EvalCodeBlock's do not reference the functions that are declared inside the eval + code, this means that simply marking the EvalCodeBlock through the global object + is insufficient to mark the declared functions. This patch corrects this by + explicitly marking the CodeBlocks of all the functions declared in the cached + EvalNode. + + * bytecode/CodeBlock.cpp: + (JSC::CodeBlock::mark): + * bytecode/CodeBlock.h: + (JSC::CodeBlock::hasFunctions): + * bytecode/EvalCodeCache.h: + (JSC::EvalCodeCache::mark): + * parser/Nodes.cpp: + (JSC::ScopeNodeData::mark): + (JSC::EvalNode::mark): + * parser/Nodes.h: + +2009-01-14 Dmitry Titov <dimich@chromium.org> + + Reviewed by Alexey Proskuryakov. + + https://bugs.webkit.org/show_bug.cgi?id=23312 + Implement MessageQueue::waitForMessageTimed() + Also fixed ThreadCondition::timedWait() to take absolute time, as discussed on webkit-dev. + Win32 version of timedWait still has to be implemented. + + * wtf/MessageQueue.h: + (WTF::MessageQueueWaitResult: new enum for the result of MessageQueue::waitForMessageTimed. + (WTF::MessageQueue::waitForMessage): + (WTF::MessageQueue::waitForMessageTimed): New method. + * wtf/Threading.h: + * wtf/ThreadingGtk.cpp: + (WTF::ThreadCondition::timedWait): changed to use absolute time instead of interval. + * wtf/ThreadingNone.cpp: + (WTF::ThreadCondition::timedWait): ditto. + * wtf/ThreadingPthreads.cpp: + (WTF::ThreadCondition::timedWait): ditto. + * wtf/ThreadingQt.cpp: + (WTF::ThreadCondition::timedWait): ditto. + * wtf/ThreadingWin.cpp: + (WTF::ThreadCondition::timedWait): ditto. The actual Win32 code is still to be implemented. + +2009-01-14 Dean McNamee <deanm@chromium.org> + + Reviewed by Darin Adler and Oliver hunt. + + Correctly match allocation functions by implementing a custom deref(). + + https://bugs.webkit.org/show_bug.cgi?id=23315 + + * runtime/ByteArray.h: + (JSC::ByteArray::deref): + (JSC::ByteArray::ByteArray): + +2009-01-14 Dan Bernstein <mitz@apple.com> + + Reviewed by John Sullivan. + + - update copyright + + * Info.plist: + +2009-01-13 Beth Dakin <bdakin@apple.com> + + Reviewed by Darin Adler and Oliver Hunt. + + <rdar://problem/6489314> REGRESSION: Business widget's front side + fails to render correctly when flipping widget + + The problem here is that parseInt was parsing NaN as 0. This patch + corrects that by parsing NaN as NaN. This matches our old behavior + and Firefox. + + * runtime/JSGlobalObjectFunctions.cpp: + (JSC::globalFuncParseInt): + +2009-01-13 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Oliver Hunt. + + Fix for: https://bugs.webkit.org/show_bug.cgi?id=23292 + + Implementation of two argument canDoFastAdditiveOperations does not correlate well with reality. + + * runtime/JSImmediate.h: + (JSC::JSFastMath::canDoFastAdditiveOperations): + +2009-01-13 Zalan Bujtas <zbujtas@gmail.com> + + Reviewed by Darin Adler. + + https://bugs.webkit.org/show_bug.cgi?id=23290 + Fix JSImmediate::isImmediate(src) to !src->isCell() + + * interpreter/Interpreter.cpp: + (JSC::Interpreter::privateExecute): + +2009-01-13 Dmitry Titov <dimich@chromium.org> + + Reviewed by Darin Adler. + + https://bugs.webkit.org/show_bug.cgi?id=23281 + Fix the Chromium Win build. + Need to use PLATFORM(WIN_OS) instead of PLATFORM(WIN). + Moved GTK and WX up in #if sequence because they could come with WIN_OS too, + while they have their own implementation even on Windows. + + * wtf/CurrentTime.cpp: + (WTF::currentTime): + +2009-01-12 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Oliver Hunt. + + Make the JSImmediate interface private. + + All manipulation of JS values should be through the JSValuePtr class, not by using JSImmediate + directly. The key missing methods on JSValuePtr are: + + * isCell() - check for values that are JSCell*s, and as such where asCell() may be used. + * isInt32Fast() getInt32Fast() - fast check/access for integer immediates. + * isUInt32Fast() getUInt32Fast() - ditto for unsigned integer immediates. + + The JIT is allowed full access to JSImmediate, since it needs to be able to directly + manipulate JSValuePtrs. The Interpreter is provided access to perform operations directly + on JSValuePtrs through the new JSFastMath interface. + + No performance impact. + + * API/JSCallbackObjectFunctions.h: + (JSC::::toNumber): + * API/JSValueRef.cpp: + (JSValueIsEqual): + (JSValueIsStrictEqual): + * JavaScriptCore.exp: + * bytecode/CodeBlock.h: + (JSC::CodeBlock::isKnownNotImmediate): + * bytecompiler/BytecodeGenerator.cpp: + (JSC::keyForImmediateSwitch): + * bytecompiler/BytecodeGenerator.h: + (JSC::BytecodeGenerator::JSValueHashTraits::constructDeletedValue): + (JSC::BytecodeGenerator::JSValueHashTraits::isDeletedValue): + * interpreter/Interpreter.cpp: + (JSC::jsLess): + (JSC::jsLessEq): + (JSC::jsAdd): + (JSC::jsIsObjectType): + (JSC::cachePrototypeChain): + (JSC::Interpreter::tryCachePutByID): + (JSC::Interpreter::tryCacheGetByID): + (JSC::Interpreter::privateExecute): + (JSC::Interpreter::tryCTICachePutByID): + (JSC::Interpreter::tryCTICacheGetByID): + (JSC::Interpreter::cti_op_add): + (JSC::Interpreter::cti_op_get_by_id_self_fail): + (JSC::Interpreter::cti_op_get_by_id_proto_list): + (JSC::Interpreter::cti_op_instanceof): + (JSC::Interpreter::cti_op_mul): + (JSC::Interpreter::cti_op_get_by_val): + (JSC::Interpreter::cti_op_get_by_val_byte_array): + (JSC::Interpreter::cti_op_sub): + (JSC::Interpreter::cti_op_put_by_val): + (JSC::Interpreter::cti_op_put_by_val_array): + (JSC::Interpreter::cti_op_put_by_val_byte_array): + (JSC::Interpreter::cti_op_negate): + (JSC::Interpreter::cti_op_div): + (JSC::Interpreter::cti_op_eq): + (JSC::Interpreter::cti_op_lshift): + (JSC::Interpreter::cti_op_bitand): + (JSC::Interpreter::cti_op_rshift): + (JSC::Interpreter::cti_op_bitnot): + (JSC::Interpreter::cti_op_neq): + (JSC::Interpreter::cti_op_urshift): + (JSC::Interpreter::cti_op_call_eval): + (JSC::Interpreter::cti_op_throw): + (JSC::Interpreter::cti_op_is_undefined): + (JSC::Interpreter::cti_op_stricteq): + (JSC::Interpreter::cti_op_nstricteq): + (JSC::Interpreter::cti_op_switch_imm): + (JSC::Interpreter::cti_vm_throw): + * interpreter/Interpreter.h: + (JSC::Interpreter::isJSArray): + (JSC::Interpreter::isJSString): + (JSC::Interpreter::isJSByteArray): + * jit/JIT.cpp: + (JSC::JIT::compileOpStrictEq): + (JSC::JIT::privateCompileMainPass): + * jit/JIT.h: + (JSC::JIT::isStrictEqCaseHandledInJITCode): + * jit/JITArithmetic.cpp: + (JSC::JIT::compileFastArith_op_rshift): + (JSC::JIT::compileFastArith_op_bitand): + (JSC::JIT::compileFastArith_op_mod): + * jit/JITCall.cpp: + (JSC::JIT::unlinkCall): + (JSC::JIT::compileOpCall): + * jit/JITInlineMethods.h: + (JSC::JIT::getConstantOperandImmediateInt): + (JSC::JIT::isOperandConstantImmediateInt): + * parser/Nodes.cpp: + (JSC::processClauseList): + * runtime/ArrayPrototype.cpp: + (JSC::arrayProtoFuncIndexOf): + (JSC::arrayProtoFuncLastIndexOf): + * runtime/BooleanPrototype.cpp: + (JSC::booleanProtoFuncValueOf): + * runtime/Collector.cpp: + (JSC::Heap::protect): + (JSC::Heap::unprotect): + (JSC::Heap::heap): + * runtime/JSByteArray.cpp: + (JSC::JSByteArray::getOwnPropertySlot): + * runtime/JSByteArray.h: + (JSC::JSByteArray::getIndex): + * runtime/JSCell.cpp: + * runtime/JSCell.h: + (JSC::JSValuePtr::isNumberCell): + (JSC::JSValuePtr::asCell): + (JSC::JSValuePtr::isNumber): + * runtime/JSGlobalObjectFunctions.cpp: + (JSC::globalFuncParseInt): + * runtime/JSImmediate.h: + (JSC::js0): + (JSC::jsImpossibleValue): + (JSC::JSValuePtr::toInt32): + (JSC::JSValuePtr::toUInt32): + (JSC::JSValuePtr::isCell): + (JSC::JSValuePtr::isInt32Fast): + (JSC::JSValuePtr::getInt32Fast): + (JSC::JSValuePtr::isUInt32Fast): + (JSC::JSValuePtr::getUInt32Fast): + (JSC::JSValuePtr::makeInt32Fast): + (JSC::JSValuePtr::areBothInt32Fast): + (JSC::JSFastMath::canDoFastBitwiseOperations): + (JSC::JSFastMath::equal): + (JSC::JSFastMath::notEqual): + (JSC::JSFastMath::andImmediateNumbers): + (JSC::JSFastMath::xorImmediateNumbers): + (JSC::JSFastMath::orImmediateNumbers): + (JSC::JSFastMath::canDoFastRshift): + (JSC::JSFastMath::canDoFastUrshift): + (JSC::JSFastMath::rightShiftImmediateNumbers): + (JSC::JSFastMath::canDoFastAdditiveOperations): + (JSC::JSFastMath::addImmediateNumbers): + (JSC::JSFastMath::subImmediateNumbers): + (JSC::JSFastMath::incImmediateNumber): + (JSC::JSFastMath::decImmediateNumber): + * runtime/JSNumberCell.h: + (JSC::JSValuePtr::asNumberCell): + (JSC::jsNumber): + (JSC::JSValuePtr::uncheckedGetNumber): + (JSC::JSNumberCell::toInt32): + (JSC::JSNumberCell::toUInt32): + (JSC::JSValuePtr::toJSNumber): + (JSC::JSValuePtr::getNumber): + (JSC::JSValuePtr::numberToInt32): + (JSC::JSValuePtr::numberToUInt32): + * runtime/JSObject.h: + (JSC::JSValuePtr::isObject): + (JSC::JSValuePtr::get): + (JSC::JSValuePtr::put): + * runtime/JSValue.cpp: + (JSC::JSValuePtr::toInteger): + (JSC::JSValuePtr::toIntegerPreserveNaN): + * runtime/JSValue.h: + * runtime/Operations.cpp: + (JSC::JSValuePtr::equalSlowCase): + (JSC::JSValuePtr::strictEqualSlowCase): + * runtime/Operations.h: + (JSC::JSValuePtr::equal): + (JSC::JSValuePtr::equalSlowCaseInline): + (JSC::JSValuePtr::strictEqual): + (JSC::JSValuePtr::strictEqualSlowCaseInline): + * runtime/Protect.h: + (JSC::gcProtect): + (JSC::gcUnprotect): + * runtime/StringPrototype.cpp: + (JSC::stringProtoFuncCharAt): + (JSC::stringProtoFuncCharCodeAt): + * runtime/Structure.cpp: + (JSC::Structure::createCachedPrototypeChain): + +2009-01-12 Kevin Ollivier <kevino@theolliviers.com> + + Since date time functions have moved here, now the wx port JSC + needs to depend on wx. + + * jscore.bkl: + +2009-01-11 David Levin <levin@chromium.org> + + Reviewed by Darin Adler. + + https://bugs.webkit.org/show_bug.cgi?id=23245 + + Add initializeThreading to key places in JS API to ensure that + UString is properly initialized. + + * API/JSContextRef.cpp: + (JSContextGroupCreate): + (JSGlobalContextCreate): + * API/JSObjectRef.cpp: + (JSClassCreate): + * API/JSStringRef.cpp: + (JSStringCreateWithCharacters): + (JSStringCreateWithUTF8CString): + * API/JSStringRefCF.cpp: + (JSStringCreateWithCFString): + +2009-01-11 David Levin <levin@chromium.org> + + Reviewed by Darin Adler. + + https://bugs.webkit.org/show_bug.cgi?id=23175 + + Separate out BaseString information from UString::Rep and make all baseString access go through + a member function, so that it may be used for something else (in the future) in the BaseString + case. + + * runtime/SmallStrings.cpp: + (JSC::SmallStringsStorage::rep): + (JSC::SmallStringsStorage::SmallStringsStorage): + (JSC::SmallStrings::SmallStrings): + (JSC::SmallStrings::mark): + Adjust to account for the changes in UString and put the UString in place in + SmallStringsStorage to aid in locality of reference among the UChar[] and UString::Rep's. + + * runtime/SmallStrings.h: + * runtime/UString.cpp: + (JSC::initializeStaticBaseString): + (JSC::initializeUString): + (JSC::UString::Rep::create): + (JSC::UString::Rep::destroy): + (JSC::UString::Rep::checkConsistency): + (JSC::expandCapacity): + (JSC::UString::expandPreCapacity): + (JSC::concatenate): + (JSC::UString::append): + (JSC::UString::operator=): + * runtime/UString.h: + (JSC::UString::Rep::baseIsSelf): + (JSC::UString::Rep::setBaseString): + (JSC::UString::Rep::baseString): + (JSC::UString::Rep::): + (JSC::UString::Rep::null): + (JSC::UString::Rep::empty): + (JSC::UString::Rep::data): + (JSC::UString::cost): + Separate out the items out used by base strings from those used in Rep's that only + point to base strings. (This potentially saves 24 bytes per Rep.) + +2009-01-11 Darin Adler <darin@apple.com> + + Reviewed by Dan Bernstein. + + Bug 23239: improve handling of unused arguments in JavaScriptCore + https://bugs.webkit.org/show_bug.cgi?id=23239 + + * runtime/DatePrototype.cpp: Moved LocaleDateTimeFormat enum outside #if + so we can use this on all platforms. Changed valueOf to share the same + function with getTime, since the contents of the two are identical. Removed + a FIXME since the idea isn't really specific enough or helpful enough to + need to sit here in the source code. + (JSC::formatLocaleDate): Changed the Mac version of this function to take + the same arguments as the non-Mac version so the caller doesn't have to + special-case the two platforms. Also made the formatString array be const; + before the characters were, but the array was a modifiable global variable. + (JSC::dateProtoFuncToLocaleString): Changed to call the new unified + version of formatLocaleDate and remove the ifdef. + (JSC::dateProtoFuncToLocaleDateString): Ditto. + (JSC::dateProtoFuncToLocaleTimeString): Ditto. + + * runtime/JSNotAnObject.cpp: + (JSC::JSNotAnObject::toObject): Use the new ASSERT_UNUSED instead of the + old UNUSED_PARAM. + + * runtime/RegExp.cpp: + (JSC::RegExp::RegExp): Changed to only use UNUSED_PARAM when the parameter + is actually unused. + + * wtf/TCSystemAlloc.cpp: + (TCMalloc_SystemRelease): Changed to only use UNUSED_PARAM when the parameter + is actually unused. + (TCMalloc_SystemCommit): Changed to omit the argument names instead of using + UNUSED_PARAM. + +2009-01-11 Oliver Hunt <oliver@apple.com> + + Reviewed by NOBODY (Build fix). + + Fix the build (whoops) + + * interpreter/Interpreter.cpp: + (JSC::Interpreter::cti_op_get_by_val): + +2009-01-11 Oliver Hunt <oliver@apple.com> + + Reviewed by Darin Adler and Anders Carlsson + + Bug 23128: get/put_by_val need to respecialise in the face of ByteArray + + Restructure the code slightly, and add comments per Darin's suggestions + + * interpreter/Interpreter.cpp: + (JSC::Interpreter::cti_op_get_by_val): + (JSC::Interpreter::cti_op_get_by_val_byte_array): + (JSC::Interpreter::cti_op_put_by_val): + (JSC::Interpreter::cti_op_put_by_val_byte_array): + +2009-01-11 Oliver Hunt <oliver@apple.com> + + Reviewed by Anders Carlsson. + + Whoops, I accidentally removed an exception check from fast the + fast path for string indexing when i originally landed the + byte array logic. + + * interpreter/Interpreter.cpp: + (JSC::Interpreter::cti_op_get_by_val): + +2009-01-11 Oliver Hunt <oliver@apple.com> + + Reviewed by Anders Carlsson. + + Bug 23128: get/put_by_val need to respecialise in the face of ByteArray + <https://bugs.webkit.org/show_bug.cgi?id=23128> + + Fairly simple patch, add specialised versions of cti_op_get/put_by_val + that assume ByteArray, thus avoiding a few branches in the case of bytearray + manipulation. + + No effect on SunSpider. 15% win on the original testcase. + + * interpreter/Interpreter.cpp: + (JSC::Interpreter::cti_op_get_by_val): + (JSC::Interpreter::cti_op_get_by_val_byte_array): + (JSC::Interpreter::cti_op_put_by_val): + (JSC::Interpreter::cti_op_put_by_val_byte_array): + * interpreter/Interpreter.h: + +2009-01-11 Alexey Proskuryakov <ap@webkit.org> + + Try to fix Windows build. + + * wtf/CurrentTime.cpp: Added a definition of msPerSecond (previously, this code was in + DateMath.cpp, with constant definition in DateTime.h) + +2009-01-11 Alexey Proskuryakov <ap@webkit.org> + + Try to fix Windows build. + + * wtf/CurrentTime.cpp: Include <sys/types.h> and <sys/timeb.h>, as MSDN says to. + +2009-01-11 Dmitry Titov <dimich@chromium.org> + + Reviewed by Darin Adler. + + https://bugs.webkit.org/show_bug.cgi?id=23207 + Moved currentTime() to from WebCore to WTF. + + * GNUmakefile.am: + * JavaScriptCore.exp: added export for WTF::currentTime() + * JavaScriptCore.pri: + * JavaScriptCore.scons: + * JavaScriptCore.vcproj/WTF/WTF.vcproj: + * JavaScriptCore.xcodeproj/project.pbxproj: + * JavaScriptCoreSources.bkl: + * runtime/DateMath.cpp: + (JSC::getCurrentUTCTimeWithMicroseconds): This function had another implementation of currentTime(), essentially. Now uses WTF version. + * wtf/CurrentTime.cpp: Added. + (WTF::currentTime): + (WTF::highResUpTime): + (WTF::lowResUTCTime): + (WTF::qpcAvailable): + * wtf/CurrentTime.h: Added. + +2009-01-09 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Oliver Hunt. + + Stage two of converting JSValue from a pointer to a class type. + Remove the class JSValue. The functionallity has been transitioned + into the wrapper class type JSValuePtr. + + The last stage will be to rename JSValuePtr to JSValue, remove the + overloaded -> operator, and switch operations on JSValuePtrs from + using '->' to use '.' instead. + + * API/APICast.h: + * JavaScriptCore.exp: + * runtime/JSCell.h: + (JSC::asCell): + (JSC::JSValuePtr::asCell): + (JSC::JSValuePtr::isNumber): + (JSC::JSValuePtr::isString): + (JSC::JSValuePtr::isGetterSetter): + (JSC::JSValuePtr::isObject): + (JSC::JSValuePtr::getNumber): + (JSC::JSValuePtr::getString): + (JSC::JSValuePtr::getObject): + (JSC::JSValuePtr::getCallData): + (JSC::JSValuePtr::getConstructData): + (JSC::JSValuePtr::getUInt32): + (JSC::JSValuePtr::getTruncatedInt32): + (JSC::JSValuePtr::getTruncatedUInt32): + (JSC::JSValuePtr::mark): + (JSC::JSValuePtr::marked): + (JSC::JSValuePtr::toPrimitive): + (JSC::JSValuePtr::getPrimitiveNumber): + (JSC::JSValuePtr::toBoolean): + (JSC::JSValuePtr::toNumber): + (JSC::JSValuePtr::toString): + (JSC::JSValuePtr::toObject): + (JSC::JSValuePtr::toThisObject): + (JSC::JSValuePtr::needsThisConversion): + (JSC::JSValuePtr::toThisString): + (JSC::JSValuePtr::getJSNumber): + * runtime/JSImmediate.h: + (JSC::JSValuePtr::isUndefined): + (JSC::JSValuePtr::isNull): + (JSC::JSValuePtr::isUndefinedOrNull): + (JSC::JSValuePtr::isBoolean): + (JSC::JSValuePtr::getBoolean): + (JSC::JSValuePtr::toInt32): + (JSC::JSValuePtr::toUInt32): + * runtime/JSNumberCell.h: + (JSC::JSValuePtr::uncheckedGetNumber): + (JSC::JSValuePtr::toJSNumber): + * runtime/JSObject.h: + (JSC::JSValuePtr::isObject): + (JSC::JSValuePtr::get): + (JSC::JSValuePtr::put): + * runtime/JSString.h: + (JSC::JSValuePtr::toThisJSString): + * runtime/JSValue.cpp: + (JSC::JSValuePtr::toInteger): + (JSC::JSValuePtr::toIntegerPreserveNaN): + (JSC::JSValuePtr::toInt32SlowCase): + (JSC::JSValuePtr::toUInt32SlowCase): + * runtime/JSValue.h: + (JSC::JSValuePtr::makeImmediate): + (JSC::JSValuePtr::immediateValue): + (JSC::JSValuePtr::JSValuePtr): + (JSC::JSValuePtr::operator->): + (JSC::JSValuePtr::operator bool): + (JSC::JSValuePtr::operator==): + (JSC::JSValuePtr::operator!=): + (JSC::JSValuePtr::encode): + (JSC::JSValuePtr::decode): + (JSC::JSValuePtr::toFloat): + (JSC::JSValuePtr::asValue): + (JSC::operator==): + (JSC::operator!=): + +2009-01-09 David Levin <levin@chromium.org> + + Reviewed by Oliver Hunt. + + https://bugs.webkit.org/show_bug.cgi?id=23175 + + Adjustment to previous patch. Remove call to initilizeThreading from JSGlobalCreate + and fix jsc.cpp instead. + + * jsc.cpp: + (main): + (jscmain): + * runtime/JSGlobalData.cpp: + (JSC::JSGlobalData::create): + +2009-01-09 Sam Weinig <sam@webkit.org> + + Roll r39720 back in with a working interpreted mode. + +2009-01-09 David Levin <levin@chromium.org> + + Reviewed by Oliver Hunt. + + https://bugs.webkit.org/show_bug.cgi?id=23175 + + Added a template to make the pointer and flags combination + in UString more readable and less error prone. + + * GNUmakefile.am: + * JavaScriptCore.exp: + * JavaScriptCore.vcproj/WTF/WTF.vcproj: + * JavaScriptCore.xcodeproj/project.pbxproj: + Added PtrAndFlags.h (and sorted the xcode project file). + + * runtime/Identifier.cpp: + (JSC::Identifier::add): + (JSC::Identifier::addSlowCase): + * runtime/InitializeThreading.cpp: + (JSC::initializeThreadingOnce): + Made the init threading initialize the UString globals. Before + these were initilized using {} but that became harder due to the + addition of this tempalte class. + + * runtime/JSGlobalData.cpp: + (JSC::JSGlobalData::create): + * runtime/PropertyNameArray.cpp: + (JSC::PropertyNameArray::add): + * runtime/UString.cpp: + (JSC::initializeStaticBaseString): + (JSC::initializeUString): + (JSC::UString::Rep::create): + (JSC::UString::Rep::createFromUTF8): + (JSC::createRep): + (JSC::UString::UString): + (JSC::concatenate): + (JSC::UString::operator=): + (JSC::UString::makeNull): + (JSC::UString::nullRep): + * runtime/UString.h: + (JSC::UString::Rep::identifierTable): + (JSC::UString::Rep::setIdentifierTable): + (JSC::UString::Rep::isStatic): + (JSC::UString::Rep::setStatic): + (JSC::UString::Rep::): + (JSC::UString::Rep::null): + (JSC::UString::Rep::empty): + (JSC::UString::isNull): + (JSC::UString::null): + (JSC::UString::UString): + + * wtf/PtrAndFlags.h: Added. + (WTF::PtrAndFlags::PtrAndFlags): + (WTF::PtrAndFlags::isFlagSet): + (WTF::PtrAndFlags::setFlag): + (WTF::PtrAndFlags::clearFlag): + (WTF::PtrAndFlags::get): + (WTF::PtrAndFlags::set): + A simple way to layer together a pointer and 2 flags. It relies on the pointer being 4 byte aligned, + which should happen for all allocators (due to aligning pointers, int's, etc. on 4 byte boundaries). + +2009-01-08 Gavin Barraclough <barraclough@apple.com> + + Reviewed by -O-l-i-v-e-r- -H-u-n-t- Sam Weinig (sorry, Sam!). + + Encode immediates in the low word of JSValuePtrs, on x86-64. + + On 32-bit platforms a JSValuePtr may represent a 31-bit signed integer. + On 64-bit platforms, if USE(ALTERNATE_JSIMMEDIATE) is defined, a full + 32-bit integer may be stored in an immediate. + + Presently USE(ALTERNATE_JSIMMEDIATE) uses the same encoding as the default + immediate format - the value is left shifted by one, so a one bit tag can + be added to indicate the value is an immediate. However this means that + values must be commonly be detagged (by right shifting by one) before + arithmetic operations can be performed on immediates. This patch modifies + the formattting so the the high bits of the immediate mark values as being + integer. + + * assembler/MacroAssembler.h: + (JSC::MacroAssembler::not32): + (JSC::MacroAssembler::orPtr): + (JSC::MacroAssembler::zeroExtend32ToPtr): + (JSC::MacroAssembler::jaePtr): + (JSC::MacroAssembler::jbPtr): + (JSC::MacroAssembler::jnzPtr): + (JSC::MacroAssembler::jzPtr): + * assembler/X86Assembler.h: + (JSC::X86Assembler::): + (JSC::X86Assembler::notl_r): + (JSC::X86Assembler::testq_i32r): + * jit/JIT.cpp: + (JSC::JIT::privateCompileMainPass): + (JSC::JIT::privateCompileSlowCases): + (JSC::JIT::privateCompileCTIMachineTrampolines): + * jit/JIT.h: + * jit/JITArithmetic.cpp: + (JSC::JIT::compileFastArith_op_lshift): + (JSC::JIT::compileFastArith_op_rshift): + (JSC::JIT::compileFastArith_op_bitand): + (JSC::JIT::compileFastArithSlow_op_bitand): + (JSC::JIT::compileFastArith_op_mod): + (JSC::JIT::compileFastArithSlow_op_mod): + (JSC::JIT::compileFastArith_op_add): + (JSC::JIT::compileFastArith_op_mul): + (JSC::JIT::compileFastArith_op_post_inc): + (JSC::JIT::compileFastArith_op_post_dec): + (JSC::JIT::compileFastArith_op_pre_inc): + (JSC::JIT::compileFastArith_op_pre_dec): + (JSC::JIT::putDoubleResultToJSNumberCellOrJSImmediate): + (JSC::JIT::compileBinaryArithOp): + * jit/JITCall.cpp: + (JSC::JIT::compileOpCallSlowCase): + * jit/JITInlineMethods.h: + (JSC::JIT::emitJumpIfJSCell): + (JSC::JIT::emitJumpIfNotJSCell): + (JSC::JIT::emitJumpIfImmNum): + (JSC::JIT::emitJumpSlowCaseIfNotImmNum): + (JSC::JIT::emitJumpSlowCaseIfNotImmNums): + (JSC::JIT::emitFastArithDeTagImmediate): + (JSC::JIT::emitFastArithDeTagImmediateJumpIfZero): + (JSC::JIT::emitFastArithReTagImmediate): + (JSC::JIT::emitFastArithImmToInt): + (JSC::JIT::emitFastArithIntToImmNoCheck): + (JSC::JIT::emitTagAsBoolImmediate): + * jit/JITPropertyAccess.cpp: + (JSC::resizePropertyStorage): + (JSC::JIT::privateCompilePutByIdTransition): + (JSC::JIT::privateCompilePatchGetArrayLength): + (JSC::JIT::privateCompileGetByIdSelf): + (JSC::JIT::privateCompileGetByIdProto): + (JSC::JIT::privateCompileGetByIdChain): + (JSC::JIT::privateCompilePutByIdReplace): + * runtime/JSImmediate.h: + (JSC::JSImmediate::isNumber): + (JSC::JSImmediate::isPositiveNumber): + (JSC::JSImmediate::areBothImmediateNumbers): + (JSC::JSImmediate::xorImmediateNumbers): + (JSC::JSImmediate::rightShiftImmediateNumbers): + (JSC::JSImmediate::canDoFastAdditiveOperations): + (JSC::JSImmediate::addImmediateNumbers): + (JSC::JSImmediate::subImmediateNumbers): + (JSC::JSImmediate::makeInt): + (JSC::JSImmediate::toBoolean): + * wtf/Platform.h: + +2009-01-08 Sam Weinig <sam@webkit.org> + + Revert r39720. It broke Interpreted mode. + +2009-01-08 Sam Weinig <sam@webkit.org> + + Reviewed by Oliver Hunt. + + Fix for https://bugs.webkit.org/show_bug.cgi?id=23197 + Delay creating the PCVector until an exception is thrown + Part of <rdar://problem/6469060> + Don't store exception information for a CodeBlock until first exception is thrown + + - Change the process for re-parsing/re-generating bytecode for exception information + to use data from the original CodeBlock (offsets of GlobalResolve instructions) to + aid in creating an identical instruction stream on re-parse, instead of padding + interchangeable opcodes, which would result in different JITed code. + - Fix bug where the wrong ScopeChainNode was used when re-parsing/regenerating from + within some odd modified scope chains. + - Lazily create the pcVector by re-JITing the regenerated CodeBlock and stealing the + the pcVector from it. + + Saves ~2MB on Membuster head. + + * bytecode/CodeBlock.cpp: + (JSC::CodeBlock::dump): + (JSC::CodeBlock::reparseForExceptionInfoIfNecessary): + (JSC::CodeBlock::hasGlobalResolveInstructionAtBytecodeOffset): + (JSC::CodeBlock::hasGlobalResolveInfoAtBytecodeOffset): + * bytecode/CodeBlock.h: + (JSC::JITCodeRef::JITCodeRef): + (JSC::GlobalResolveInfo::GlobalResolveInfo): + (JSC::CodeBlock::getBytecodeIndex): + (JSC::CodeBlock::addGlobalResolveInstruction): + (JSC::CodeBlock::addGlobalResolveInfo): + (JSC::CodeBlock::addFunctionRegisterInfo): + (JSC::CodeBlock::hasExceptionInfo): + (JSC::CodeBlock::pcVector): + (JSC::EvalCodeBlock::EvalCodeBlock): + (JSC::EvalCodeBlock::baseScopeDepth): + * bytecode/Opcode.h: + * bytecompiler/BytecodeGenerator.cpp: + (JSC::BytecodeGenerator::BytecodeGenerator): + (JSC::BytecodeGenerator::emitResolve): + (JSC::BytecodeGenerator::emitGetScopedVar): + * bytecompiler/BytecodeGenerator.h: + (JSC::BytecodeGenerator::setRegeneratingForExceptionInfo): + * interpreter/Interpreter.cpp: + (JSC::bytecodeOffsetForPC): + (JSC::Interpreter::unwindCallFrame): + (JSC::Interpreter::privateExecute): + (JSC::Interpreter::retrieveLastCaller): + (JSC::Interpreter::cti_op_instanceof): + (JSC::Interpreter::cti_op_call_NotJSFunction): + (JSC::Interpreter::cti_op_resolve): + (JSC::Interpreter::cti_op_construct_NotJSConstruct): + (JSC::Interpreter::cti_op_resolve_func): + (JSC::Interpreter::cti_op_resolve_skip): + (JSC::Interpreter::cti_op_resolve_global): + (JSC::Interpreter::cti_op_resolve_with_base): + (JSC::Interpreter::cti_op_throw): + (JSC::Interpreter::cti_op_in): + (JSC::Interpreter::cti_vm_throw): + * jit/JIT.cpp: + (JSC::JIT::privateCompile): + * parser/Nodes.cpp: + (JSC::EvalNode::generateBytecode): + (JSC::EvalNode::bytecodeForExceptionInfoReparse): + (JSC::FunctionBodyNode::bytecodeForExceptionInfoReparse): + * parser/Nodes.h: + +2009-01-08 Jian Li <jianli@chromium.org> + + Reviewed by Alexey Proskuryakov. + + Add Win32 implementation of ThreadSpecific. + https://bugs.webkit.org/show_bug.cgi?id=22614 + + * JavaScriptCore.vcproj/WTF/WTF.vcproj: + * wtf/ThreadSpecific.h: + (WTF::ThreadSpecific::ThreadSpecific): + (WTF::ThreadSpecific::~ThreadSpecific): + (WTF::ThreadSpecific::get): + (WTF::ThreadSpecific::set): + (WTF::ThreadSpecific::destroy): + * wtf/ThreadSpecificWin.cpp: Added. + (WTF::ThreadSpecificThreadExit): + * wtf/ThreadingWin.cpp: + (WTF::wtfThreadEntryPoint): + +2009-01-08 Justin McPherson <justin.mcpherson@nokia.com> + + Reviewed by Simon Hausmann. + + Fix compilation with Qt on NetBSD. + + * runtime/Collector.cpp: + (JSC::currentThreadStackBase): Use PLATFORM(NETBSD) to enter the + code path to retrieve the stack base using pthread_attr_get_np. + The PTHREAD_NP_H define is not used because the header file does + not exist on NetBSD, but the function is declared nevertheless. + * wtf/Platform.h: Introduce WTF_PLATFORM_NETBSD. + +2009-01-07 Sam Weinig <sam@webkit.org> + + Reviewed by Geoffrey Garen. + + <rdar://problem/6469060> Don't store exception information for a CodeBlock until first exception is thrown + + Don't initially store exception information (lineNumber/expressionRange/getByIdExcecptionInfo) + in CodeBlocks blocks. Instead, re-parse for the data on demand and cache it then. + + One important change that was needed to make this work was to pad op_get_global_var with nops to + be the same length as op_resolve_global, since one could be replaced for the other on re-parsing, + and we want to keep the offsets bytecode offsets the same. + + 1.3MB improvement on Membuster head. + + * bytecode/CodeBlock.cpp: + (JSC::CodeBlock::dump): Update op_get_global_var to account for the padding. + (JSC::CodeBlock::dumpStatistics): Add more statistic dumping. + (JSC::CodeBlock::CodeBlock): Initialize m_exceptionInfo. + (JSC::CodeBlock::reparseForExceptionInfoIfNecessary): Re-parses the CodeBlocks + associated SourceCode and steals the ExceptionInfo from it. + (JSC::CodeBlock::lineNumberForBytecodeOffset): Creates the exception info on demand. + (JSC::CodeBlock::expressionRangeForBytecodeOffset): Ditto. + (JSC::CodeBlock::getByIdExceptionInfoForBytecodeOffset): Ditto. + * bytecode/CodeBlock.h: + (JSC::CodeBlock::numberOfExceptionHandlers): Updated to account for m_exceptionInfo indirection. + (JSC::CodeBlock::addExceptionHandler): Ditto. + (JSC::CodeBlock::exceptionHandler): Ditto. + (JSC::CodeBlock::clearExceptionInfo): Ditto. + (JSC::CodeBlock::addExpressionInfo): Ditto. + (JSC::CodeBlock::addGetByIdExceptionInfo): Ditto. + (JSC::CodeBlock::numberOfLineInfos): Ditto. + (JSC::CodeBlock::addLineInfo): Ditto. + (JSC::CodeBlock::lastLineInfo): Ditto. + + * bytecode/Opcode.h: Change length of op_get_global_var to match op_resolve_global. + + * bytecode/SamplingTool.cpp: + (JSC::SamplingTool::dump): Add comment indicating why it is okay not to pass a CallFrame. + + * bytecompiler/BytecodeGenerator.cpp: + (JSC::BytecodeGenerator::generate): Clear the exception info after generation for Function and Eval + Code when not in regenerate for exception info mode. + (JSC::BytecodeGenerator::BytecodeGenerator): Initialize m_regeneratingForExceptionInfo to false. + (JSC::BytecodeGenerator::emitGetScopedVar): Pad op_get_global_var with 2 nops. + * bytecompiler/BytecodeGenerator.h: + (JSC::BytecodeGenerator::setRegeneratingForExcpeptionInfo): Added. + + * interpreter/Interpreter.cpp: + (JSC::Interpreter::throwException): Pass the CallFrame to exception info accessors. + (JSC::Interpreter::privateExecute): Ditto. + (JSC::Interpreter::retrieveLastCaller): Ditto. + (JSC::Interpreter::cti_op_new_error): Ditto. + + * jit/JIT.cpp: + (JSC::JIT::privateCompileMainPass): Pass the current bytecode offset instead of hard coding the + line number, the stub will do the accessing if it gets called. + + * parser/Nodes.cpp: + (JSC::ProgramNode::emitBytecode): Moved. + (JSC::ProgramNode::generateBytecode): Moved. + (JSC::EvalNode::create): Moved. + (JSC::EvalNode::bytecodeForExceptionInfoReparse): Added. + (JSC::FunctionBodyNode::generateBytecode): Rename reparse to reparseInPlace. + (JSC::FunctionBodyNode::bytecodeForExceptionInfoReparse): Addded. + + * parser/Nodes.h: + (JSC::ScopeNode::features): Added getter. + * parser/Parser.cpp: + (JSC::Parser::reparseInPlace): Renamed from reparse. + * parser/Parser.h: + (JSC::Parser::reparse): Added. Re-parses the passed in Node into + a new Node. + * runtime/ExceptionHelpers.cpp: + (JSC::createUndefinedVariableError): Pass along CallFrame. + (JSC::createInvalidParamError): Ditto. + (JSC::createNotAConstructorError): Ditto. + (JSC::createNotAFunctionError): Ditto. + (JSC::createNotAnObjectError): Ditto. + +2009-01-06 Gavin Barraclough <baraclough@apple.com> + + Reviewed by Maciej Stachowiak. + + Replace accidentally removed references in BytecodeGenerator, deleting these + will be hindering the sharing of constant numbers and strings. + + The code to add a new constant (either number or string) to their respective + map works by attempting to add a null entry, then checking the result of the + add for null. The first time, this should return the null (or noValue). + The code checks for null (to see if this is the initial add), and then allocates + a new number / string object. This code relies on the result returned from + the add to the map being stored as a reference, such that the allocated object + will be stored in the map, and will be resused if the same constant is encountered + again. By failing to use a reference we will be leaking GC object for each + additional entry added to the map. As GC objects they should be clollected, + be we should no be allocatin them in the first place. + + https://bugs.webkit.org/show_bug.cgi?id=23158 + + * bytecompiler/BytecodeGenerator.cpp: + (JSC::BytecodeGenerator::emitLoad): + +2009-01-06 Oliver Hunt <oliver@apple.com> + + Reviewed by Gavin Barraclough. + + <rdar://problem/6040850> JavaScript register file should use VirtualAlloc on Windows + + Fairly simple, just reserve 4Mb of address space for the + register file, and then commit one section at a time. We + don't release committed memory as we drop back, but then + mac doesn't either so this probably not too much of a + problem. + + * interpreter/RegisterFile.cpp: + (JSC::RegisterFile::~RegisterFile): + * interpreter/RegisterFile.h: + (JSC::RegisterFile::RegisterFile): + (JSC::RegisterFile::grow): + +2009-01-06 Alexey Proskuryakov <ap@webkit.org> + + Reviewed by Darin Adler. + + https://bugs.webkit.org/show_bug.cgi?id=23142 + ThreadGlobalData leaks seen on buildbot + + * wtf/ThreadSpecific.h: (WTF::ThreadSpecific::destroy): Temporarily reset the thread + specific value to make getter work on Mac OS X. + + * wtf/Platform.h: Touch this file again to make sure all Windows builds use the most recent + version of ThreadSpecific.h. + +2009-01-05 Gavin Barraclough <baraclough@apple.com> + + Reviewed by Oliver Hunt. + + Replace all uses of JSValue* with a new smart pointer type, JSValuePtr. + + A JavaScript value may be a heap object or boxed primitive, represented by a + pointer, or may be an unboxed immediate value, such as an integer. Since a + value may dynamically need to contain either a pointer value or an immediate, + we encode immediates as pointer values (since all valid JSCell pointers are + allocated at alligned addesses, unaligned addresses are available to encode + immediates). As such all JavaScript values are represented using a JSValue*. + + This implementation is encumbered by a number of constraints. It ties the + JSValue representation to the size of pointer on the platform, which, for + example, means that we currently can represent different ranges of integers + as immediates on x86 and x86-64. It also prevents us from overloading the + to-boolean conversion used to test for noValue() - effectively forcing us + to represent noValue() as 0. This would potentially be problematic were we + to wish to encode integer values differently (e.g. were we to use the v8 + encoding, where pointers are tagged with 1 and integers with 0, then the + immediate integer 0 would conflict with noValue()). + + This patch replaces all usage of JSValue* with a new class, JSValuePtr, + which encapsulates the pointer. JSValuePtr maintains the same interface as + JSValue*, overloading operator-> and operator bool such that previous + operations in the code on variables of type JSValue* are still supported. + + In order to provide a ProtectPtr<> type with support for the new value + representation (without using the internal JSValue type directly), a new + ProtectJSValuePtr type has been added, equivalent to the previous type + ProtectPtr<JSValue>. + + This patch is likely the first in a sequence of three changes. With the + value now encapsulated it will likely make sense to migrate the functionality + from JSValue into JSValuePtr, such that the internal pointer representation + need not be exposed. Through migrating the functionality to the wrapper + class the existing JSValue should be rendered redundant, and the class is + likely to be removed (the JSValuePtr now wrapping a pointer to a JSCell). + At this stage it will likely make sense to rename JSValuePtr to JSValue. + + https://bugs.webkit.org/show_bug.cgi?id=23114 + + * API/APICast.h: + (toJS): + (toRef): + * API/JSBase.cpp: + (JSEvaluateScript): + * API/JSCallbackConstructor.h: + (JSC::JSCallbackConstructor::createStructure): + * API/JSCallbackFunction.cpp: + (JSC::JSCallbackFunction::call): + * API/JSCallbackFunction.h: + (JSC::JSCallbackFunction::createStructure): + * API/JSCallbackObject.h: + (JSC::JSCallbackObject::createStructure): + * API/JSCallbackObjectFunctions.h: + (JSC::::asCallbackObject): + (JSC::::put): + (JSC::::hasInstance): + (JSC::::call): + (JSC::::staticValueGetter): + (JSC::::staticFunctionGetter): + (JSC::::callbackGetter): + * API/JSContextRef.cpp: + * API/JSObjectRef.cpp: + (JSObjectMakeConstructor): + (JSObjectSetPrototype): + (JSObjectGetProperty): + (JSObjectSetProperty): + (JSObjectGetPropertyAtIndex): + (JSObjectSetPropertyAtIndex): + * API/JSValueRef.cpp: + (JSValueGetType): + (JSValueIsUndefined): + (JSValueIsNull): + (JSValueIsBoolean): + (JSValueIsNumber): + (JSValueIsString): + (JSValueIsObject): + (JSValueIsObjectOfClass): + (JSValueIsEqual): + (JSValueIsStrictEqual): + (JSValueIsInstanceOfConstructor): + (JSValueToBoolean): + (JSValueToNumber): + (JSValueToStringCopy): + (JSValueToObject): + (JSValueProtect): + (JSValueUnprotect): + * JavaScriptCore.exp: + * bytecode/CodeBlock.cpp: + (JSC::valueToSourceString): + (JSC::constantName): + (JSC::CodeBlock::dump): + * bytecode/CodeBlock.h: + (JSC::CodeBlock::getConstant): + (JSC::CodeBlock::addUnexpectedConstant): + (JSC::CodeBlock::unexpectedConstant): + * bytecode/EvalCodeCache.h: + (JSC::EvalCodeCache::get): + * bytecompiler/BytecodeGenerator.cpp: + (JSC::BytecodeGenerator::BytecodeGenerator): + (JSC::BytecodeGenerator::addConstant): + (JSC::BytecodeGenerator::addUnexpectedConstant): + (JSC::BytecodeGenerator::emitLoad): + (JSC::BytecodeGenerator::emitLoadJSV): + (JSC::BytecodeGenerator::emitGetScopedVar): + (JSC::BytecodeGenerator::emitPutScopedVar): + (JSC::BytecodeGenerator::emitNewError): + (JSC::keyForImmediateSwitch): + * bytecompiler/BytecodeGenerator.h: + (JSC::BytecodeGenerator::JSValueHashTraits::constructDeletedValue): + (JSC::BytecodeGenerator::JSValueHashTraits::isDeletedValue): + * debugger/DebuggerCallFrame.cpp: + (JSC::DebuggerCallFrame::evaluate): + * debugger/DebuggerCallFrame.h: + (JSC::DebuggerCallFrame::DebuggerCallFrame): + (JSC::DebuggerCallFrame::exception): + * interpreter/CallFrame.cpp: + (JSC::CallFrame::thisValue): + * interpreter/CallFrame.h: + (JSC::ExecState::setException): + (JSC::ExecState::exception): + (JSC::ExecState::exceptionSlot): + (JSC::ExecState::hadException): + * interpreter/Interpreter.cpp: + (JSC::fastIsNumber): + (JSC::fastToInt32): + (JSC::fastToUInt32): + (JSC::jsLess): + (JSC::jsLessEq): + (JSC::jsAddSlowCase): + (JSC::jsAdd): + (JSC::jsTypeStringForValue): + (JSC::jsIsObjectType): + (JSC::jsIsFunctionType): + (JSC::Interpreter::resolve): + (JSC::Interpreter::resolveSkip): + (JSC::Interpreter::resolveGlobal): + (JSC::inlineResolveBase): + (JSC::Interpreter::resolveBase): + (JSC::Interpreter::resolveBaseAndProperty): + (JSC::Interpreter::resolveBaseAndFunc): + (JSC::isNotObject): + (JSC::Interpreter::callEval): + (JSC::Interpreter::unwindCallFrame): + (JSC::Interpreter::throwException): + (JSC::Interpreter::execute): + (JSC::Interpreter::checkTimeout): + (JSC::Interpreter::createExceptionScope): + (JSC::cachePrototypeChain): + (JSC::Interpreter::tryCachePutByID): + (JSC::countPrototypeChainEntriesAndCheckForProxies): + (JSC::Interpreter::tryCacheGetByID): + (JSC::Interpreter::privateExecute): + (JSC::Interpreter::retrieveArguments): + (JSC::Interpreter::retrieveCaller): + (JSC::Interpreter::retrieveLastCaller): + (JSC::Interpreter::tryCTICachePutByID): + (JSC::Interpreter::tryCTICacheGetByID): + (JSC::returnToThrowTrampoline): + (JSC::Interpreter::cti_op_convert_this): + (JSC::Interpreter::cti_op_add): + (JSC::Interpreter::cti_op_pre_inc): + (JSC::Interpreter::cti_op_loop_if_less): + (JSC::Interpreter::cti_op_loop_if_lesseq): + (JSC::Interpreter::cti_op_get_by_id_generic): + (JSC::Interpreter::cti_op_get_by_id): + (JSC::Interpreter::cti_op_get_by_id_second): + (JSC::Interpreter::cti_op_get_by_id_self_fail): + (JSC::Interpreter::cti_op_get_by_id_proto_list): + (JSC::Interpreter::cti_op_get_by_id_proto_list_full): + (JSC::Interpreter::cti_op_get_by_id_proto_fail): + (JSC::Interpreter::cti_op_get_by_id_array_fail): + (JSC::Interpreter::cti_op_get_by_id_string_fail): + (JSC::Interpreter::cti_op_instanceof): + (JSC::Interpreter::cti_op_del_by_id): + (JSC::Interpreter::cti_op_mul): + (JSC::Interpreter::cti_op_call_NotJSFunction): + (JSC::Interpreter::cti_op_resolve): + (JSC::Interpreter::cti_op_construct_NotJSConstruct): + (JSC::Interpreter::cti_op_get_by_val): + (JSC::Interpreter::cti_op_resolve_func): + (JSC::Interpreter::cti_op_sub): + (JSC::Interpreter::cti_op_put_by_val): + (JSC::Interpreter::cti_op_put_by_val_array): + (JSC::Interpreter::cti_op_lesseq): + (JSC::Interpreter::cti_op_loop_if_true): + (JSC::Interpreter::cti_op_negate): + (JSC::Interpreter::cti_op_resolve_base): + (JSC::Interpreter::cti_op_resolve_skip): + (JSC::Interpreter::cti_op_resolve_global): + (JSC::Interpreter::cti_op_div): + (JSC::Interpreter::cti_op_pre_dec): + (JSC::Interpreter::cti_op_jless): + (JSC::Interpreter::cti_op_not): + (JSC::Interpreter::cti_op_jtrue): + (JSC::Interpreter::cti_op_post_inc): + (JSC::Interpreter::cti_op_eq): + (JSC::Interpreter::cti_op_lshift): + (JSC::Interpreter::cti_op_bitand): + (JSC::Interpreter::cti_op_rshift): + (JSC::Interpreter::cti_op_bitnot): + (JSC::Interpreter::cti_op_resolve_with_base): + (JSC::Interpreter::cti_op_mod): + (JSC::Interpreter::cti_op_less): + (JSC::Interpreter::cti_op_neq): + (JSC::Interpreter::cti_op_post_dec): + (JSC::Interpreter::cti_op_urshift): + (JSC::Interpreter::cti_op_bitxor): + (JSC::Interpreter::cti_op_bitor): + (JSC::Interpreter::cti_op_call_eval): + (JSC::Interpreter::cti_op_throw): + (JSC::Interpreter::cti_op_next_pname): + (JSC::Interpreter::cti_op_typeof): + (JSC::Interpreter::cti_op_is_undefined): + (JSC::Interpreter::cti_op_is_boolean): + (JSC::Interpreter::cti_op_is_number): + (JSC::Interpreter::cti_op_is_string): + (JSC::Interpreter::cti_op_is_object): + (JSC::Interpreter::cti_op_is_function): + (JSC::Interpreter::cti_op_stricteq): + (JSC::Interpreter::cti_op_nstricteq): + (JSC::Interpreter::cti_op_to_jsnumber): + (JSC::Interpreter::cti_op_in): + (JSC::Interpreter::cti_op_switch_imm): + (JSC::Interpreter::cti_op_switch_char): + (JSC::Interpreter::cti_op_switch_string): + (JSC::Interpreter::cti_op_del_by_val): + (JSC::Interpreter::cti_op_new_error): + (JSC::Interpreter::cti_vm_throw): + * interpreter/Interpreter.h: + (JSC::Interpreter::isJSArray): + (JSC::Interpreter::isJSString): + * interpreter/Register.h: + (JSC::Register::): + (JSC::Register::Register): + (JSC::Register::jsValue): + (JSC::Register::getJSValue): + * jit/JIT.cpp: + (JSC::): + (JSC::JIT::compileOpStrictEq): + (JSC::JIT::privateCompileMainPass): + (JSC::JIT::privateCompileSlowCases): + * jit/JIT.h: + (JSC::): + (JSC::JIT::execute): + * jit/JITArithmetic.cpp: + (JSC::JIT::compileFastArith_op_rshift): + (JSC::JIT::compileFastArithSlow_op_rshift): + * jit/JITCall.cpp: + (JSC::JIT::unlinkCall): + (JSC::JIT::compileOpCallInitializeCallFrame): + (JSC::JIT::compileOpCall): + * jit/JITInlineMethods.h: + (JSC::JIT::emitGetVirtualRegister): + (JSC::JIT::getConstantOperand): + (JSC::JIT::isOperandConstant31BitImmediateInt): + (JSC::JIT::emitPutJITStubArgFromVirtualRegister): + (JSC::JIT::emitInitRegister): + * jit/JITPropertyAccess.cpp: + (JSC::resizePropertyStorage): + (JSC::JIT::privateCompilePutByIdTransition): + (JSC::JIT::patchGetByIdSelf): + (JSC::JIT::patchPutByIdReplace): + (JSC::JIT::privateCompileGetByIdSelf): + (JSC::JIT::privateCompileGetByIdProto): + (JSC::JIT::privateCompileGetByIdSelfList): + (JSC::JIT::privateCompileGetByIdProtoList): + (JSC::JIT::privateCompileGetByIdChainList): + (JSC::JIT::privateCompileGetByIdChain): + (JSC::JIT::privateCompilePutByIdReplace): + * jsc.cpp: + (functionPrint): + (functionDebug): + (functionGC): + (functionVersion): + (functionRun): + (functionLoad): + (functionReadline): + (functionQuit): + * parser/Nodes.cpp: + (JSC::NullNode::emitBytecode): + (JSC::ArrayNode::emitBytecode): + (JSC::FunctionCallValueNode::emitBytecode): + (JSC::FunctionCallResolveNode::emitBytecode): + (JSC::VoidNode::emitBytecode): + (JSC::ConstDeclNode::emitCodeSingle): + (JSC::ReturnNode::emitBytecode): + (JSC::processClauseList): + (JSC::EvalNode::emitBytecode): + (JSC::FunctionBodyNode::emitBytecode): + (JSC::ProgramNode::emitBytecode): + * profiler/ProfileGenerator.cpp: + (JSC::ProfileGenerator::addParentForConsoleStart): + * profiler/Profiler.cpp: + (JSC::Profiler::willExecute): + (JSC::Profiler::didExecute): + (JSC::Profiler::createCallIdentifier): + * profiler/Profiler.h: + * runtime/ArgList.cpp: + (JSC::ArgList::slowAppend): + * runtime/ArgList.h: + (JSC::ArgList::at): + (JSC::ArgList::append): + * runtime/Arguments.cpp: + (JSC::Arguments::put): + * runtime/Arguments.h: + (JSC::Arguments::createStructure): + (JSC::asArguments): + * runtime/ArrayConstructor.cpp: + (JSC::callArrayConstructor): + * runtime/ArrayPrototype.cpp: + (JSC::getProperty): + (JSC::putProperty): + (JSC::arrayProtoFuncToString): + (JSC::arrayProtoFuncToLocaleString): + (JSC::arrayProtoFuncJoin): + (JSC::arrayProtoFuncConcat): + (JSC::arrayProtoFuncPop): + (JSC::arrayProtoFuncPush): + (JSC::arrayProtoFuncReverse): + (JSC::arrayProtoFuncShift): + (JSC::arrayProtoFuncSlice): + (JSC::arrayProtoFuncSort): + (JSC::arrayProtoFuncSplice): + (JSC::arrayProtoFuncUnShift): + (JSC::arrayProtoFuncFilter): + (JSC::arrayProtoFuncMap): + (JSC::arrayProtoFuncEvery): + (JSC::arrayProtoFuncForEach): + (JSC::arrayProtoFuncSome): + (JSC::arrayProtoFuncIndexOf): + (JSC::arrayProtoFuncLastIndexOf): + * runtime/BooleanConstructor.cpp: + (JSC::callBooleanConstructor): + (JSC::constructBooleanFromImmediateBoolean): + * runtime/BooleanConstructor.h: + * runtime/BooleanObject.h: + (JSC::asBooleanObject): + * runtime/BooleanPrototype.cpp: + (JSC::booleanProtoFuncToString): + (JSC::booleanProtoFuncValueOf): + * runtime/CallData.cpp: + (JSC::call): + * runtime/CallData.h: + * runtime/Collector.cpp: + (JSC::Heap::protect): + (JSC::Heap::unprotect): + (JSC::Heap::heap): + (JSC::Heap::collect): + * runtime/Collector.h: + * runtime/Completion.cpp: + (JSC::evaluate): + * runtime/Completion.h: + (JSC::Completion::Completion): + (JSC::Completion::value): + (JSC::Completion::setValue): + (JSC::Completion::isValueCompletion): + * runtime/ConstructData.cpp: + (JSC::construct): + * runtime/ConstructData.h: + * runtime/DateConstructor.cpp: + (JSC::constructDate): + (JSC::callDate): + (JSC::dateParse): + (JSC::dateNow): + (JSC::dateUTC): + * runtime/DateInstance.h: + (JSC::asDateInstance): + * runtime/DatePrototype.cpp: + (JSC::dateProtoFuncToString): + (JSC::dateProtoFuncToUTCString): + (JSC::dateProtoFuncToDateString): + (JSC::dateProtoFuncToTimeString): + (JSC::dateProtoFuncToLocaleString): + (JSC::dateProtoFuncToLocaleDateString): + (JSC::dateProtoFuncToLocaleTimeString): + (JSC::dateProtoFuncValueOf): + (JSC::dateProtoFuncGetTime): + (JSC::dateProtoFuncGetFullYear): + (JSC::dateProtoFuncGetUTCFullYear): + (JSC::dateProtoFuncToGMTString): + (JSC::dateProtoFuncGetMonth): + (JSC::dateProtoFuncGetUTCMonth): + (JSC::dateProtoFuncGetDate): + (JSC::dateProtoFuncGetUTCDate): + (JSC::dateProtoFuncGetDay): + (JSC::dateProtoFuncGetUTCDay): + (JSC::dateProtoFuncGetHours): + (JSC::dateProtoFuncGetUTCHours): + (JSC::dateProtoFuncGetMinutes): + (JSC::dateProtoFuncGetUTCMinutes): + (JSC::dateProtoFuncGetSeconds): + (JSC::dateProtoFuncGetUTCSeconds): + (JSC::dateProtoFuncGetMilliSeconds): + (JSC::dateProtoFuncGetUTCMilliseconds): + (JSC::dateProtoFuncGetTimezoneOffset): + (JSC::dateProtoFuncSetTime): + (JSC::setNewValueFromTimeArgs): + (JSC::setNewValueFromDateArgs): + (JSC::dateProtoFuncSetMilliSeconds): + (JSC::dateProtoFuncSetUTCMilliseconds): + (JSC::dateProtoFuncSetSeconds): + (JSC::dateProtoFuncSetUTCSeconds): + (JSC::dateProtoFuncSetMinutes): + (JSC::dateProtoFuncSetUTCMinutes): + (JSC::dateProtoFuncSetHours): + (JSC::dateProtoFuncSetUTCHours): + (JSC::dateProtoFuncSetDate): + (JSC::dateProtoFuncSetUTCDate): + (JSC::dateProtoFuncSetMonth): + (JSC::dateProtoFuncSetUTCMonth): + (JSC::dateProtoFuncSetFullYear): + (JSC::dateProtoFuncSetUTCFullYear): + (JSC::dateProtoFuncSetYear): + (JSC::dateProtoFuncGetYear): + * runtime/DatePrototype.h: + (JSC::DatePrototype::createStructure): + * runtime/ErrorConstructor.cpp: + (JSC::callErrorConstructor): + * runtime/ErrorPrototype.cpp: + (JSC::errorProtoFuncToString): + * runtime/ExceptionHelpers.cpp: + (JSC::createInterruptedExecutionException): + (JSC::createError): + (JSC::createStackOverflowError): + (JSC::createUndefinedVariableError): + (JSC::createErrorMessage): + (JSC::createInvalidParamError): + (JSC::createNotAConstructorError): + (JSC::createNotAFunctionError): + * runtime/ExceptionHelpers.h: + * runtime/FunctionConstructor.cpp: + (JSC::callFunctionConstructor): + * runtime/FunctionPrototype.cpp: + (JSC::callFunctionPrototype): + (JSC::functionProtoFuncToString): + (JSC::functionProtoFuncApply): + (JSC::functionProtoFuncCall): + * runtime/FunctionPrototype.h: + (JSC::FunctionPrototype::createStructure): + * runtime/GetterSetter.cpp: + (JSC::GetterSetter::toPrimitive): + (JSC::GetterSetter::getPrimitiveNumber): + * runtime/GetterSetter.h: + (JSC::asGetterSetter): + * runtime/InitializeThreading.cpp: + * runtime/InternalFunction.h: + (JSC::InternalFunction::createStructure): + (JSC::asInternalFunction): + * runtime/JSActivation.cpp: + (JSC::JSActivation::getOwnPropertySlot): + (JSC::JSActivation::put): + (JSC::JSActivation::putWithAttributes): + (JSC::JSActivation::argumentsGetter): + * runtime/JSActivation.h: + (JSC::JSActivation::createStructure): + (JSC::asActivation): + * runtime/JSArray.cpp: + (JSC::storageSize): + (JSC::JSArray::JSArray): + (JSC::JSArray::getOwnPropertySlot): + (JSC::JSArray::put): + (JSC::JSArray::putSlowCase): + (JSC::JSArray::deleteProperty): + (JSC::JSArray::getPropertyNames): + (JSC::JSArray::setLength): + (JSC::JSArray::pop): + (JSC::JSArray::push): + (JSC::JSArray::mark): + (JSC::JSArray::sort): + (JSC::JSArray::compactForSorting): + (JSC::JSArray::checkConsistency): + (JSC::constructArray): + * runtime/JSArray.h: + (JSC::JSArray::getIndex): + (JSC::JSArray::setIndex): + (JSC::JSArray::createStructure): + (JSC::asArray): + * runtime/JSCell.cpp: + (JSC::JSCell::put): + (JSC::JSCell::getJSNumber): + * runtime/JSCell.h: + (JSC::asCell): + (JSC::JSValue::asCell): + (JSC::JSValue::toPrimitive): + (JSC::JSValue::getPrimitiveNumber): + (JSC::JSValue::getJSNumber): + * runtime/JSFunction.cpp: + (JSC::JSFunction::call): + (JSC::JSFunction::argumentsGetter): + (JSC::JSFunction::callerGetter): + (JSC::JSFunction::lengthGetter): + (JSC::JSFunction::getOwnPropertySlot): + (JSC::JSFunction::put): + (JSC::JSFunction::construct): + * runtime/JSFunction.h: + (JSC::JSFunction::createStructure): + (JSC::asFunction): + * runtime/JSGlobalData.h: + * runtime/JSGlobalObject.cpp: + (JSC::markIfNeeded): + (JSC::JSGlobalObject::put): + (JSC::JSGlobalObject::putWithAttributes): + (JSC::JSGlobalObject::reset): + (JSC::JSGlobalObject::resetPrototype): + * runtime/JSGlobalObject.h: + (JSC::JSGlobalObject::createStructure): + (JSC::JSGlobalObject::GlobalPropertyInfo::GlobalPropertyInfo): + (JSC::asGlobalObject): + (JSC::Structure::prototypeForLookup): + * runtime/JSGlobalObjectFunctions.cpp: + (JSC::encode): + (JSC::decode): + (JSC::globalFuncEval): + (JSC::globalFuncParseInt): + (JSC::globalFuncParseFloat): + (JSC::globalFuncIsNaN): + (JSC::globalFuncIsFinite): + (JSC::globalFuncDecodeURI): + (JSC::globalFuncDecodeURIComponent): + (JSC::globalFuncEncodeURI): + (JSC::globalFuncEncodeURIComponent): + (JSC::globalFuncEscape): + (JSC::globalFuncUnescape): + (JSC::globalFuncJSCPrint): + * runtime/JSGlobalObjectFunctions.h: + * runtime/JSImmediate.cpp: + (JSC::JSImmediate::toThisObject): + (JSC::JSImmediate::toObject): + (JSC::JSImmediate::prototype): + (JSC::JSImmediate::toString): + * runtime/JSImmediate.h: + (JSC::JSImmediate::isImmediate): + (JSC::JSImmediate::isNumber): + (JSC::JSImmediate::isPositiveNumber): + (JSC::JSImmediate::isBoolean): + (JSC::JSImmediate::isUndefinedOrNull): + (JSC::JSImmediate::isNegative): + (JSC::JSImmediate::isEitherImmediate): + (JSC::JSImmediate::isAnyImmediate): + (JSC::JSImmediate::areBothImmediate): + (JSC::JSImmediate::areBothImmediateNumbers): + (JSC::JSImmediate::andImmediateNumbers): + (JSC::JSImmediate::xorImmediateNumbers): + (JSC::JSImmediate::orImmediateNumbers): + (JSC::JSImmediate::rightShiftImmediateNumbers): + (JSC::JSImmediate::canDoFastAdditiveOperations): + (JSC::JSImmediate::addImmediateNumbers): + (JSC::JSImmediate::subImmediateNumbers): + (JSC::JSImmediate::incImmediateNumber): + (JSC::JSImmediate::decImmediateNumber): + (JSC::JSImmediate::makeValue): + (JSC::JSImmediate::makeInt): + (JSC::JSImmediate::makeBool): + (JSC::JSImmediate::makeUndefined): + (JSC::JSImmediate::makeNull): + (JSC::JSImmediate::intValue): + (JSC::JSImmediate::uintValue): + (JSC::JSImmediate::boolValue): + (JSC::JSImmediate::rawValue): + (JSC::JSImmediate::trueImmediate): + (JSC::JSImmediate::falseImmediate): + (JSC::JSImmediate::undefinedImmediate): + (JSC::JSImmediate::nullImmediate): + (JSC::JSImmediate::zeroImmediate): + (JSC::JSImmediate::oneImmediate): + (JSC::JSImmediate::impossibleValue): + (JSC::JSImmediate::toBoolean): + (JSC::JSImmediate::getTruncatedUInt32): + (JSC::JSImmediate::from): + (JSC::JSImmediate::getTruncatedInt32): + (JSC::JSImmediate::toDouble): + (JSC::JSImmediate::getUInt32): + (JSC::jsNull): + (JSC::jsBoolean): + (JSC::jsUndefined): + (JSC::JSValue::isUndefined): + (JSC::JSValue::isNull): + (JSC::JSValue::isUndefinedOrNull): + (JSC::JSValue::isBoolean): + (JSC::JSValue::getBoolean): + (JSC::JSValue::toInt32): + (JSC::JSValue::toUInt32): + (JSC::toInt32): + (JSC::toUInt32): + * runtime/JSNotAnObject.cpp: + (JSC::JSNotAnObject::toPrimitive): + (JSC::JSNotAnObject::getPrimitiveNumber): + (JSC::JSNotAnObject::put): + * runtime/JSNotAnObject.h: + (JSC::JSNotAnObject::createStructure): + * runtime/JSNumberCell.cpp: + (JSC::JSNumberCell::toPrimitive): + (JSC::JSNumberCell::getPrimitiveNumber): + (JSC::JSNumberCell::getJSNumber): + (JSC::jsNumberCell): + (JSC::jsNaN): + * runtime/JSNumberCell.h: + (JSC::JSNumberCell::createStructure): + (JSC::asNumberCell): + (JSC::jsNumber): + (JSC::JSValue::toJSNumber): + * runtime/JSObject.cpp: + (JSC::JSObject::mark): + (JSC::JSObject::put): + (JSC::JSObject::putWithAttributes): + (JSC::callDefaultValueFunction): + (JSC::JSObject::getPrimitiveNumber): + (JSC::JSObject::defaultValue): + (JSC::JSObject::defineGetter): + (JSC::JSObject::defineSetter): + (JSC::JSObject::lookupGetter): + (JSC::JSObject::lookupSetter): + (JSC::JSObject::hasInstance): + (JSC::JSObject::toNumber): + (JSC::JSObject::toString): + (JSC::JSObject::fillGetterPropertySlot): + * runtime/JSObject.h: + (JSC::JSObject::getDirect): + (JSC::JSObject::getDirectLocation): + (JSC::JSObject::offsetForLocation): + (JSC::JSObject::locationForOffset): + (JSC::JSObject::getDirectOffset): + (JSC::JSObject::putDirectOffset): + (JSC::JSObject::createStructure): + (JSC::asObject): + (JSC::JSObject::prototype): + (JSC::JSObject::setPrototype): + (JSC::JSObject::inlineGetOwnPropertySlot): + (JSC::JSObject::getOwnPropertySlotForWrite): + (JSC::JSObject::getPropertySlot): + (JSC::JSObject::get): + (JSC::JSObject::putDirect): + (JSC::JSObject::putDirectWithoutTransition): + (JSC::JSObject::toPrimitive): + (JSC::JSValue::get): + (JSC::JSValue::put): + (JSC::JSObject::allocatePropertyStorageInline): + * runtime/JSPropertyNameIterator.cpp: + (JSC::JSPropertyNameIterator::toPrimitive): + (JSC::JSPropertyNameIterator::getPrimitiveNumber): + * runtime/JSPropertyNameIterator.h: + (JSC::JSPropertyNameIterator::create): + (JSC::JSPropertyNameIterator::next): + * runtime/JSStaticScopeObject.cpp: + (JSC::JSStaticScopeObject::put): + (JSC::JSStaticScopeObject::putWithAttributes): + * runtime/JSStaticScopeObject.h: + (JSC::JSStaticScopeObject::JSStaticScopeObject): + (JSC::JSStaticScopeObject::createStructure): + * runtime/JSString.cpp: + (JSC::JSString::toPrimitive): + (JSC::JSString::getPrimitiveNumber): + (JSC::JSString::getOwnPropertySlot): + * runtime/JSString.h: + (JSC::JSString::createStructure): + (JSC::asString): + * runtime/JSValue.h: + (JSC::JSValuePtr::makeImmediate): + (JSC::JSValuePtr::immediateValue): + (JSC::JSValuePtr::JSValuePtr): + (JSC::JSValuePtr::operator->): + (JSC::JSValuePtr::hasValue): + (JSC::JSValuePtr::operator==): + (JSC::JSValuePtr::operator!=): + (JSC::JSValuePtr::encode): + (JSC::JSValuePtr::decode): + (JSC::JSValue::asValue): + (JSC::noValue): + (JSC::operator==): + (JSC::operator!=): + * runtime/JSVariableObject.h: + (JSC::JSVariableObject::symbolTablePut): + (JSC::JSVariableObject::symbolTablePutWithAttributes): + * runtime/JSWrapperObject.cpp: + (JSC::JSWrapperObject::mark): + * runtime/JSWrapperObject.h: + (JSC::JSWrapperObject::internalValue): + (JSC::JSWrapperObject::setInternalValue): + * runtime/Lookup.cpp: + (JSC::setUpStaticFunctionSlot): + * runtime/Lookup.h: + (JSC::lookupPut): + * runtime/MathObject.cpp: + (JSC::mathProtoFuncAbs): + (JSC::mathProtoFuncACos): + (JSC::mathProtoFuncASin): + (JSC::mathProtoFuncATan): + (JSC::mathProtoFuncATan2): + (JSC::mathProtoFuncCeil): + (JSC::mathProtoFuncCos): + (JSC::mathProtoFuncExp): + (JSC::mathProtoFuncFloor): + (JSC::mathProtoFuncLog): + (JSC::mathProtoFuncMax): + (JSC::mathProtoFuncMin): + (JSC::mathProtoFuncPow): + (JSC::mathProtoFuncRandom): + (JSC::mathProtoFuncRound): + (JSC::mathProtoFuncSin): + (JSC::mathProtoFuncSqrt): + (JSC::mathProtoFuncTan): + * runtime/MathObject.h: + (JSC::MathObject::createStructure): + * runtime/NativeErrorConstructor.cpp: + (JSC::callNativeErrorConstructor): + * runtime/NumberConstructor.cpp: + (JSC::numberConstructorNaNValue): + (JSC::numberConstructorNegInfinity): + (JSC::numberConstructorPosInfinity): + (JSC::numberConstructorMaxValue): + (JSC::numberConstructorMinValue): + (JSC::callNumberConstructor): + * runtime/NumberConstructor.h: + (JSC::NumberConstructor::createStructure): + * runtime/NumberObject.cpp: + (JSC::NumberObject::getJSNumber): + (JSC::constructNumberFromImmediateNumber): + * runtime/NumberObject.h: + * runtime/NumberPrototype.cpp: + (JSC::numberProtoFuncToString): + (JSC::numberProtoFuncToLocaleString): + (JSC::numberProtoFuncValueOf): + (JSC::numberProtoFuncToFixed): + (JSC::numberProtoFuncToExponential): + (JSC::numberProtoFuncToPrecision): + * runtime/ObjectConstructor.cpp: + (JSC::constructObject): + (JSC::callObjectConstructor): + * runtime/ObjectPrototype.cpp: + (JSC::objectProtoFuncValueOf): + (JSC::objectProtoFuncHasOwnProperty): + (JSC::objectProtoFuncIsPrototypeOf): + (JSC::objectProtoFuncDefineGetter): + (JSC::objectProtoFuncDefineSetter): + (JSC::objectProtoFuncLookupGetter): + (JSC::objectProtoFuncLookupSetter): + (JSC::objectProtoFuncPropertyIsEnumerable): + (JSC::objectProtoFuncToLocaleString): + (JSC::objectProtoFuncToString): + * runtime/ObjectPrototype.h: + * runtime/Operations.cpp: + (JSC::equal): + (JSC::equalSlowCase): + (JSC::strictEqual): + (JSC::strictEqualSlowCase): + (JSC::throwOutOfMemoryError): + * runtime/Operations.h: + (JSC::equalSlowCaseInline): + (JSC::strictEqualSlowCaseInline): + * runtime/PropertySlot.cpp: + (JSC::PropertySlot::functionGetter): + * runtime/PropertySlot.h: + (JSC::PropertySlot::PropertySlot): + (JSC::PropertySlot::getValue): + (JSC::PropertySlot::putValue): + (JSC::PropertySlot::setValueSlot): + (JSC::PropertySlot::setValue): + (JSC::PropertySlot::setCustom): + (JSC::PropertySlot::setCustomIndex): + (JSC::PropertySlot::slotBase): + (JSC::PropertySlot::setBase): + (JSC::PropertySlot::): + * runtime/Protect.h: + (JSC::gcProtect): + (JSC::gcUnprotect): + (JSC::ProtectedPtr::ProtectedPtr): + (JSC::ProtectedPtr::operator JSValuePtr): + (JSC::ProtectedJSValuePtr::ProtectedJSValuePtr): + (JSC::ProtectedJSValuePtr::get): + (JSC::ProtectedJSValuePtr::operator JSValuePtr): + (JSC::ProtectedJSValuePtr::operator->): + (JSC::::ProtectedPtr): + (JSC::::~ProtectedPtr): + (JSC::::operator): + (JSC::ProtectedJSValuePtr::~ProtectedJSValuePtr): + (JSC::ProtectedJSValuePtr::operator=): + (JSC::operator==): + (JSC::operator!=): + * runtime/RegExpConstructor.cpp: + (JSC::RegExpConstructor::getBackref): + (JSC::RegExpConstructor::getLastParen): + (JSC::RegExpConstructor::getLeftContext): + (JSC::RegExpConstructor::getRightContext): + (JSC::regExpConstructorDollar1): + (JSC::regExpConstructorDollar2): + (JSC::regExpConstructorDollar3): + (JSC::regExpConstructorDollar4): + (JSC::regExpConstructorDollar5): + (JSC::regExpConstructorDollar6): + (JSC::regExpConstructorDollar7): + (JSC::regExpConstructorDollar8): + (JSC::regExpConstructorDollar9): + (JSC::regExpConstructorInput): + (JSC::regExpConstructorMultiline): + (JSC::regExpConstructorLastMatch): + (JSC::regExpConstructorLastParen): + (JSC::regExpConstructorLeftContext): + (JSC::regExpConstructorRightContext): + (JSC::RegExpConstructor::put): + (JSC::setRegExpConstructorInput): + (JSC::setRegExpConstructorMultiline): + (JSC::constructRegExp): + (JSC::callRegExpConstructor): + * runtime/RegExpConstructor.h: + (JSC::RegExpConstructor::createStructure): + (JSC::asRegExpConstructor): + * runtime/RegExpMatchesArray.h: + (JSC::RegExpMatchesArray::put): + * runtime/RegExpObject.cpp: + (JSC::regExpObjectGlobal): + (JSC::regExpObjectIgnoreCase): + (JSC::regExpObjectMultiline): + (JSC::regExpObjectSource): + (JSC::regExpObjectLastIndex): + (JSC::RegExpObject::put): + (JSC::setRegExpObjectLastIndex): + (JSC::RegExpObject::test): + (JSC::RegExpObject::exec): + (JSC::callRegExpObject): + * runtime/RegExpObject.h: + (JSC::RegExpObject::createStructure): + (JSC::asRegExpObject): + * runtime/RegExpPrototype.cpp: + (JSC::regExpProtoFuncTest): + (JSC::regExpProtoFuncExec): + (JSC::regExpProtoFuncCompile): + (JSC::regExpProtoFuncToString): + * runtime/StringConstructor.cpp: + (JSC::stringFromCharCodeSlowCase): + (JSC::stringFromCharCode): + (JSC::callStringConstructor): + * runtime/StringObject.cpp: + (JSC::StringObject::put): + * runtime/StringObject.h: + (JSC::StringObject::createStructure): + (JSC::asStringObject): + * runtime/StringObjectThatMasqueradesAsUndefined.h: + (JSC::StringObjectThatMasqueradesAsUndefined::createStructure): + * runtime/StringPrototype.cpp: + (JSC::stringProtoFuncReplace): + (JSC::stringProtoFuncToString): + (JSC::stringProtoFuncCharAt): + (JSC::stringProtoFuncCharCodeAt): + (JSC::stringProtoFuncConcat): + (JSC::stringProtoFuncIndexOf): + (JSC::stringProtoFuncLastIndexOf): + (JSC::stringProtoFuncMatch): + (JSC::stringProtoFuncSearch): + (JSC::stringProtoFuncSlice): + (JSC::stringProtoFuncSplit): + (JSC::stringProtoFuncSubstr): + (JSC::stringProtoFuncSubstring): + (JSC::stringProtoFuncToLowerCase): + (JSC::stringProtoFuncToUpperCase): + (JSC::stringProtoFuncLocaleCompare): + (JSC::stringProtoFuncBig): + (JSC::stringProtoFuncSmall): + (JSC::stringProtoFuncBlink): + (JSC::stringProtoFuncBold): + (JSC::stringProtoFuncFixed): + (JSC::stringProtoFuncItalics): + (JSC::stringProtoFuncStrike): + (JSC::stringProtoFuncSub): + (JSC::stringProtoFuncSup): + (JSC::stringProtoFuncFontcolor): + (JSC::stringProtoFuncFontsize): + (JSC::stringProtoFuncAnchor): + (JSC::stringProtoFuncLink): + * runtime/Structure.cpp: + (JSC::Structure::Structure): + (JSC::Structure::changePrototypeTransition): + (JSC::Structure::createCachedPrototypeChain): + * runtime/Structure.h: + (JSC::Structure::create): + (JSC::Structure::setPrototypeWithoutTransition): + (JSC::Structure::storedPrototype): + +2009-01-06 Oliver Hunt <oliver@apple.com> + + Reviewed by Cameron Zwarich. + + <https://bugs.webkit.org/show_bug.cgi?id=23085> [jsfunfuzz] Over released ScopeChainNode + <rdar://problem/6474110> + + So this delightful bug was caused by our unwind code using a ScopeChain to perform + the unwind. The ScopeChain would ref the initial top of the scope chain, then deref + the resultant top of scope chain, which is incorrect. + + This patch removes the dependency on ScopeChain for the unwind, and i've filed + <https://bugs.webkit.org/show_bug.cgi?id=23144> to look into the unintuitive + ScopeChain behaviour. + + * interpreter/Interpreter.cpp: + (JSC::Interpreter::throwException): + +2009-01-06 Adam Roben <aroben@apple.com> + + Hopeful Windows crash-on-launch fix + + * wtf/Platform.h: Force a world rebuild by touching this file. + +2009-01-06 Holger Hans Peter Freyther <zecke@selfish.org> + + Reviewed by NOBODY (Build fix). + + * GNUmakefile.am:Add ByteArray.cpp too + +2009-01-06 Holger Hans Peter Freyther <zecke@selfish.org> + + Reviewed by NOBODY (Speculative build fix). + + AllInOneFile.cpp does not include the JSByteArray.cpp include it... + + * GNUmakefile.am: + +2009-01-05 Oliver Hunt <oliver@apple.com> + + Reviewed by NOBODY (Build fix). + + Fix Wx build + + * JavaScriptCoreSources.bkl: + +2009-01-05 Oliver Hunt <oliver@apple.com> + + Windows build fixes + + Rubber-stamped by Alice Liu. + + * interpreter/Interpreter.cpp: + (JSC::Interpreter::Interpreter): + * runtime/ByteArray.cpp: + (JSC::ByteArray::create): + * runtime/ByteArray.h: + +2009-01-05 Oliver Hunt <oliver@apple.com> + + Reviewed by Gavin Barraclough. + + CanvasPixelArray performance is too slow + <https://bugs.webkit.org/show_bug.cgi?id=23123> + + The fix to this is to devirtualise get and put in a manner similar to + JSString and JSArray. To do this I've added a ByteArray implementation + and JSByteArray wrapper to JSC. We can then do vptr comparisons to + devirtualise the calls. + + This devirtualisation improves performance by 1.5-2x in my somewhat ad + hoc tests. + + * GNUmakefile.am: + * JavaScriptCore.exp: + * JavaScriptCore.pri: + * JavaScriptCore.scons: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: + * JavaScriptCore.xcodeproj/project.pbxproj: + * interpreter/Interpreter.cpp: + (JSC::Interpreter::Interpreter): + (JSC::Interpreter::privateExecute): + (JSC::Interpreter::cti_op_get_by_val): + (JSC::Interpreter::cti_op_put_by_val): + * interpreter/Interpreter.h: + (JSC::Interpreter::isJSByteArray): + * runtime/ByteArray.cpp: Added. + (JSC::ByteArray::create): + * runtime/ByteArray.h: Added. + (JSC::ByteArray::length): + (JSC::ByteArray::set): + (JSC::ByteArray::get): + (JSC::ByteArray::data): + (JSC::ByteArray::ByteArray): + * runtime/JSByteArray.cpp: Added. + (JSC::): + (JSC::JSByteArray::JSByteArray): + (JSC::JSByteArray::createStructure): + (JSC::JSByteArray::getOwnPropertySlot): + (JSC::JSByteArray::put): + (JSC::JSByteArray::getPropertyNames): + * runtime/JSByteArray.h: Added. + (JSC::JSByteArray::canAccessIndex): + (JSC::JSByteArray::getIndex): + (JSC::JSByteArray::setIndex): + (JSC::JSByteArray::classInfo): + (JSC::JSByteArray::length): + (JSC::JSByteArray::): + (JSC::JSByteArray::JSByteArray): + (JSC::asByteArray): + +2009-01-05 Alexey Proskuryakov <ap@webkit.org> + + Reviewed by Darin Adler. + + https://bugs.webkit.org/show_bug.cgi?id=23073 + <rdar://problem/6471129> Workers crash on Windows Release builds + + * wtf/ThreadSpecific.h: + (WTF::ThreadSpecific::destroy): Changed to clear the pointer only after data object + destruction is finished - otherwise, WebCore::ThreadGlobalData destructor was re-creating + the object in order to access atomic string table. + (WTF::ThreadSpecific::operator T*): Symmetrically, set up the per-thread pointer before + data constructor is called. + + * wtf/ThreadingWin.cpp: (WTF::wtfThreadEntryPoint): Remove a Windows-only hack to finalize + a thread - pthreadVC2 is a DLL, so it gets thread detached messages, and cleans up thread + specific data automatically. Besides, this code wasn't even compiled in for some time now. + +2009-01-05 Alexey Proskuryakov <ap@webkit.org> + + Reviewed by Darin Adler. + + https://bugs.webkit.org/show_bug.cgi?id=23115 + Create a version of ASSERT for use with otherwise unused variables + + * wtf/Assertions.h: Added ASSERT_UNUSED. + + * jit/ExecutableAllocatorPosix.cpp: + (JSC::ExecutablePool::systemRelease): + * runtime/Collector.cpp: + (JSC::Heap::destroy): + (JSC::Heap::heapAllocate): + * runtime/JSNotAnObject.cpp: + (JSC::JSNotAnObject::toPrimitive): + (JSC::JSNotAnObject::getPrimitiveNumber): + (JSC::JSNotAnObject::toBoolean): + (JSC::JSNotAnObject::toNumber): + (JSC::JSNotAnObject::toString): + (JSC::JSNotAnObject::getOwnPropertySlot): + (JSC::JSNotAnObject::put): + (JSC::JSNotAnObject::deleteProperty): + (JSC::JSNotAnObject::getPropertyNames): + * wtf/TCSystemAlloc.cpp: + (TCMalloc_SystemRelease): + Use it in some places that used other idioms for this purpose. + +2009-01-04 Alice Liu <alice.liu@apple.com> + + <rdar://problem/6341776> Merge m_transitionCount and m_offset in Structure. + + Reviewed by Darin Adler. + + * runtime/Structure.cpp: + (JSC::Structure::Structure): Remove m_transitionCount + (JSC::Structure::addPropertyTransitionToExistingStructure): No need to wait until after the assignment to offset to assert if it's notFound; move it up. + (JSC::Structure::addPropertyTransition): Use method for transitionCount instead of m_transitionCount. Remove line that maintains the m_transitionCount. + (JSC::Structure::changePrototypeTransition): Remove line that maintains the m_transitionCount. + (JSC::Structure::getterSetterTransition): Remove line that maintains the m_transitionCount. + * runtime/Structure.h: + Changed s_maxTransitionLength and m_offset from size_t to signed char. m_offset will never become greater than 64 + because the structure transitions to a dictionary at that time. + (JSC::Structure::transitionCount): method to replace the data member + +2009-01-04 Darin Adler <darin@apple.com> + + Reviewed by David Kilzer. + + Bug 15114: Provide compile-time assertions for sizeof(UChar), sizeof(DeprecatedChar), etc. + https://bugs.webkit.org/show_bug.cgi?id=15114 + + * wtf/unicode/Unicode.h: Assert size of UChar. There is no DeprecatedChar any more. + +2009-01-03 Sam Weinig <sam@webkit.org> + + Reviewed by Oliver Hunt. + + Change the pcVector from storing native code pointers to storing offsets + from the base pointer. This will allow us to generate the pcVector on demand + for exceptions. + + * bytecode/CodeBlock.h: + (JSC::PC::PC): + (JSC::getNativePCOffset): + (JSC::CodeBlock::getBytecodeIndex): + * jit/JIT.cpp: + (JSC::JIT::privateCompile): + +2009-01-02 Oliver Hunt <oliver@apple.com> + + Reviewed by NOBODY (Build fix). + + * runtime/ScopeChain.cpp: + +2009-01-02 Oliver Hunt <oliver@apple.com> + + Reviewed by Gavin Barraclough. + + [jsfunfuzz] unwind logic for exceptions in eval fails to account for dynamic scope external to the eval + https://bugs.webkit.org/show_bug.cgi?id=23078 + + This bug was caused by eval codeblocks being generated without accounting + for the depth of the scope chain they inherited. This meant that exception + handlers would understate their expected scope chain depth, which in turn + led to incorrectly removing nodes from the scope chain. + + * bytecompiler/BytecodeGenerator.cpp: + (JSC::BytecodeGenerator::BytecodeGenerator): + (JSC::BytecodeGenerator::emitCatch): + * bytecompiler/BytecodeGenerator.h: + * interpreter/Interpreter.cpp: + (JSC::depth): + * runtime/ScopeChain.cpp: + (JSC::ScopeChain::localDepth): + * runtime/ScopeChain.h: + (JSC::ScopeChainNode::deref): + (JSC::ScopeChainNode::ref): + +2009-01-02 David Smith <catfish.man@gmail.com> + + Reviewed by Darin Adler. + + https://bugs.webkit.org/show_bug.cgi?id=22699 + Enable NodeList caching for getElementsByTagName + + * wtf/HashFunctions.h: Moved the definition of PHI here and renamed to stringHashingStartValue + +2009-01-02 David Kilzer <ddkilzer@apple.com> + + Attempt to fix Qt Linux build after r39553 + + * wtf/RandomNumberSeed.h: Include <sys/time.h> for gettimeofday(). + Include <sys/types.h> and <unistd.h> for getpid(). + +2009-01-02 David Kilzer <ddkilzer@apple.com> + + Bug 23081: These files are no longer part of the KDE libraries + + <https://bugs.webkit.org/show_bug.cgi?id=23081> + + Reviewed by Darin Adler. + + Removed "This file is part of the KDE libraries" comment from + source files. Added or updated Apple copyrights as well. + + * parser/Lexer.h: + * wtf/HashCountedSet.h: + * wtf/RetainPtr.h: + * wtf/VectorTraits.h: + +2009-01-02 David Kilzer <ddkilzer@apple.com> + + Bug 23080: Remove last vestiges of KJS references + + <https://bugs.webkit.org/show_bug.cgi?id=23080> + + Reviewed by Darin Adler. + + Also updated Apple copyright statements. + + * DerivedSources.make: Changed bison "kjsyy" prefix to "jscyy". + * GNUmakefile.am: Ditto. + * JavaScriptCore.pri: Ditto. Also changed KJSBISON to JSCBISON + and kjsbison to jscbison. + + * JavaScriptCoreSources.bkl: Changed JSCORE_KJS_SOURCES to + JSCORE_JSC_SOURCES. + * jscore.bkl: Ditto. + + * create_hash_table: Updated copyright and removed old comment. + + * parser/Grammar.y: Changed "kjsyy" prefix to "jscyy" prefix. + * parser/Lexer.cpp: Ditto. Also changed KJS_DEBUG_LEX to + JSC_DEBUG_LEX. + (jscyylex): + (JSC::Lexer::lex): + * parser/Parser.cpp: Ditto. + (JSC::Parser::parse): + + * pcre/dftables: Changed "kjs_pcre_" prefix to "jsc_pcre_". + * pcre/pcre_compile.cpp: Ditto. + (getOthercaseRange): + (encodeUTF8): + (compileBranch): + (calculateCompiledPatternLength): + * pcre/pcre_exec.cpp: Ditto. + (matchRef): + (getUTF8CharAndIncrementLength): + (match): + * pcre/pcre_internal.h: Ditto. + (toLowerCase): + (flipCase): + (classBitmapForChar): + (charTypeForChar): + * pcre/pcre_tables.cpp: Ditto. + * pcre/pcre_ucp_searchfuncs.cpp: Ditto. + (jsc_pcre_ucp_othercase): + * pcre/pcre_xclass.cpp: Ditto. + (getUTF8CharAndAdvancePointer): + (jsc_pcre_xclass): + + * runtime/Collector.h: Updated header guards using the + clean-header-guards script. + * runtime/CollectorHeapIterator.h: Added missing header guard. + * runtime/Identifier.h: Updated header guards. + * runtime/JSFunction.h: Fixed end-of-namespace comment. + + * runtime/JSGlobalObject.cpp: + (JSC::JSGlobalObject::reset): Renamed "kjsprint" debug function + to "jscprint". Changed implementation method from + globalFuncKJSPrint() to globalFuncJSCPrint(). + * runtime/JSGlobalObjectFunctions.cpp: + (JSC::globalFuncJSCPrint): Renamed from globalFuncKJSPrint(). + * runtime/JSGlobalObjectFunctions.h: Ditto. + + * runtime/JSImmediate.h: Updated header guards. + * runtime/JSLock.h: Ditto. + * runtime/JSType.h: Ditto. + * runtime/JSWrapperObject.h: Ditto. + * runtime/Lookup.h: Ditto. + * runtime/Operations.h: Ditto. + * runtime/Protect.h: Ditto. + * runtime/RegExp.h: Ditto. + * runtime/UString.h: Ditto. + + * tests/mozilla/js1_5/Array/regress-157652.js: Changed "KJS" + reference in comment to "JSC". + + * wrec/CharacterClassConstructor.cpp: Change "kjs_pcre_" function + prefixes to "jsc_pcre_". + (JSC::WREC::CharacterClassConstructor::put): + (JSC::WREC::CharacterClassConstructor::flush): + + * wtf/unicode/Unicode.h: Change "KJS_" header guard to "WTF_". + * wtf/unicode/icu/UnicodeIcu.h: Ditto. + * wtf/unicode/qt4/UnicodeQt4.h: Ditto. + +2009-01-02 Oliver Hunt <oliver@apple.com> + + Reviewed by Maciej Stachowiak. + + Make randomNumber generate 2^53 values instead of 2^32 (or 2^31 for rand() platforms) + + * wtf/RandomNumber.cpp: + (WTF::randomNumber): + +2009-01-02 David Kilzer <ddkilzer@apple.com> + + Remove declaration for JSC::Identifier::initializeIdentifierThreading() + + Reviewed by Alexey Proskuryakov. + + * runtime/Identifier.h: + (JSC::Identifier::initializeIdentifierThreading): Removed + declaration since the implementation was removed in r34412. + +2009-01-01 Darin Adler <darin@apple.com> + + Reviewed by Oliver Hunt. + + String.replace does not support $& replacement metacharacter when search term is not a RegExp + <https://bugs.webkit.org/show_bug.cgi?id=21431> + <rdar://problem/6274993> + + Test: fast/js/string-replace-3.html + + * runtime/StringPrototype.cpp: + (JSC::substituteBackreferences): Added a null check here so we won't try to handle $$-$9 + backreferences when the search term is a string, not a RegExp. Added a check for 0 so we + won't try to handle $0 or $00 as a backreference. + (JSC::stringProtoFuncReplace): Added a call to substituteBackreferences. + +2009-01-01 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Darin Adler. + + Allow 32-bit integers to be stored in JSImmediates, on x64-bit. + Presently the top 32-bits of a 64-bit JSImmediate serve as a sign extension of a 31-bit + int stored in the low word (shifted left by one, to make room for a tag). In the new + format, the top 31-bits serve as a sign extension of a 32-bit int, still shifted left by + one. + + The new behavior is enabled using a flag in Platform.h, 'WTF_USE_ALTERNATE_JSIMMEDIATE'. + When this is set the constants defining the range of ints allowed to be stored as + JSImmediate values is extended. The code in JSImmediate.h can safely operate on either + format. This patch updates the JIT so that it can also operate with the new format. + + ~2% progression on x86-64, with & without the JIT, on sunspider & v8 tests. + + * assembler/MacroAssembler.h: + (JSC::MacroAssembler::addPtr): + (JSC::MacroAssembler::orPtr): + (JSC::MacroAssembler::or32): + (JSC::MacroAssembler::rshiftPtr): + (JSC::MacroAssembler::rshift32): + (JSC::MacroAssembler::subPtr): + (JSC::MacroAssembler::xorPtr): + (JSC::MacroAssembler::xor32): + (JSC::MacroAssembler::move): + (JSC::MacroAssembler::compareImm64ForBranch): + (JSC::MacroAssembler::compareImm64ForBranchEquality): + (JSC::MacroAssembler::jePtr): + (JSC::MacroAssembler::jgePtr): + (JSC::MacroAssembler::jlPtr): + (JSC::MacroAssembler::jlePtr): + (JSC::MacroAssembler::jnePtr): + (JSC::MacroAssembler::jnzSubPtr): + (JSC::MacroAssembler::joAddPtr): + (JSC::MacroAssembler::jzSubPtr): + * assembler/X86Assembler.h: + (JSC::X86Assembler::addq_rr): + (JSC::X86Assembler::orq_ir): + (JSC::X86Assembler::subq_ir): + (JSC::X86Assembler::xorq_rr): + (JSC::X86Assembler::sarq_CLr): + (JSC::X86Assembler::sarq_i8r): + (JSC::X86Assembler::cmpq_ir): + * jit/JIT.cpp: + (JSC::JIT::compileOpStrictEq): + (JSC::JIT::privateCompileMainPass): + (JSC::JIT::privateCompileSlowCases): + (JSC::JIT::privateCompileCTIMachineTrampolines): + * jit/JIT.h: + * jit/JITArithmetic.cpp: + (JSC::JIT::compileFastArith_op_lshift): + (JSC::JIT::compileFastArithSlow_op_lshift): + (JSC::JIT::compileFastArith_op_rshift): + (JSC::JIT::compileFastArithSlow_op_rshift): + (JSC::JIT::compileFastArith_op_bitand): + (JSC::JIT::compileFastArithSlow_op_bitand): + (JSC::JIT::compileFastArith_op_mod): + (JSC::JIT::compileFastArithSlow_op_mod): + (JSC::JIT::compileFastArith_op_add): + (JSC::JIT::compileFastArithSlow_op_add): + (JSC::JIT::compileFastArith_op_mul): + (JSC::JIT::compileFastArithSlow_op_mul): + (JSC::JIT::compileFastArith_op_post_inc): + (JSC::JIT::compileFastArithSlow_op_post_inc): + (JSC::JIT::compileFastArith_op_post_dec): + (JSC::JIT::compileFastArithSlow_op_post_dec): + (JSC::JIT::compileFastArith_op_pre_inc): + (JSC::JIT::compileFastArithSlow_op_pre_inc): + (JSC::JIT::compileFastArith_op_pre_dec): + (JSC::JIT::compileFastArithSlow_op_pre_dec): + (JSC::JIT::compileBinaryArithOp): + * jit/JITInlineMethods.h: + (JSC::JIT::getConstantOperand): + (JSC::JIT::getConstantOperandImmediateInt): + (JSC::JIT::isOperandConstantImmediateInt): + (JSC::JIT::isOperandConstant31BitImmediateInt): + (JSC::JIT::emitFastArithDeTagImmediate): + (JSC::JIT::emitFastArithDeTagImmediateJumpIfZero): + (JSC::JIT::emitFastArithReTagImmediate): + (JSC::JIT::emitFastArithImmToInt): + (JSC::JIT::emitFastArithIntToImmNoCheck): + * runtime/JSImmediate.h: + (JSC::JSImmediate::isPositiveNumber): + (JSC::JSImmediate::isNegative): + (JSC::JSImmediate::rightShiftImmediateNumbers): + (JSC::JSImmediate::canDoFastAdditiveOperations): + (JSC::JSImmediate::makeValue): + (JSC::JSImmediate::makeInt): + (JSC::JSImmediate::makeBool): + (JSC::JSImmediate::intValue): + (JSC::JSImmediate::rawValue): + (JSC::JSImmediate::toBoolean): + (JSC::JSImmediate::from): + * wtf/Platform.h: + +2008-12-31 Oliver Hunt <oliver@apple.com> + + Reviewed by Cameron Zwarich. + + [jsfunfuzz] Assertion + incorrect behaviour with dynamically created local variable in a catch block + <https://bugs.webkit.org/show_bug.cgi?id=23063> + + Eval inside a catch block attempts to use the catch block's static scope in + an unsafe way by attempting to add new properties to the scope. This patch + fixes this issue simply by preventing the catch block from using a static + scope if it contains an eval. + + * parser/Grammar.y: + * parser/Nodes.cpp: + (JSC::TryNode::emitBytecode): + * parser/Nodes.h: + (JSC::TryNode::): + +2008-12-31 Oliver Hunt <oliver@apple.com> + + Reviewed by Gavin Barraclough. + + [jsfunfuzz] Computed exception offset wrong when first instruction is attempt to resolve deleted eval + <https://bugs.webkit.org/show_bug.cgi?id=23062> + + This was caused by the expression information for the initial resolve of + eval not being emitted. If this resolve was the first instruction that + could throw an exception the information search would fail leading to an + assertion failure. If it was not the first throwable opcode the wrong + expression information would used. + + Fix is simply to emit the expression info. + + * parser/Nodes.cpp: + (JSC::EvalFunctionCallNode::emitBytecode): + +2008-12-31 Cameron Zwarich <cwzwarich@uwaterloo.ca> + + Reviewed by Oliver Hunt. + + Bug 23054: Caching of global lookups occurs even when the global object has become a dictionary + <https://bugs.webkit.org/show_bug.cgi?id=23054> + <rdar://problem/6469905> + + * interpreter/Interpreter.cpp: + (JSC::Interpreter::resolveGlobal): Do not cache lookup if the global + object has transitioned to a dictionary. + (JSC::Interpreter::cti_op_resolve_global): Do not cache lookup if the + global object has transitioned to a dictionary. + +2008-12-30 Oliver Hunt <oliver@apple.com> + + Reviewed by Darin Adler. + + <https://bugs.webkit.org/show_bug.cgi?id=23049> [jsfunfuzz] With blocks do not correctly protect their scope object + <rdar://problem/6469742> Crash in JSC::TypeInfo::hasStandardGetOwnPropertySlot() running jsfunfuzz + + The problem that caused this was that with nodes were not correctly protecting + the final object that was placed in the scope chain. We correct this by forcing + the use of a temporary register (which stops us relying on a local register + protecting the scope) and changing the behaviour of op_push_scope so that it + will store the final scope object. + + * bytecompiler/BytecodeGenerator.cpp: + (JSC::BytecodeGenerator::emitPushScope): + * interpreter/Interpreter.cpp: + (JSC::Interpreter::privateExecute): + (JSC::Interpreter::cti_op_push_scope): + * interpreter/Interpreter.h: + * jit/JIT.cpp: + (JSC::JIT::privateCompileMainPass): + * parser/Nodes.cpp: + (JSC::WithNode::emitBytecode): + +2008-12-30 Cameron Zwarich <cwzwarich@uwaterloo.ca> + + Reviewed by Sam Weinig. + + Bug 23037: Parsing and reparsing disagree on automatic semicolon insertion + <https://bugs.webkit.org/show_bug.cgi?id=23037> + <rdar://problem/6467124> + + Parsing and reparsing disagree about automatic semicolon insertion, so that a + function like + + function() { a = 1, } + + is parsed as being syntactically valid but gets a syntax error upon reparsing. + This leads to an assertion failure in Parser::reparse(). It is not that big of + an issue in practice, because in a Release build such a function will return + 'undefined' when called. + + In this case, we are not following the spec and it should be a syntax error. + However, unless there is a newline separating the ',' and the '}', WebKit would + not treat it as a syntax error in the past either. It would be a bit of work to + make the automatic semicolon insertion match the spec exactly, so this patch + changes it to match our past behaviour. + + The problem is that even during reparsing, the Lexer adds a semicolon at the + end of the input, which confuses allowAutomaticSemicolon(), because it is + expecting either a '}', the end of input, or a terminator like a newline. + + * parser/Lexer.cpp: + (JSC::Lexer::Lexer): Initialize m_isReparsing to false. + (JSC::Lexer::lex): Do not perform automatic semicolon insertion in the Lexer if + we are in the middle of reparsing. + (JSC::Lexer::clear): Set m_isReparsing to false. + * parser/Lexer.h: + (JSC::Lexer::setIsReparsing): Added. + * parser/Parser.cpp: + (JSC::Parser::reparse): Call Lexer::setIsReparsing() to notify the Lexer of + reparsing. + +2008-12-29 Oliver Hunt <oliver@apple.com> + + Reviewed by NOBODY (Build fix). + + Yet another attempt to fix Tiger. + + * wtf/RandomNumber.cpp: + (WTF::randomNumber): + +2008-12-29 Oliver Hunt <oliver@apple.com> + + Reviewed by NOBODY (Build fix). + + Tiger build fix (correct this time) + + * wtf/RandomNumber.cpp: + +2008-12-29 Cameron Zwarich <cwzwarich@uwaterloo.ca> + + Rubber-stamped by Alexey Proskuryakov. + + Revert r39509, because kjsyydebug is used in the generated code if YYDEBUG is 1. + + * parser/Grammar.y: + +2008-12-29 Oliver Hunt <oliver@apple.com> + + Reviewed by NOBODY (Build fix). + + Tiger build fix. + + * wtf/RandomNumber.cpp: + +2008-12-29 Oliver Hunt <oliver@apple.com> + + Reviewed by Mark Rowe. + + <rdar://problem/6358108> Insecure randomness in Math.random() leads to user tracking + + Switch to arc4random on PLATFORM(DARWIN), this is ~1.5x slower than random(), but the + it is still so fast that there is no fathomable way it could be a bottleneck for anything. + + randomNumber is called in two places + * During form submission where it is called once per form + * Math.random in JSC. For this difference to show up you have to be looping on + a cached local copy of random, for a large (>10000) calls. + + No change in SunSpider. + + * wtf/RandomNumber.cpp: + (WTF::randomNumber): + * wtf/RandomNumberSeed.h: + (WTF::initializeRandomNumberGenerator): + +2008-12-29 Cameron Zwarich <cwzwarich@uwaterloo.ca> + + Rubber-stamped by Sam Weinig. + + Remove unused kjsyydebug #define. + + * parser/Grammar.y: + +2008-12-29 Cameron Zwarich <cwzwarich@uwaterloo.ca> + + Reviewed by Oliver Hunt and Sam Weinig. + + Bug 23029: REGRESSION (r39337): jsfunfuzz generates identical test files + <https://bugs.webkit.org/show_bug.cgi?id=23029> + <rdar://problem/6469185> + + The unification of random number generation in r39337 resulted in random() + being initialized on Darwin, but rand() actually being used. Fix this by + making randomNumber() use random() instead of rand() on Darwin. + + * wtf/RandomNumber.cpp: + (WTF::randomNumber): + +2008-12-29 Sam Weinig <sam@webkit.org> + + Fix buildbots. + + * runtime/Structure.cpp: + +2008-12-29 Sam Weinig <sam@webkit.org> + + Reviewed by Oliver Hunt. + + Patch for https://bugs.webkit.org/show_bug.cgi?id=23026 + Move the deleted offsets vector into the PropertyMap + + Saves 3 words per Structure. + + * runtime/PropertyMapHashTable.h: + * runtime/Structure.cpp: + (JSC::Structure::addPropertyTransition): + (JSC::Structure::changePrototypeTransition): + (JSC::Structure::getterSetterTransition): + (JSC::Structure::toDictionaryTransition): + (JSC::Structure::fromDictionaryTransition): + (JSC::Structure::copyPropertyTable): + (JSC::Structure::put): + (JSC::Structure::remove): + (JSC::Structure::rehashPropertyMapHashTable): + * runtime/Structure.h: + (JSC::Structure::propertyStorageSize): + +2008-12-29 Cameron Zwarich <cwzwarich@uwaterloo.ca> + + Reviewed by Oliver Hunt. + + Change code using m_body.get() as a boolean to take advantage of the + implicit conversion of RefPtr to boolean. + + * runtime/JSFunction.cpp: + (JSC::JSFunction::~JSFunction): + +2008-12-28 Cameron Zwarich <cwzwarich@uwaterloo.ca> + + Reviewed by Oliver Hunt. + + Bug 22840: REGRESSION (r38349): Gmail doesn't load with profiling enabled + <https://bugs.webkit.org/show_bug.cgi?id=22840> + <rdar://problem/6468077> + + * bytecompiler/BytecodeGenerator.cpp: + (JSC::BytecodeGenerator::emitNewArray): Add an assertion that the range + of registers passed to op_new_array is sequential. + (JSC::BytecodeGenerator::emitCall): Correct the relocation of registers + when emitting profiler hooks so that registers aren't leaked. Also, add + an assertion that the 'this' register is always ref'd (because it is), + remove the needless protection of the 'this' register when relocating, + and add an assertion that the range of registers passed to op_call for + function call arguments is sequential. + (JSC::BytecodeGenerator::emitConstruct): Correct the relocation of + registers when emitting profiler hooks so that registers aren't leaked. + Also, add an assertion that the range of registers passed to op_construct + for function call arguments is sequential. + +2008-12-26 Mark Rowe <mrowe@apple.com> + + Reviewed by Alexey Proskuryakov. + + <rdar://problem/6467376> Race condition in WTF::currentThread can lead to a thread using two different identifiers during its lifetime + + If a newly-created thread calls WTF::currentThread() before WTF::createThread calls establishIdentifierForPthreadHandle + then more than one identifier will be used for the same thread. We can avoid this by adding some extra synchronization + during thread creation that delays the execution of the thread function until the thread identifier has been set up, and + an assertion to catch this problem should it reappear in the future. + + * wtf/Threading.cpp: Added. + (WTF::NewThreadContext::NewThreadContext): + (WTF::threadEntryPoint): + (WTF::createThread): Add cross-platform createThread function that delays the execution of the thread function until + after the thread identifier has been set up. + * wtf/Threading.h: + * wtf/ThreadingGtk.cpp: + (WTF::establishIdentifierForThread): + (WTF::createThreadInternal): + * wtf/ThreadingNone.cpp: + (WTF::createThreadInternal): + * wtf/ThreadingPthreads.cpp: + (WTF::establishIdentifierForPthreadHandle): + (WTF::createThreadInternal): + * wtf/ThreadingQt.cpp: + (WTF::identifierByQthreadHandle): + (WTF::establishIdentifierForThread): + (WTF::createThreadInternal): + * wtf/ThreadingWin.cpp: + (WTF::storeThreadHandleByIdentifier): + (WTF::createThreadInternal): + + Add Threading.cpp to the build. + + * GNUmakefile.am: + * JavaScriptCore.pri: + * JavaScriptCore.scons: + * JavaScriptCore.vcproj/WTF/WTF.vcproj: + * JavaScriptCore.xcodeproj/project.pbxproj: + * JavaScriptCoreSources.bkl: + +2008-12-26 Sam Weinig <sam@webkit.org> + + Reviewed by Alexey Proskuryakov. + + Remove unused method. + + * runtime/Structure.h: Remove mutableTypeInfo. + +2008-12-22 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Oliver Hunt. + + Fix rounding / bounds / signed comparison bug in ExecutableAllocator. + + ExecutableAllocator::alloc assumed that m_freePtr would be aligned. This was + not always true, since the first allocation from an additional pool would not + be rounded up. Subsequent allocations would be unaligned, and too much memory + could be erroneously allocated from the pool, when the size requested was + available, but the size rounded up to word granularity was not available in the + pool. This may result in the value of m_freePtr being greater than m_end. + + Under these circumstances, the unsigned check for space will always pass, + resulting in pointers to memory outside of the arena being returned, and + ultimately segfaulty goodness when attempting to memcpy the hot freshly jitted + code from the AssemblerBuffer. + + https://bugs.webkit.org/show_bug.cgi?id=22974 + ... and probably many, many more. + + * jit/ExecutableAllocator.h: + (JSC::ExecutablePool::alloc): + (JSC::ExecutablePool::roundUpAllocationSize): + (JSC::ExecutablePool::ExecutablePool): + (JSC::ExecutablePool::poolAllocate): + +2008-12-22 Sam Weinig <sam@webkit.org> + + Reviewed by Gavin Barraclough. + + Rename all uses of the term "repatch" to "patch". + + * assembler/MacroAssembler.h: + (JSC::MacroAssembler::DataLabelPtr::patch): + (JSC::MacroAssembler::DataLabel32::patch): + (JSC::MacroAssembler::Jump::patch): + (JSC::MacroAssembler::PatchBuffer::PatchBuffer): + (JSC::MacroAssembler::PatchBuffer::setPtr): + (JSC::MacroAssembler::loadPtrWithAddressOffsetPatch): + (JSC::MacroAssembler::storePtrWithAddressOffsetPatch): + (JSC::MacroAssembler::storePtrWithPatch): + (JSC::MacroAssembler::jnePtrWithPatch): + * assembler/X86Assembler.h: + (JSC::X86Assembler::patchAddress): + (JSC::X86Assembler::patchImmediate): + (JSC::X86Assembler::patchPointer): + (JSC::X86Assembler::patchBranchOffset): + * interpreter/Interpreter.cpp: + (JSC::Interpreter::tryCTICachePutByID): + (JSC::Interpreter::tryCTICacheGetByID): + (JSC::Interpreter::cti_op_put_by_id): + (JSC::Interpreter::cti_op_get_by_id): + (JSC::Interpreter::cti_op_get_by_id_self_fail): + (JSC::Interpreter::cti_op_get_by_id_proto_list): + (JSC::Interpreter::cti_vm_dontLazyLinkCall): + * jit/JIT.cpp: + (JSC::ctiPatchCallByReturnAddress): + (JSC::JIT::privateCompileMainPass): + (JSC::JIT::privateCompile): + (JSC::JIT::privateCompileCTIMachineTrampolines): + * jit/JIT.h: + * jit/JITCall.cpp: + (JSC::JIT::unlinkCall): + (JSC::JIT::linkCall): + (JSC::JIT::compileOpCall): + * jit/JITPropertyAccess.cpp: + (JSC::JIT::compileGetByIdHotPath): + (JSC::JIT::compilePutByIdHotPath): + (JSC::JIT::compileGetByIdSlowCase): + (JSC::JIT::compilePutByIdSlowCase): + (JSC::JIT::privateCompilePutByIdTransition): + (JSC::JIT::patchGetByIdSelf): + (JSC::JIT::patchPutByIdReplace): + (JSC::JIT::privateCompilePatchGetArrayLength): + (JSC::JIT::privateCompileGetByIdSelf): + (JSC::JIT::privateCompileGetByIdProto): + (JSC::JIT::privateCompileGetByIdSelfList): + (JSC::JIT::privateCompileGetByIdProtoList): + (JSC::JIT::privateCompileGetByIdChainList): + (JSC::JIT::privateCompileGetByIdChain): + (JSC::JIT::privateCompilePutByIdReplace): + +2008-12-22 Adam Roben <aroben@apple.com> + + Build fix after r39428 + + * jit/JITCall.cpp: + (JSC::JIT::compileOpCallSlowCase): Added a missing MacroAssembler:: + +2008-12-22 Nikolas Zimmermann <nikolas.zimmermann@torchmobile.com> + + Rubber-stamped by George Staikos. + + Unify all TorchMobile copyright lines. Consolidate in a single line, as requested by Mark Rowe, some time ago. + + * wtf/RandomNumber.cpp: + * wtf/RandomNumber.h: + * wtf/RandomNumberSeed.h: + +2008-12-21 Nikolas Zimmermann <nikolas.zimmermann@torchmobile.com> + + Rubber-stamped by George Staikos. + + Fix copyright of the new RandomNumber* files. + + * wtf/RandomNumber.cpp: + * wtf/RandomNumber.h: + * wtf/RandomNumberSeed.h: + +2008-12-21 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Oliver Hunt & Cameron Zwarich. + + Add support for call and property access repatching on x86-64. + + No change in performance on current configurations (2x impovement on v8-tests with JIT enabled on x86-64). + + * assembler/MacroAssembler.h: + (JSC::MacroAssembler::DataLabelPtr::repatch): + (JSC::MacroAssembler::DataLabelPtr::operator X86Assembler::JmpDst): + (JSC::MacroAssembler::DataLabel32::repatch): + (JSC::MacroAssembler::RepatchBuffer::addressOf): + (JSC::MacroAssembler::add32): + (JSC::MacroAssembler::sub32): + (JSC::MacroAssembler::loadPtrWithAddressOffsetRepatch): + (JSC::MacroAssembler::storePtrWithAddressOffsetRepatch): + (JSC::MacroAssembler::jePtr): + (JSC::MacroAssembler::jnePtr): + (JSC::MacroAssembler::jnePtrWithRepatch): + (JSC::MacroAssembler::differenceBetween): + * assembler/X86Assembler.h: + (JSC::X86Assembler::addl_im): + (JSC::X86Assembler::subl_im): + (JSC::X86Assembler::cmpl_rm): + (JSC::X86Assembler::movq_rm_disp32): + (JSC::X86Assembler::movq_mr_disp32): + (JSC::X86Assembler::repatchPointer): + (JSC::X86Assembler::X86InstructionFormatter::oneByteOp64_disp32): + * jit/JIT.cpp: + (JSC::JIT::privateCompile): + (JSC::JIT::privateCompileCTIMachineTrampolines): + * jit/JIT.h: + * jit/JITCall.cpp: + (JSC::JIT::unlinkCall): + (JSC::JIT::linkCall): + (JSC::JIT::compileOpCall): + (JSC::JIT::compileOpCallSlowCase): + * jit/JITInlineMethods.h: + (JSC::JIT::restoreArgumentReferenceForTrampoline): + * jit/JITPropertyAccess.cpp: + (JSC::JIT::compileGetByIdHotPath): + (JSC::JIT::compileGetByIdSlowCase): + (JSC::JIT::compilePutByIdHotPath): + (JSC::JIT::compilePutByIdSlowCase): + (JSC::resizePropertyStorage): + (JSC::JIT::privateCompilePutByIdTransition): + (JSC::JIT::privateCompileGetByIdProto): + (JSC::JIT::privateCompileGetByIdProtoList): + (JSC::JIT::privateCompileGetByIdChainList): + (JSC::JIT::privateCompileGetByIdChain): + * wtf/Platform.h: + +2008-12-20 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Oliver Hunt. + + Port optimized property access generation to the MacroAssembler. + + * assembler/MacroAssembler.h: + (JSC::MacroAssembler::AbsoluteAddress::AbsoluteAddress): + (JSC::MacroAssembler::DataLabelPtr::repatch): + (JSC::MacroAssembler::DataLabel32::DataLabel32): + (JSC::MacroAssembler::DataLabel32::repatch): + (JSC::MacroAssembler::Label::operator X86Assembler::JmpDst): + (JSC::MacroAssembler::Jump::repatch): + (JSC::MacroAssembler::JumpList::empty): + (JSC::MacroAssembler::RepatchBuffer::link): + (JSC::MacroAssembler::add32): + (JSC::MacroAssembler::and32): + (JSC::MacroAssembler::sub32): + (JSC::MacroAssembler::loadPtrWithAddressRepatch): + (JSC::MacroAssembler::storePtrWithAddressRepatch): + (JSC::MacroAssembler::push): + (JSC::MacroAssembler::ja32): + (JSC::MacroAssembler::jePtr): + (JSC::MacroAssembler::jnePtr): + (JSC::MacroAssembler::jnePtrWithRepatch): + (JSC::MacroAssembler::align): + (JSC::MacroAssembler::differenceBetween): + * assembler/X86Assembler.h: + (JSC::X86Assembler::movl_rm_disp32): + (JSC::X86Assembler::movl_mr_disp32): + (JSC::X86Assembler::X86InstructionFormatter::oneByteOp_disp32): + (JSC::X86Assembler::X86InstructionFormatter::memoryModRM): + * jit/JIT.cpp: + (JSC::ctiRepatchCallByReturnAddress): + (JSC::JIT::privateCompileMainPass): + (JSC::JIT::privateCompile): + (JSC::JIT::privateCompileCTIMachineTrampolines): + * jit/JIT.h: + * jit/JITPropertyAccess.cpp: + (JSC::JIT::compileGetByIdHotPath): + (JSC::JIT::compileGetByIdSlowCase): + (JSC::JIT::compilePutByIdHotPath): + (JSC::JIT::compilePutByIdSlowCase): + (JSC::resizePropertyStorage): + (JSC::JIT::privateCompilePutByIdTransition): + (JSC::JIT::patchGetByIdSelf): + (JSC::JIT::patchPutByIdReplace): + (JSC::JIT::privateCompilePatchGetArrayLength): + (JSC::JIT::privateCompileGetByIdSelf): + (JSC::JIT::privateCompileGetByIdProto): + (JSC::JIT::privateCompileGetByIdSelfList): + (JSC::JIT::privateCompileGetByIdProtoList): + (JSC::JIT::privateCompileGetByIdChainList): + (JSC::JIT::privateCompileGetByIdChain): + (JSC::JIT::privateCompilePutByIdReplace): + * wtf/RefCounted.h: + (WTF::RefCountedBase::addressOfCount): + +2008-12-19 Gustavo Noronha Silva <gns@gnome.org> + + Reviewed by Holger Freyther. + + https://bugs.webkit.org/show_bug.cgi?id=22686 + + Added file which was missing to the javascriptcore_sources + variable, so that it shows up in the tarball created by `make + dist'. + + * GNUmakefile.am: + +2008-12-19 Holger Hans Peter Freyther <zecke@selfish.org> + + Reviewed by Antti Koivisto. + + Build fix when building JS API tests with a c89 c compiler + + Do not use C++ style comments and convert them to C comments. + + * wtf/Platform.h: + +2008-12-18 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Sam Weinig. + + Same as last revision, adding cases for pre & post inc & dec. + + https://bugs.webkit.org/show_bug.cgi?id=22928 + + * jit/JIT.cpp: + (JSC::JIT::privateCompileMainPass): + +2008-12-18 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Sam Weinig. + + Fixes for the JIT's handling of JSImmediate values on x86-64. + On 64-bit systems, the code in JSImmediate.h relies on the upper + bits of a JSImmediate being a sign extension of the low 32-bits. + This was not being enforced by the JIT, since a number of inline + operations were being performed on 32-bit values in registers, and + when a 32-bit result is written to a register on x86-64 the value + is zero-extended to 64-bits. + + This fix honors previous behavoir. A better fix in the long run + (when the JIT is enabled by default) may be to change JSImmediate.h + so it no longer relies on the upper bits of the pointer,... though + if we're going to change JSImmediate.h for 64-bit, we probably may + as well change the format so that the full range of 32-bit ints can + be stored, rather than just 31-bits. + + https://bugs.webkit.org/show_bug.cgi?id=22925 + + * assembler/MacroAssembler.h: + (JSC::MacroAssembler::addPtr): + (JSC::MacroAssembler::andPtr): + (JSC::MacroAssembler::orPtr): + (JSC::MacroAssembler::or32): + (JSC::MacroAssembler::xor32): + (JSC::MacroAssembler::xorPtr): + (JSC::MacroAssembler::signExtend32ToPtr): + * assembler/X86Assembler.h: + (JSC::X86Assembler::): + (JSC::X86Assembler::andq_rr): + (JSC::X86Assembler::andq_ir): + (JSC::X86Assembler::orq_rr): + (JSC::X86Assembler::xorq_ir): + (JSC::X86Assembler::movsxd_rr): + * jit/JIT.cpp: + (JSC::JIT::privateCompileMainPass): + * jit/JITInlineMethods.h: + (JSC::JIT::emitFastArithReTagImmediate): + (JSC::JIT::emitFastArithPotentiallyReTagImmediate): + (JSC::JIT::emitFastArithImmToInt): + +2008-12-18 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Sam Weinig. + + Just a tidy up - rename & refactor some the #defines configuring the JIT. + + * interpreter/Interpreter.cpp: + (JSC::Interpreter::cti_op_convert_this): + (JSC::Interpreter::cti_op_end): + (JSC::Interpreter::cti_op_add): + (JSC::Interpreter::cti_op_pre_inc): + (JSC::Interpreter::cti_timeout_check): + (JSC::Interpreter::cti_register_file_check): + (JSC::Interpreter::cti_op_loop_if_less): + (JSC::Interpreter::cti_op_loop_if_lesseq): + (JSC::Interpreter::cti_op_new_object): + (JSC::Interpreter::cti_op_put_by_id_generic): + (JSC::Interpreter::cti_op_get_by_id_generic): + (JSC::Interpreter::cti_op_put_by_id): + (JSC::Interpreter::cti_op_put_by_id_second): + (JSC::Interpreter::cti_op_put_by_id_fail): + (JSC::Interpreter::cti_op_get_by_id): + (JSC::Interpreter::cti_op_get_by_id_second): + (JSC::Interpreter::cti_op_get_by_id_self_fail): + (JSC::Interpreter::cti_op_get_by_id_proto_list): + (JSC::Interpreter::cti_op_get_by_id_proto_list_full): + (JSC::Interpreter::cti_op_get_by_id_proto_fail): + (JSC::Interpreter::cti_op_get_by_id_array_fail): + (JSC::Interpreter::cti_op_get_by_id_string_fail): + (JSC::Interpreter::cti_op_instanceof): + (JSC::Interpreter::cti_op_del_by_id): + (JSC::Interpreter::cti_op_mul): + (JSC::Interpreter::cti_op_new_func): + (JSC::Interpreter::cti_op_call_JSFunction): + (JSC::Interpreter::cti_op_call_arityCheck): + (JSC::Interpreter::cti_vm_dontLazyLinkCall): + (JSC::Interpreter::cti_vm_lazyLinkCall): + (JSC::Interpreter::cti_op_push_activation): + (JSC::Interpreter::cti_op_call_NotJSFunction): + (JSC::Interpreter::cti_op_create_arguments): + (JSC::Interpreter::cti_op_create_arguments_no_params): + (JSC::Interpreter::cti_op_tear_off_activation): + (JSC::Interpreter::cti_op_tear_off_arguments): + (JSC::Interpreter::cti_op_profile_will_call): + (JSC::Interpreter::cti_op_profile_did_call): + (JSC::Interpreter::cti_op_ret_scopeChain): + (JSC::Interpreter::cti_op_new_array): + (JSC::Interpreter::cti_op_resolve): + (JSC::Interpreter::cti_op_construct_JSConstruct): + (JSC::Interpreter::cti_op_construct_NotJSConstruct): + (JSC::Interpreter::cti_op_get_by_val): + (JSC::Interpreter::cti_op_resolve_func): + (JSC::Interpreter::cti_op_sub): + (JSC::Interpreter::cti_op_put_by_val): + (JSC::Interpreter::cti_op_put_by_val_array): + (JSC::Interpreter::cti_op_lesseq): + (JSC::Interpreter::cti_op_loop_if_true): + (JSC::Interpreter::cti_op_negate): + (JSC::Interpreter::cti_op_resolve_base): + (JSC::Interpreter::cti_op_resolve_skip): + (JSC::Interpreter::cti_op_resolve_global): + (JSC::Interpreter::cti_op_div): + (JSC::Interpreter::cti_op_pre_dec): + (JSC::Interpreter::cti_op_jless): + (JSC::Interpreter::cti_op_not): + (JSC::Interpreter::cti_op_jtrue): + (JSC::Interpreter::cti_op_post_inc): + (JSC::Interpreter::cti_op_eq): + (JSC::Interpreter::cti_op_lshift): + (JSC::Interpreter::cti_op_bitand): + (JSC::Interpreter::cti_op_rshift): + (JSC::Interpreter::cti_op_bitnot): + (JSC::Interpreter::cti_op_resolve_with_base): + (JSC::Interpreter::cti_op_new_func_exp): + (JSC::Interpreter::cti_op_mod): + (JSC::Interpreter::cti_op_less): + (JSC::Interpreter::cti_op_neq): + (JSC::Interpreter::cti_op_post_dec): + (JSC::Interpreter::cti_op_urshift): + (JSC::Interpreter::cti_op_bitxor): + (JSC::Interpreter::cti_op_new_regexp): + (JSC::Interpreter::cti_op_bitor): + (JSC::Interpreter::cti_op_call_eval): + (JSC::Interpreter::cti_op_throw): + (JSC::Interpreter::cti_op_get_pnames): + (JSC::Interpreter::cti_op_next_pname): + (JSC::Interpreter::cti_op_push_scope): + (JSC::Interpreter::cti_op_pop_scope): + (JSC::Interpreter::cti_op_typeof): + (JSC::Interpreter::cti_op_is_undefined): + (JSC::Interpreter::cti_op_is_boolean): + (JSC::Interpreter::cti_op_is_number): + (JSC::Interpreter::cti_op_is_string): + (JSC::Interpreter::cti_op_is_object): + (JSC::Interpreter::cti_op_is_function): + (JSC::Interpreter::cti_op_stricteq): + (JSC::Interpreter::cti_op_nstricteq): + (JSC::Interpreter::cti_op_to_jsnumber): + (JSC::Interpreter::cti_op_in): + (JSC::Interpreter::cti_op_push_new_scope): + (JSC::Interpreter::cti_op_jmp_scopes): + (JSC::Interpreter::cti_op_put_by_index): + (JSC::Interpreter::cti_op_switch_imm): + (JSC::Interpreter::cti_op_switch_char): + (JSC::Interpreter::cti_op_switch_string): + (JSC::Interpreter::cti_op_del_by_val): + (JSC::Interpreter::cti_op_put_getter): + (JSC::Interpreter::cti_op_put_setter): + (JSC::Interpreter::cti_op_new_error): + (JSC::Interpreter::cti_op_debug): + (JSC::Interpreter::cti_vm_throw): + * interpreter/Interpreter.h: + * jit/JIT.cpp: + (JSC::): + (JSC::JIT::privateCompileMainPass): + (JSC::JIT::privateCompile): + * jit/JIT.h: + * jit/JITInlineMethods.h: + (JSC::JIT::restoreArgumentReference): + (JSC::JIT::restoreArgumentReferenceForTrampoline): + * wtf/Platform.h: + +2008-12-18 Cameron Zwarich <zwarich@apple.com> + + Reviewed by Geoff Garen. + + Bug 21855: REGRESSION (r37323): Gmail complains about popup blocking when opening a link + <https://bugs.webkit.org/show_bug.cgi?id=21855> + <rdar://problem/6278244> + + Move DynamicGlobalObjectScope to JSGlobalObject.h so that it can be used + from WebCore. + + * interpreter/Interpreter.cpp: + * runtime/JSGlobalObject.h: + (JSC::DynamicGlobalObjectScope::DynamicGlobalObjectScope): + (JSC::DynamicGlobalObjectScope::~DynamicGlobalObjectScope): + +2008-12-17 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Gavin Barraclough. + + Fixed https://bugs.webkit.org/show_bug.cgi?id=22393 + Segfault when caching property accesses to primitive cells. + + Changed some asObject casts to asCell casts in cases where a primitive + value may be a cell and not an object. + + Re-enabled property caching for primitives in cases where it had been + disabled because of this bug. + + Updated a comment to better explain something Darin thought needed + explaining in an old patch review. + + * interpreter/Interpreter.cpp: + (JSC::countPrototypeChainEntriesAndCheckForProxies): + (JSC::Interpreter::tryCacheGetByID): + (JSC::Interpreter::tryCTICacheGetByID): + (JSC::Interpreter::cti_op_get_by_id_self_fail): + (JSC::Interpreter::cti_op_get_by_id_proto_list): + +2008-12-17 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Cameron Zwarich. + + Fixes for Sunspider failures with the JIT enabled on x86-64. + + * assembler/MacroAssembler.h: + Switch the order of the RegisterID & Address form of je32, to keep it consistent with jne32. + * jit/JIT.cpp: + * jit/JIT.h: + * jit/JITInlineMethods.h: + Port the m_ctiVirtualCall tramopline generation to use the MacroAssembler interface. + * jit/JITCall.cpp: + Fix bug in the non-optimizing code path, vptr check should have been to the memory address pointer + to by the register, not to the register itself. + * wrec/WRECGenerator.cpp: + See assembler/MacroAssembler.h, above. + +2008-12-17 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Sam Weinig. + + print("Hello, 64-bit jitted world!"); + Get hello-world working through the JIT, on x86-64. + + * assembler/X86Assembler.h: + Fix encoding of opcode + RegisterID format instructions for 64-bit. + * interpreter/Interpreter.cpp: + * interpreter/Interpreter.h: + Make VoidPtrPair actually be a pair of void*s. + (Possibly should make this change for 32-bit Mac platforms, too - but won't change 32-bit behaviour in this patch). + * jit/JIT.cpp: + * jit/JIT.h: + Provide names for the timeoutCheckRegister & callFrameRegister on x86-64, + force x86-64 ctiTrampoline arguments onto the stack, + implement the asm trampolines for x86-64, + implement the restoreArgumentReference methods for x86-64 calling conventions. + * jit/JITCall.cpp: + * jit/JITInlineMethods.h: + * wtf/Platform.h: + Add switch settings to ENABLE(JIT), on PLATFORM(X86_64) (currently still disabled). + +2008-12-17 Sam Weinig <sam@webkit.org> + + Reviewed by Gavin Barraclough. + + Add more CodeBlock statistics. + + * bytecode/CodeBlock.cpp: + (JSC::CodeBlock::dumpStatistics): + +2008-12-17 Sam Weinig <sam@webkit.org> + + Reviewed by Darin Adler. + + Fix for https://bugs.webkit.org/show_bug.cgi?id=22897 + <rdar://problem/6428342> + Look into feasibility of discarding bytecode after native codegen + + Clear the bytecode Instruction vector at the end JIT generation. + + Saves 4.8 MB on Membuster head. + + * bytecode/CodeBlock.cpp: + (JSC::CodeBlock::dump): Add logging for the case that someone tries + to dump the instructions of a CodeBlock that has had its bytecode + vector cleared. + (JSC::CodeBlock::CodeBlock): Initialize the instructionCount + (JSC::CodeBlock::handlerForBytecodeOffset): Use instructionCount instead + of the size of the instruction vector in the assertion. + (JSC::CodeBlock::lineNumberForBytecodeOffset): Ditto. + (JSC::CodeBlock::expressionRangeForBytecodeOffset): Ditto. + (JSC::CodeBlock::getByIdExceptionInfoForBytecodeOffset): Ditto. + (JSC::CodeBlock::functionRegisterForBytecodeOffset): Ditto. + * bytecode/CodeBlock.h: + (JSC::CodeBlock::setInstructionCount): Store the instruction vector size + in debug builds for assertions. + * bytecompiler/BytecodeGenerator.cpp: + (JSC::BytecodeGenerator::generate): + * jit/JIT.cpp: + (JSC::JIT::privateCompile): Clear the bytecode vector unless we + have compiled with Opcode sampling where we will continue to require it + +2008-12-17 Cary Clark <caryclark@google.com> + + Reviewed by Darin Adler. + Landed by Adam Barth. + + Add ENABLE_TEXT_CARET to permit the ANDROID platform + to invalidate and draw the caret in a separate thread. + + * wtf/Platform.h: + Default ENABLE_TEXT_CARET to 1. + +2008-12-17 Alexey Proskuryakov <ap@webkit.org> + + Reviewed by Darin Adler. + + Don't use unique context group in JSGlobalContextCreate() on Tiger or Leopard, take two. + + * API/JSContextRef.cpp: The previous patch that claimed to do this was making Tiger and + Leopard always use unique context group instead. + +2008-12-16 Sam Weinig <sam@webkit.org> + + Reviewed by Geoffrey Garen. + + Fix for https://bugs.webkit.org/show_bug.cgi?id=22838 + Remove dependency on the bytecode Instruction buffer in Interpreter::throwException + Part of <rdar://problem/6428342> + + * bytecode/CodeBlock.cpp: + (JSC::CodeBlock::functionRegisterForBytecodeOffset): Added. Function to get + a function Register index in a callFrame for a bytecode offset. + (JSC::CodeBlock::shrinkToFit): Shrink m_getByIdExceptionInfo and m_functionRegisterInfos. + * bytecode/CodeBlock.h: + (JSC::FunctionRegisterInfo::FunctionRegisterInfo): Added. + (JSC::CodeBlock::addFunctionRegisterInfo): + * bytecompiler/BytecodeGenerator.cpp: + (JSC::BytecodeGenerator::emitCall): + * interpreter/Interpreter.cpp: + (JSC::Interpreter::throwException): Use functionRegisterForBytecodeOffset in JIT + mode. + +2008-12-16 Sam Weinig <sam@webkit.org> + + Reviewed by Gavin Barraclough. + + Fix for https://bugs.webkit.org/show_bug.cgi?id=22837 + Remove dependency on the bytecode Instruction buffer in Interpreter::cti_op_call_NotJSFunction + Part of <rdar://problem/6428342> + + * interpreter/CallFrame.h: Added comment regarding returnPC storing a void*. + * interpreter/Interpreter.cpp: + (JSC::bytecodeOffsetForPC): We no longer have any cases of the PC + being in the instruction stream for JIT, so we can remove the check. + (JSC::Interpreter::cti_op_call_NotJSFunction): Use the CTI_RETURN_ADDRESS + as the call frame returnPC as it is only necessary for looking up when + throwing an exception. + * interpreter/RegisterFile.h: + (JSC::RegisterFile::): Added comment regarding returnPC storing a void*. + * jit/JIT.h: Remove ARG_instr4. + * jit/JITCall.cpp: + (JSC::JIT::compileOpCallSetupArgs): Don't pass the instruction pointer. + +2008-12-16 Darin Adler <darin@apple.com> + + Reviewed and landed by Cameron Zwarich. + + Preparatory work for fixing + + Bug 22887: Make UString::Rep use RefCounted rather than implementing its own ref counting + <https://bugs.webkit.org/show_bug.cgi?id=22887> + + Change the various string translators used by Identifier:add() so that + they never zero the ref count of a newly created UString::Rep. + + * runtime/Identifier.cpp: + (JSC::CStringTranslator::translate): + (JSC::Identifier::add): + (JSC::UCharBufferTranslator::translate): + +2008-12-16 Gavin Barraclough <barraclough@apple.com> + + Build fix for 'doze. + + * assembler/AssemblerBuffer.h: + +2008-12-16 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Cameron Zwarich. + + Make the JIT compile on x86-64. + This largely involves populting the missing calls in MacroAssembler.h. + In addition some reinterpret_casts need removing from the JIT, and the + repatching property access code will need to be fully compiled out for + now. The changes in interpret.cpp are to reorder the functions so that + the _generic forms come before all other property access methods, and + then to place all property access methods other than the generic forms + under control of the ENABLE_JIT_OPTIMIZE_PROPERTY_ACCESS macro. + + No performance impact. + + * assembler/AssemblerBuffer.h: + (JSC::AssemblerBuffer::putInt64Unchecked): + * assembler/MacroAssembler.h: + (JSC::MacroAssembler::loadPtr): + (JSC::MacroAssembler::load32): + (JSC::MacroAssembler::storePtr): + (JSC::MacroAssembler::storePtrWithRepatch): + (JSC::MacroAssembler::store32): + (JSC::MacroAssembler::poke): + (JSC::MacroAssembler::move): + (JSC::MacroAssembler::testImm64): + (JSC::MacroAssembler::jePtr): + (JSC::MacroAssembler::jnePtr): + (JSC::MacroAssembler::jnzPtr): + (JSC::MacroAssembler::jzPtr): + * assembler/X86Assembler.h: + (JSC::X86Assembler::): + (JSC::X86Assembler::cmpq_rr): + (JSC::X86Assembler::cmpq_rm): + (JSC::X86Assembler::cmpq_im): + (JSC::X86Assembler::testq_i32m): + (JSC::X86Assembler::movl_mEAX): + (JSC::X86Assembler::movl_i32r): + (JSC::X86Assembler::movl_EAXm): + (JSC::X86Assembler::movq_rm): + (JSC::X86Assembler::movq_mEAX): + (JSC::X86Assembler::movq_mr): + (JSC::X86Assembler::movq_i64r): + (JSC::X86Assembler::movl_mr): + (JSC::X86Assembler::X86InstructionFormatter::oneByteOp64): + (JSC::X86Assembler::X86InstructionFormatter::immediate64): + * interpreter/Interpreter.cpp: + (JSC::Interpreter::cti_op_put_by_id_generic): + (JSC::Interpreter::cti_op_get_by_id_generic): + (JSC::Interpreter::cti_op_put_by_id): + (JSC::Interpreter::cti_op_put_by_id_second): + * jit/JIT.cpp: + (JSC::JIT::privateCompileMainPass): + (JSC::JIT::privateCompile): + (JSC::JIT::privateCompileCTIMachineTrampolines): + * jit/JITCall.cpp: + (JSC::JIT::compileOpCallSetupArgs): + (JSC::JIT::compileOpCall): + * jit/JITPropertyAccess.cpp: + (JSC::JIT::compileGetByIdHotPath): + (JSC::JIT::compilePutByIdHotPath): + * runtime/JSImmediate.h: + (JSC::JSImmediate::makeInt): + +2008-12-16 Cameron Zwarich <zwarich@apple.com> + + Reviewed by Darin Adler. + + Bug 22869: REGRESSION (r38407): http://news.cnet.com/8301-13579_3-9953533-37.html crashes + <https://bugs.webkit.org/show_bug.cgi?id=22869> + <rdar://problem/6402499> + + Before r38407, Structure::m_nameInPrevious was ref'd due to it being + stored in a PropertyMap. However, PropertyMaps are created lazily after + r38407, so Structure::m_nameInPrevious is not necessarily ref'd while + it is being used. Making it a RefPtr instead of a raw pointer fixes + the problem. + + Unfortunately, the crash in the bug is rather intermittent, and it is + impossible to add an assertion in UString::Ref::ref() to catch this bug + because some users of UString::Rep deliberately zero out the reference + count. Therefore, there is no layout test accompanying this bug fix. + + * runtime/Structure.cpp: + (JSC::Structure::~Structure): Use get(). + (JSC::Structure::materializePropertyMap): Use get(). + (JSC::Structure::addPropertyTransitionToExistingStructure): Use get(). + (JSC::Structure::addPropertyTransition): Use get(). + * runtime/Structure.h: Make Structure::m_nameInPrevious a RefPtr instead + of a raw pointer. + +2008-12-16 Nikolas Zimmermann <nikolas.zimmermann@torchmobile.com> + + Not reviewed. Attempt to fix win build. No 'using namespace WTF' in this file, needs manual WTF:: prefix. + Not sure why the build works as is here. + + * runtime/MathObject.cpp: + (JSC::mathProtoFuncRandom): + +2008-12-16 Nikolas Zimmermann <nikolas.zimmermann@torchmobile.com> + + Reviewed by Darin Adler. + + Fixes: https://bugs.webkit.org/show_bug.cgi?id=22876 + + Unify random number generation in JavaScriptCore & WebCore, by introducing + wtf/RandomNumber.h and moving wtf_random/wtf_random_init out of MathExtras.h. + + wtf_random_init() has been renamed to initializeRandomNumberGenerator() and + lives in it's own private header: wtf/RandomNumberSeed.h, only intended to + be used from within JavaScriptCore. + + wtf_random() has been renamed to randomNumber() and lives in a public header + wtf/RandomNumber.h, usable from within JavaScriptCore & WebCore. It encapsulates + the code taking care of initializing the random number generator (only when + building without ENABLE(JSC_MULTIPLE_THREADS), otherwhise initializeThreading() + already took care of that). + + Functional change on darwin: Use random() instead of rand(), as it got a larger + period (more randomness). HTMLFormElement already contains this implementation + and I just moved it in randomNumber(), as special case for PLATFORM(DARWIN). + + * GNUmakefile.am: Add RandomNumber.(cpp/h) / RandomNumberSeed.h. + * JavaScriptCore.exp: Ditto. + * JavaScriptCore.pri: Ditto. + * JavaScriptCore.scons: Ditto. + * JavaScriptCore.vcproj/WTF/WTF.vcproj: Ditto. + * JavaScriptCore.xcodeproj/project.pbxproj: Ditto. + * JavaScriptCoreSources.bkl: Ditto. + * runtime/MathObject.cpp: Use new WTF::randomNumber() functionality. + (JSC::mathProtoFuncRandom): + * wtf/MathExtras.h: Move wtf_random / wtf_random_init to new files. + * wtf/RandomNumber.cpp: Added. + (WTF::randomNumber): + * wtf/RandomNumber.h: Added. + * wtf/RandomNumberSeed.h: Added. Internal usage within JSC only. + (WTF::initializeRandomNumberGenerator): + * wtf/ThreadingGtk.cpp: Rename wtf_random_init() to initializeRandomNumberGenerator(). + (WTF::initializeThreading): + * wtf/ThreadingPthreads.cpp: Ditto. + (WTF::initializeThreading): + * wtf/ThreadingQt.cpp: Ditto. + (WTF::initializeThreading): + * wtf/ThreadingWin.cpp: Ditto. + (WTF::initializeThreading): + +2008-12-16 Yael Aharon <yael.aharon@nokia.com> + + Reviewed by Tor Arne Vestbø. + + Qt/Win build fix + + * JavaScriptCore.pri: + +2008-12-15 Mark Rowe <mrowe@apple.com> + + Reviewed by Cameron Zwarich. + + Fix the build with GCC 4.0. + + * Configurations/JavaScriptCore.xcconfig: GCC 4.0 appears to have a bug when compiling with -funwind-tables on, + so don't use it with that compiler version. + +2008-12-15 Mark Rowe <mrowe@apple.com> + + Rubber-stamped by Cameron Zwarich. + + <rdar://problem/6289933> Change WebKit-related projects to build with GCC 4.2 on Leopard. + + * Configurations/Base.xcconfig: + * Configurations/DebugRelease.xcconfig: + +2008-12-15 Alexey Proskuryakov <ap@webkit.org> + + Reviewed by Darin Adler. + + Don't use unique context group in JSGlobalContextCreate() on Tiger or Leopard. + + * API/JSContextRef.cpp: (JSGlobalContextCreate): + +2008-12-15 Alexey Proskuryakov <ap@webkit.org> + + Reviewed by Darin Adler. + + <rdar://problem/6445089> Mach ports leak from worker threads + + * interpreter/Interpreter.cpp: (JSC::getCPUTime): + Deallocate the thread self port. + +2008-12-15 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Mark Rowe. + + Construct stack frames in JIT code, so that backtracing can still work. + <rdar://problem/6447870> JIT should play nice with attempts to take stack traces + + * jit/JIT.cpp: + (JSC::): + (JSC::JIT::privateCompileMainPass): + +2008-12-15 Mark Rowe <mrowe@apple.com> + + Reviewed by Gavin Barraclough. + + <rdar://problem/6402262> JavaScriptCore needs exception handling tables in order to get stack traces without frame pointers + + * Configurations/JavaScriptCore.xcconfig: + +2008-12-15 Gavin Barraclough <barraclough@apple.com> + + Rubber stamped by Mark Rowe. + + Revert r39226 / Bug 22818: Unify JIT callback argument access OS X / Windows + This causes Acid3 failures – reverting for now & will revisit later. + https://bugs.webkit.org/show_bug.cgi?id=22873 + + * interpreter/Interpreter.h: + * jit/JIT.cpp: + (JSC::JIT::privateCompileCTIMachineTrampolines): + * jit/JIT.h: + * jit/JITInlineMethods.h: + (JSC::JIT::restoreArgumentReference): + (JSC::JIT::restoreArgumentReferenceForTrampoline): + (JSC::JIT::emitCTICall_internal): + * jit/JITPropertyAccess.cpp: + (JSC::JIT::privateCompilePutByIdTransition): + * wtf/Platform.h: + +2008-12-15 Darin Adler <darin@apple.com> + + Reviewed by Sam Weinig. + + - fix <rdar://problem/6427048> crash due to infinite recursion after setting window.__proto__ = window + + Replaced toGlobalObject with the more generally useful unwrappedObject and used it to + fix the cycle detection code in put(__proto__). + + * JavaScriptCore.exp: Updated. + + * runtime/JSGlobalObject.cpp: Removed toGlobalObject. We now use unwrappedObject instead. + * runtime/JSGlobalObject.h: + (JSC::JSGlobalObject::isGlobalObject): Ditto. + + * runtime/JSGlobalObjectFunctions.cpp: + (JSC::globalFuncEval): Use unwrappedObject and isGlobalObject here rather than toGlobalObject. + + * runtime/JSObject.cpp: + (JSC::JSObject::put): Rewrote prototype cycle checking loop. Use unwrappedObject in the loop now. + (JSC::JSObject::unwrappedObject): Replaced toGlobalObject with this new function. + * runtime/JSObject.h: More of the same. + +2008-12-15 Steve Falkenburg <sfalken@apple.com> + + Windows build fix. + + Visual Studio requires visibility of forward declarations to match class declaration. + + * assembler/X86Assembler.h: + +2008-12-15 Gustavo Noronha Silva <kov@kov.eti.br> + + Reviewed by Mark Rowe. + + https://bugs.webkit.org/show_bug.cgi?id=22686 + + GTK+ build fix. + + * GNUmakefile.am: + +2008-12-15 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Geoff Garen. + + Add support to X86Assembler emitting instructions that access all 16 registers on x86-64. + Add a new formating class, that is reponsible for both emitting the opcode bytes and the + ModRm bytes of an instruction in a single call; this can insert the REX byte as necessary + before the opcode, but has access to the register numbers to build the REX. + + * assembler/AssemblerBuffer.h: + (JSC::AssemblerBuffer::isAligned): + (JSC::AssemblerBuffer::data): + * assembler/MacroAssembler.h: + (JSC::MacroAssembler::addPtr): + (JSC::MacroAssembler::add32): + (JSC::MacroAssembler::and32): + (JSC::MacroAssembler::or32): + (JSC::MacroAssembler::sub32): + (JSC::MacroAssembler::xor32): + (JSC::MacroAssembler::loadPtr): + (JSC::MacroAssembler::load32): + (JSC::MacroAssembler::load16): + (JSC::MacroAssembler::storePtr): + (JSC::MacroAssembler::storePtrWithRepatch): + (JSC::MacroAssembler::store32): + (JSC::MacroAssembler::pop): + (JSC::MacroAssembler::push): + (JSC::MacroAssembler::compareImm32ForBranch): + (JSC::MacroAssembler::compareImm32ForBranchEquality): + (JSC::MacroAssembler::testImm32): + (JSC::MacroAssembler::jae32): + (JSC::MacroAssembler::jb32): + (JSC::MacroAssembler::je16): + (JSC::MacroAssembler::jg32): + (JSC::MacroAssembler::jnePtr): + (JSC::MacroAssembler::jne32): + (JSC::MacroAssembler::jump): + * assembler/X86Assembler.h: + (JSC::X86::): + (JSC::X86Assembler::): + (JSC::X86Assembler::size): + (JSC::X86Assembler::push_r): + (JSC::X86Assembler::pop_r): + (JSC::X86Assembler::push_i32): + (JSC::X86Assembler::push_m): + (JSC::X86Assembler::pop_m): + (JSC::X86Assembler::addl_rr): + (JSC::X86Assembler::addl_mr): + (JSC::X86Assembler::addl_ir): + (JSC::X86Assembler::addq_ir): + (JSC::X86Assembler::addl_im): + (JSC::X86Assembler::andl_rr): + (JSC::X86Assembler::andl_ir): + (JSC::X86Assembler::orl_rr): + (JSC::X86Assembler::orl_mr): + (JSC::X86Assembler::orl_ir): + (JSC::X86Assembler::subl_rr): + (JSC::X86Assembler::subl_mr): + (JSC::X86Assembler::subl_ir): + (JSC::X86Assembler::subl_im): + (JSC::X86Assembler::xorl_rr): + (JSC::X86Assembler::xorl_ir): + (JSC::X86Assembler::sarl_i8r): + (JSC::X86Assembler::sarl_CLr): + (JSC::X86Assembler::shll_i8r): + (JSC::X86Assembler::shll_CLr): + (JSC::X86Assembler::imull_rr): + (JSC::X86Assembler::imull_i32r): + (JSC::X86Assembler::idivl_r): + (JSC::X86Assembler::cmpl_rr): + (JSC::X86Assembler::cmpl_rm): + (JSC::X86Assembler::cmpl_mr): + (JSC::X86Assembler::cmpl_ir): + (JSC::X86Assembler::cmpl_ir_force32): + (JSC::X86Assembler::cmpl_im): + (JSC::X86Assembler::cmpl_im_force32): + (JSC::X86Assembler::cmpw_rm): + (JSC::X86Assembler::testl_rr): + (JSC::X86Assembler::testl_i32r): + (JSC::X86Assembler::testl_i32m): + (JSC::X86Assembler::testq_rr): + (JSC::X86Assembler::testq_i32r): + (JSC::X86Assembler::testb_i8r): + (JSC::X86Assembler::sete_r): + (JSC::X86Assembler::setz_r): + (JSC::X86Assembler::setne_r): + (JSC::X86Assembler::setnz_r): + (JSC::X86Assembler::cdq): + (JSC::X86Assembler::xchgl_rr): + (JSC::X86Assembler::movl_rr): + (JSC::X86Assembler::movl_rm): + (JSC::X86Assembler::movl_mr): + (JSC::X86Assembler::movl_i32r): + (JSC::X86Assembler::movl_i32m): + (JSC::X86Assembler::movq_rr): + (JSC::X86Assembler::movq_rm): + (JSC::X86Assembler::movq_mr): + (JSC::X86Assembler::movzwl_mr): + (JSC::X86Assembler::movzbl_rr): + (JSC::X86Assembler::leal_mr): + (JSC::X86Assembler::call): + (JSC::X86Assembler::jmp): + (JSC::X86Assembler::jmp_r): + (JSC::X86Assembler::jmp_m): + (JSC::X86Assembler::jne): + (JSC::X86Assembler::jnz): + (JSC::X86Assembler::je): + (JSC::X86Assembler::jl): + (JSC::X86Assembler::jb): + (JSC::X86Assembler::jle): + (JSC::X86Assembler::jbe): + (JSC::X86Assembler::jge): + (JSC::X86Assembler::jg): + (JSC::X86Assembler::ja): + (JSC::X86Assembler::jae): + (JSC::X86Assembler::jo): + (JSC::X86Assembler::jp): + (JSC::X86Assembler::js): + (JSC::X86Assembler::addsd_rr): + (JSC::X86Assembler::addsd_mr): + (JSC::X86Assembler::cvtsi2sd_rr): + (JSC::X86Assembler::cvttsd2si_rr): + (JSC::X86Assembler::movd_rr): + (JSC::X86Assembler::movsd_rm): + (JSC::X86Assembler::movsd_mr): + (JSC::X86Assembler::mulsd_rr): + (JSC::X86Assembler::mulsd_mr): + (JSC::X86Assembler::pextrw_irr): + (JSC::X86Assembler::subsd_rr): + (JSC::X86Assembler::subsd_mr): + (JSC::X86Assembler::ucomis_rr): + (JSC::X86Assembler::int3): + (JSC::X86Assembler::ret): + (JSC::X86Assembler::predictNotTaken): + (JSC::X86Assembler::label): + (JSC::X86Assembler::align): + (JSC::X86Assembler::link): + (JSC::X86Assembler::executableCopy): + (JSC::X86Assembler::X86InstructionFormater::prefix): + (JSC::X86Assembler::X86InstructionFormater::oneByteOp): + (JSC::X86Assembler::X86InstructionFormater::twoByteOp): + (JSC::X86Assembler::X86InstructionFormater::oneByteOp64): + (JSC::X86Assembler::X86InstructionFormater::oneByteOp8): + (JSC::X86Assembler::X86InstructionFormater::twoByteOp8): + (JSC::X86Assembler::X86InstructionFormater::instructionImmediate8): + (JSC::X86Assembler::X86InstructionFormater::instructionImmediate32): + (JSC::X86Assembler::X86InstructionFormater::instructionRel32): + (JSC::X86Assembler::X86InstructionFormater::size): + (JSC::X86Assembler::X86InstructionFormater::isAligned): + (JSC::X86Assembler::X86InstructionFormater::data): + (JSC::X86Assembler::X86InstructionFormater::executableCopy): + (JSC::X86Assembler::X86InstructionFormater::registerModRM): + (JSC::X86Assembler::X86InstructionFormater::memoryModRM): + * jit/JIT.cpp: + (JSC::JIT::privateCompileMainPass): + (JSC::JIT::privateCompile): + (JSC::JIT::privateCompileCTIMachineTrampolines): + * jit/JITArithmetic.cpp: + (JSC::JIT::putDoubleResultToJSNumberCellOrJSImmediate): + (JSC::JIT::compileBinaryArithOp): + * jit/JITCall.cpp: + (JSC::JIT::compileOpCall): + (JSC::JIT::compileOpCallSlowCase): + * jit/JITPropertyAccess.cpp: + (JSC::JIT::compileGetByIdHotPath): + (JSC::JIT::compilePutByIdHotPath): + (JSC::JIT::privateCompilePutByIdTransition): + (JSC::JIT::privateCompilePatchGetArrayLength): + (JSC::JIT::privateCompileGetByIdProto): + (JSC::JIT::privateCompileGetByIdProtoList): + (JSC::JIT::privateCompileGetByIdChainList): + (JSC::JIT::privateCompileGetByIdChain): + +2008-12-15 Darin Adler <darin@apple.com> + + * interpreter/RegisterFile.h: Tweak include formatting. + +2008-12-15 Holger Hans Peter Freyther <zecke@selfish.org> + + Build fix for Gtk+. + + * interpreter/RegisterFile.h: Include stdio.h for fprintf + +2008-12-15 Alexey Proskuryakov <ap@webkit.org> + + Reviewed by Oliver Hunt. + + <rdar://problem/6444455> Worker Thread crash running multiple workers for a moderate amount of time + + * interpreter/RegisterFile.h: (JSC::RegisterFile::RegisterFile): + Improve error handling: if mmap fails, crash immediately, and print out the reason. + +2008-12-13 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Cameron Zwarich. + + Re-enable WREC on 64-bit. + Implements one of the MacroAssembler::jnzPtr methods, previously only implemented for 32-bit x86. + + https://bugs.webkit.org/show_bug.cgi?id=22849 + + * assembler/MacroAssembler.h: + (JSC::MacroAssembler::testImm64): + (JSC::MacroAssembler::jnzPtr): + * assembler/X86Assembler.h: + (JSC::X86Assembler::testq_i32r): + (JSC::X86Assembler::testq_rr): + * wtf/Platform.h: + +2008-12-13 Gavin Barraclough <barraclough@apple.com> + + Fix PPC builds. + + * assembler/MacroAssembler.h: + +2008-12-13 Gavin Barraclough <barraclough@apple.com> + + Build fix only, no review. + + * bytecode/CodeBlock.h: + +2008-12-13 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Cameron Zwarich. + + Port the remainder of the JIT, bar calling convention related code, and code + implementing optimizations which can be disabled, to use the MacroAssembler. + + * assembler/MacroAssembler.h: + (JSC::MacroAssembler::DataLabelPtr::DataLabelPtr): + (JSC::MacroAssembler::RepatchBuffer::RepatchBuffer): + (JSC::MacroAssembler::RepatchBuffer::link): + (JSC::MacroAssembler::RepatchBuffer::addressOf): + (JSC::MacroAssembler::RepatchBuffer::setPtr): + (JSC::MacroAssembler::addPtr): + (JSC::MacroAssembler::lshift32): + (JSC::MacroAssembler::mod32): + (JSC::MacroAssembler::rshift32): + (JSC::MacroAssembler::storePtrWithRepatch): + (JSC::MacroAssembler::jnzPtr): + (JSC::MacroAssembler::jzPtr): + (JSC::MacroAssembler::jump): + (JSC::MacroAssembler::label): + * assembler/X86Assembler.h: + (JSC::X86Assembler::): + (JSC::X86Assembler::xchgl_rr): + (JSC::X86Assembler::jmp_m): + (JSC::X86Assembler::repatchAddress): + (JSC::X86Assembler::getRelocatedAddress): + * bytecode/CodeBlock.cpp: + (JSC::CodeBlock::CodeBlock): + * bytecode/CodeBlock.h: + (JSC::JITCodeRef::JITCodeRef): + (JSC::CodeBlock::setJITCode): + (JSC::CodeBlock::jitCode): + (JSC::CodeBlock::executablePool): + * jit/JIT.cpp: + (JSC::JIT::privateCompileMainPass): + (JSC::JIT::privateCompileLinkPass): + (JSC::JIT::privateCompile): + (JSC::JIT::privateCompileCTIMachineTrampolines): + * jit/JIT.h: + (JSC::CallRecord::CallRecord): + (JSC::JumpTable::JumpTable): + (JSC::JIT::emitCTICall): + (JSC::JIT::JSRInfo::JSRInfo): + * jit/JITArithmetic.cpp: + * jit/JITCall.cpp: + * jit/JITInlineMethods.h: + (JSC::JIT::emitNakedCall): + (JSC::JIT::emitCTICall_internal): + (JSC::JIT::checkStructure): + (JSC::JIT::emitFastArithDeTagImmediateJumpIfZero): + (JSC::JIT::addSlowCase): + (JSC::JIT::addJump): + (JSC::JIT::emitJumpSlowToHot): + * jit/JITPropertyAccess.cpp: + (JSC::JIT::privateCompileGetByIdChainList): + (JSC::JIT::privateCompileGetByIdChain): + +2008-12-12 Cameron Zwarich <zwarich@apple.com> + + Reviewed by Sam Weinig. + + Fix the failures of the following layout tests, which regressed in + r39255: + + fast/dom/StyleSheet/ownerNode-lifetime-2.html + fast/xsl/transform-xhr-doc.xhtml + + The binary search in CodeBlock::getByIdExceptionInfoForBytecodeOffset() + doesn't guarantee that it actually finds a match, so add an explicit check + for this. + + * bytecode/CodeBlock.cpp: + (JSC::CodeBlock::getByIdExceptionInfoForBytecodeOffset): + +2008-12-12 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Cameron Zwarich. + + Replace emitPutCallArg methods with emitPutJITStubArg methods. Primarily to make the argument numbering + more sensible (1-based incrementing by 1, rather than 0-based incrementing by 4). The CTI name also seems + to be being deprecated from the code generally. + + * jit/JIT.cpp: + (JSC::JIT::privateCompileMainPass): + (JSC::JIT::privateCompileSlowCases): + (JSC::JIT::privateCompileCTIMachineTrampolines): + * jit/JIT.h: + * jit/JITArithmetic.cpp: + (JSC::JIT::compileBinaryArithOp): + (JSC::JIT::compileBinaryArithOpSlowCase): + * jit/JITCall.cpp: + (JSC::JIT::compileOpCallSetupArgs): + (JSC::JIT::compileOpCallEvalSetupArgs): + (JSC::JIT::compileOpConstructSetupArgs): + (JSC::JIT::compileOpCall): + * jit/JITInlineMethods.h: + (JSC::JIT::emitPutJITStubArg): + (JSC::JIT::emitPutJITStubArgConstant): + (JSC::JIT::emitGetJITStubArg): + (JSC::JIT::emitPutJITStubArgFromVirtualRegister): + * jit/JITPropertyAccess.cpp: + (JSC::JIT::compileGetByIdHotPath): + (JSC::JIT::compilePutByIdHotPath): + (JSC::JIT::compileGetByIdSlowCase): + (JSC::JIT::compilePutByIdSlowCase): + +2008-12-12 Gavin Barraclough <barraclough@apple.com> + + Fix windows builds. + + * jit/JIT.cpp: + (JSC::JIT::privateCompileMainPass): + (JSC::JIT::privateCompileSlowCases): + (JSC::JIT::privateCompile): + +2008-12-12 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Geoff Garen. + + Remove loop counter 'i' from the JIT generation passes, replace with a member m_bytecodeIndex. + + No impact on performance. + + * jit/JIT.cpp: + (JSC::JIT::compileOpStrictEq): + (JSC::JIT::emitSlowScriptCheck): + (JSC::JIT::privateCompileMainPass): + (JSC::JIT::privateCompileSlowCases): + (JSC::JIT::privateCompile): + * jit/JIT.h: + (JSC::CallRecord::CallRecord): + (JSC::JmpTable::JmpTable): + (JSC::JIT::emitCTICall): + * jit/JITArithmetic.cpp: + (JSC::JIT::compileBinaryArithOp): + (JSC::JIT::compileBinaryArithOpSlowCase): + * jit/JITCall.cpp: + (JSC::JIT::compileOpCall): + (JSC::JIT::compileOpCallSlowCase): + * jit/JITInlineMethods.h: + (JSC::JIT::emitGetVirtualRegister): + (JSC::JIT::emitGetVirtualRegisters): + (JSC::JIT::emitNakedCall): + (JSC::JIT::emitCTICall_internal): + (JSC::JIT::emitJumpSlowCaseIfJSCell): + (JSC::JIT::emitJumpSlowCaseIfNotJSCell): + (JSC::JIT::emitJumpSlowCaseIfNotImmNum): + (JSC::JIT::emitJumpSlowCaseIfNotImmNums): + (JSC::JIT::emitFastArithIntToImmOrSlowCase): + (JSC::JIT::addSlowCase): + (JSC::JIT::addJump): + (JSC::JIT::emitJumpSlowToHot): + * jit/JITPropertyAccess.cpp: + (JSC::JIT::compileGetByIdHotPath): + (JSC::JIT::compileGetByIdSlowCase): + (JSC::JIT::compilePutByIdHotPath): + (JSC::JIT::compilePutByIdSlowCase): + +2008-12-12 Sam Weinig <sam@webkit.org> + + Reviewed by Cameron Zwarich. + + <rdar://problem/6428342> Look into feasibility of discarding bytecode after native codegen + + Move more JIT functionality to using offsets into the Instruction buffer + instead of raw pointers. Two to go! + + * interpreter/Interpreter.cpp: + (JSC::bytecodeOffsetForPC): Rename from vPCForPC. + (JSC::Interpreter::resolve): Pass offset to exception helper. + (JSC::Interpreter::resolveSkip): Ditto. + (JSC::Interpreter::resolveGlobal): Ditto. + (JSC::Interpreter::resolveBaseAndProperty): Ditto. + (JSC::Interpreter::resolveBaseAndFunc): Ditto. + (JSC::isNotObject): Ditto. + (JSC::Interpreter::unwindCallFrame): Call bytecodeOffsetForPC. + (JSC::Interpreter::throwException): Use offsets instead of vPCs. + (JSC::Interpreter::privateExecute): Pass offset to exception helper. + (JSC::Interpreter::retrieveLastCaller): Ditto. + (JSC::Interpreter::cti_op_instanceof): Ditto. + (JSC::Interpreter::cti_op_call_NotJSFunction): Ditto. + (JSC::Interpreter::cti_op_resolve): Pass offset to exception helper. + (JSC::Interpreter::cti_op_construct_NotJSConstruct): Ditto. + (JSC::Interpreter::cti_op_resolve_func): Ditto. + (JSC::Interpreter::cti_op_resolve_skip): Ditto. + (JSC::Interpreter::cti_op_resolve_global): Ditto. + (JSC::Interpreter::cti_op_resolve_with_base): Ditto. + (JSC::Interpreter::cti_op_throw): Ditto. + (JSC::Interpreter::cti_op_in): Ditto. + (JSC::Interpreter::cti_vm_throw): Ditto. + * interpreter/Interpreter.h: + + * jit/JIT.cpp: + (JSC::JIT::privateCompileMainPass): Don't pass unnecessary vPC to stub. + * jit/JIT.h: Remove ARG_instr1 - ARG_instr3 and ARG_instr5 - ARG_instr6. + * jit/JITCall.cpp: + (JSC::JIT::compileOpCallEvalSetupArgs): Don't pass unnecessary vPC to stub.. + (JSC::JIT::compileOpConstructSetupArgs): Ditto. + + * runtime/ExceptionHelpers.cpp: + (JSC::createUndefinedVariableError): Take an offset instead of vPC. + (JSC::createInvalidParamError): Ditto. + (JSC::createNotAConstructorError): Ditto. + (JSC::createNotAFunctionError): Ditto. + (JSC::createNotAnObjectError): Ditto. + * runtime/ExceptionHelpers.h: + +2008-12-12 Cameron Zwarich <zwarich@apple.com> + + Reviewed by Oliver Hunt. + + Bug 22835: Crash during bytecode generation when comparing to null + <https://bugs.webkit.org/show_bug.cgi?id=22835> + <rdar://problem/6286749> + + Change the special cases in bytecode generation for comparison to null + to use tempDestination(). + + * parser/Nodes.cpp: + (JSC::BinaryOpNode::emitBytecode): + (JSC::EqualNode::emitBytecode): + +2008-12-12 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Geoff Garen. + + Move slow-cases of JIT code generation over to the MacroAssembler interface. + + * assembler/MacroAssembler.h: + (JSC::MacroAssembler::Label::Label): + (JSC::MacroAssembler::jae32): + (JSC::MacroAssembler::jg32): + (JSC::MacroAssembler::jzPtr): + * jit/JIT.cpp: + (JSC::JIT::privateCompileSlowCases): + (JSC::JIT::privateCompile): + (JSC::JIT::emitGetVariableObjectRegister): + (JSC::JIT::emitPutVariableObjectRegister): + * jit/JIT.h: + (JSC::SlowCaseEntry::SlowCaseEntry): + (JSC::JIT::getSlowCase): + (JSC::JIT::linkSlowCase): + * jit/JITArithmetic.cpp: + (JSC::JIT::compileBinaryArithOpSlowCase): + * jit/JITCall.cpp: + (JSC::JIT::compileOpCallInitializeCallFrame): + (JSC::JIT::compileOpCall): + (JSC::JIT::compileOpCallSlowCase): + * jit/JITInlineMethods.h: + (JSC::JIT::emitJumpSlowCaseIfNotJSCell): + (JSC::JIT::linkSlowCaseIfNotJSCell): + * jit/JITPropertyAccess.cpp: + (JSC::JIT::compileGetByIdHotPath): + (JSC::JIT::compilePutByIdHotPath): + (JSC::JIT::compileGetByIdSlowCase): + (JSC::JIT::compilePutByIdSlowCase): + +2008-12-12 Cameron Zwarich <zwarich@apple.com> + + Reviewed by Sam Weinig. + + Bug 22828: Do not inspect bytecode instruction stream for op_get_by_id exception information + <https://bugs.webkit.org/show_bug.cgi?id=22828> + + In order to remove the bytecode instruction stream after generating + native code, all inspection of bytecode instructions at runtime must + be removed. One particular instance of this is the special handling of + exceptions thrown by the op_get_by_id emitted directly before an + op_construct or an op_instanceof. This patch moves that information to + an auxiliary data structure in CodeBlock. + + * bytecode/CodeBlock.cpp: + (JSC::CodeBlock::getByIdExceptionInfoForBytecodeOffset): + * bytecode/CodeBlock.h: + (JSC::CodeBlock::addGetByIdExceptionInfo): + * bytecompiler/BytecodeGenerator.cpp: + (JSC::BytecodeGenerator::emitConstruct): + * bytecompiler/BytecodeGenerator.h: + (JSC::BytecodeGenerator::emitGetByIdExceptionInfo): + * parser/Nodes.cpp: + (JSC::InstanceOfNode::emitBytecode): + * runtime/ExceptionHelpers.cpp: + (JSC::createNotAnObjectError): + +2008-12-12 Sam Weinig <sam@webkit.org> + + Reviewed by Geoffrey Garen. + + Change exception information accessors to take offsets into the bytecode + instruction buffer instead of pointers so that they can work even even + if the bytecode buffer is purged. + + * bytecode/CodeBlock.cpp: + (JSC::instructionOffsetForNth): + (JSC::CodeBlock::handlerForBytecodeOffset): + (JSC::CodeBlock::lineNumberForBytecodeOffset): + (JSC::CodeBlock::expressionRangeForBytecodeOffset): + * bytecode/CodeBlock.h: + * bytecode/SamplingTool.cpp: + (JSC::SamplingTool::dump): + * interpreter/Interpreter.cpp: + (JSC::Interpreter::throwException): + (JSC::Interpreter::privateExecute): + (JSC::Interpreter::retrieveLastCaller): + * jit/JIT.cpp: + (JSC::JIT::privateCompileMainPass): + * runtime/ExceptionHelpers.cpp: + (JSC::createUndefinedVariableError): + (JSC::createInvalidParamError): + (JSC::createNotAConstructorError): + (JSC::createNotAFunctionError): + (JSC::createNotAnObjectError): + +2008-12-12 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Cameron Zwarich. + + Tiny bit of refactoring in quantifier generation. + + * wrec/WRECGenerator.cpp: + (JSC::WREC::Generator::generateNonGreedyQuantifier): + (JSC::WREC::Generator::generateGreedyQuantifier): + +2008-12-11 Sam Weinig <sam@webkit.org> + + Reviewed by Geoffrey Garen. + + Remove dependancy on having the Instruction buffer in order to + deref Structures used for property access and global resolves. + Instead, we put references to the necessary Structures in auxiliary + data structures on the CodeBlock. This is not an ideal solution, + as we still pay for having the Structures in two places and we + would like to eventually just hold on to offsets into the machine + code buffer. + + - Also removes CodeBlock bloat in non-JIT by #ifdefing the JIT + only data structures. + + * GNUmakefile.am: + * JavaScriptCore.pri: + * JavaScriptCore.scons: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: + * JavaScriptCore.xcodeproj/project.pbxproj: + * JavaScriptCoreSources.bkl: + * bytecode/CodeBlock.cpp: + (JSC::isGlobalResolve): + (JSC::isPropertyAccess): + (JSC::instructionOffsetForNth): + (JSC::printGlobalResolveInfo): + (JSC::printStructureStubInfo): + (JSC::CodeBlock::printStructures): + (JSC::CodeBlock::dump): + (JSC::CodeBlock::~CodeBlock): + (JSC::CodeBlock::shrinkToFit): + * bytecode/CodeBlock.h: + (JSC::GlobalResolveInfo::GlobalResolveInfo): + (JSC::getNativePC): + (JSC::CodeBlock::instructions): + (JSC::CodeBlock::getStubInfo): + (JSC::CodeBlock::getBytecodeIndex): + (JSC::CodeBlock::addPropertyAccessInstruction): + (JSC::CodeBlock::addGlobalResolveInstruction): + (JSC::CodeBlock::numberOfStructureStubInfos): + (JSC::CodeBlock::addStructureStubInfo): + (JSC::CodeBlock::structureStubInfo): + (JSC::CodeBlock::addGlobalResolveInfo): + (JSC::CodeBlock::globalResolveInfo): + (JSC::CodeBlock::numberOfCallLinkInfos): + (JSC::CodeBlock::addCallLinkInfo): + (JSC::CodeBlock::callLinkInfo): + * bytecode/Instruction.h: + (JSC::PolymorphicAccessStructureList::PolymorphicStubInfo::set): + (JSC::PolymorphicAccessStructureList::PolymorphicAccessStructureList): + * bytecode/Opcode.h: + (JSC::): + * bytecode/StructureStubInfo.cpp: Copied from bytecode/CodeBlock.cpp. + (JSC::StructureStubInfo::deref): + * bytecode/StructureStubInfo.h: Copied from bytecode/CodeBlock.h. + (JSC::StructureStubInfo::StructureStubInfo): + (JSC::StructureStubInfo::initGetByIdSelf): + (JSC::StructureStubInfo::initGetByIdProto): + (JSC::StructureStubInfo::initGetByIdChain): + (JSC::StructureStubInfo::initGetByIdSelfList): + (JSC::StructureStubInfo::initGetByIdProtoList): + (JSC::StructureStubInfo::initPutByIdTransition): + (JSC::StructureStubInfo::initPutByIdReplace): + (JSC::StructureStubInfo::): + * bytecompiler/BytecodeGenerator.cpp: + (JSC::BytecodeGenerator::emitResolve): + (JSC::BytecodeGenerator::emitGetById): + (JSC::BytecodeGenerator::emitPutById): + (JSC::BytecodeGenerator::emitCall): + (JSC::BytecodeGenerator::emitConstruct): + (JSC::BytecodeGenerator::emitCatch): + * interpreter/Interpreter.cpp: + (JSC::Interpreter::tryCTICachePutByID): + (JSC::Interpreter::tryCTICacheGetByID): + (JSC::Interpreter::cti_op_get_by_id_self_fail): + (JSC::getPolymorphicAccessStructureListSlot): + (JSC::Interpreter::cti_op_get_by_id_proto_list): + (JSC::Interpreter::cti_op_resolve_global): + * jit/JIT.cpp: + (JSC::JIT::JIT): + (JSC::JIT::privateCompileMainPass): + (JSC::JIT::privateCompileSlowCases): + (JSC::JIT::privateCompile): + * jit/JITPropertyAccess.cpp: + (JSC::JIT::compileGetByIdHotPath): + (JSC::JIT::compilePutByIdHotPath): + (JSC::JIT::compileGetByIdSlowCase): + (JSC::JIT::compilePutByIdSlowCase): + (JSC::JIT::privateCompileGetByIdSelfList): + (JSC::JIT::privateCompileGetByIdProtoList): + (JSC::JIT::privateCompileGetByIdChainList): + +2008-12-11 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Oliver Hunt. + + Remove CTI_ARGUMENTS mode, use va_start implementation on Windows, + unifying JIT callback (cti_*) argument access on OS X & Windows + + No performance impact. + + * interpreter/Interpreter.h: + * jit/JIT.cpp: + (JSC::JIT::privateCompileCTIMachineTrampolines): + * jit/JIT.h: + * jit/JITInlineMethods.h: + (JSC::JIT::emitCTICall): + * jit/JITPropertyAccess.cpp: + (JSC::JIT::privateCompilePutByIdTransition): + * wtf/Platform.h: + +2008-12-11 Holger Freyther <zecke@selfish.org> + + Reviewed by Simon Hausmann. + + https://bugs.webkit.org/show_bug.cgi?id=20953 + + For Qt it is not pratical to have a FontCache and GlyphPageTreeNode + implementation. This is one of the reasons why the Qt port is currently not + using WebCore/platform/graphics/Font.cpp. By allowing to not use + the simple/fast-path the Qt port will be able to use it. + + Introduce USE(FONT_FAST_PATH) and define it for every port but the + Qt one. + + * wtf/Platform.h: Enable USE(FONT_FAST_PATH) + +2008-12-11 Gabor Loki <loki@inf.u-szeged.hu> + + Reviewed by Darin Adler and landed by Holger Freyther. + + <https://bugs.webkit.org/show_bug.cgi?id=22648> + Fix threading on Qt-port and Gtk-port for Sampling tool. + + * wtf/ThreadingGtk.cpp: + (WTF::waitForThreadCompletion): + * wtf/ThreadingQt.cpp: + (WTF::waitForThreadCompletion): + +2008-12-10 Cameron Zwarich <zwarich@apple.com> + + Reviewed by Oliver Hunt. + + Bug 22734: Debugger crashes when stepping into a function call in a return statement + <https://bugs.webkit.org/show_bug.cgi?id=22734> + <rdar://problem/6426796> + + * bytecompiler/BytecodeGenerator.cpp: + (JSC::BytecodeGenerator::BytecodeGenerator): The DebuggerCallFrame uses + the 'this' value stored in a callFrame, so op_convert_this should be + emitted at the beginning of a function body when generating bytecode + with debug hooks. + * debugger/DebuggerCallFrame.cpp: + (JSC::DebuggerCallFrame::thisObject): The assertion inherent in the call + to asObject() here is valid, because any 'this' value should have been + converted to a JSObject*. + +2008-12-10 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Geoff Garen. + + Port more of the JIT to use the MacroAssembler interface. + + Everything in the main pass, bar a few corner cases (operations with required + registers, or calling convention code). Slightly refactors array creation, + moving the offset calculation into the callFrame into C code (reducing code + planted). + + Overall this appears to be a 1% win on v8-tests, due to the smaller immediates + being planted (in jfalse in particular). + + * interpreter/Interpreter.cpp: + (JSC::Interpreter::cti_op_new_array): + * jit/JIT.cpp: + (JSC::JIT::privateCompileMainPass): + (JSC::JIT::privateCompileSlowCases): + * jit/JIT.h: + * wrec/WRECGenerator.cpp: + (JSC::WREC::Generator::generateEnter): + +2008-12-10 Sam Weinig <sam@webkit.org> + + Fix non-JIT builds. + + * bytecode/CodeBlock.h: + +2008-12-10 Sam Weinig <sam@webkit.org> + + Reviewed by Geoffrey Garen. + + <rdar://problem/6428332> Remove the CTI return address table from CodeBlock + + Step 2: + + Convert the return address table from a HashMap to a sorted Vector. This + reduces the size of the data structure by ~4.5MB on Membuster head. + + SunSpider reports a 0.5% progression. + + * bytecode/CodeBlock.cpp: + (JSC::sizeInBytes): Generic method to get the cost of a Vector. + (JSC::CodeBlock::dumpStatistics): Add dumping of member sizes. + * bytecode/CodeBlock.h: + (JSC::PC::PC): Struct representing NativePC -> VirtualPC mappings. + (JSC::getNativePC): Helper for binary chop. + (JSC::CodeBlock::getBytecodeIndex): Used to get the VirtualPC from a + NativePC using a binary chop of the pcVector. + (JSC::CodeBlock::pcVector): Accessor. + + * interpreter/Interpreter.cpp: + (JSC::vPCForPC): Use getBytecodeIndex instead of jitReturnAddressVPCMap().get(). + (JSC::Interpreter::cti_op_instanceof): Ditto. + (JSC::Interpreter::cti_op_resolve): Ditto. + (JSC::Interpreter::cti_op_resolve_func): Ditto. + (JSC::Interpreter::cti_op_resolve_skip): Ditto. + (JSC::Interpreter::cti_op_resolve_with_base): Ditto. + (JSC::Interpreter::cti_op_throw): Ditto. + (JSC::Interpreter::cti_op_in): Ditto. + (JSC::Interpreter::cti_vm_throw): Ditto. + + * jit/JIT.cpp: + (JSC::JIT::privateCompile): Reserve exact capacity and fill the pcVector. + +2008-12-09 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Oliver Hunt. + + Added WREC support for an assertion followed by a quantifier. Fixed + PCRE to match. + + * wrec/WRECParser.cpp: + (JSC::WREC::Parser::parseParentheses): Throw away the quantifier, since + it's meaningless. (Firefox does the same.) + + * pcre/pcre_compile.cpp: + (compileBranch): ditto. + +2008-12-09 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Cameron Zwarich. + + In preparation for compiling WREC without PCRE: + + Further relaxed WREC's parsing to be more web-compatible. Fixed PCRE to + match in cases where it didn't already. + + Changed JavaScriptCore to report syntax errors detected by WREC, rather + than falling back on PCRE any time WREC sees an error. + + * pcre/pcre_compile.cpp: + (checkEscape): Relaxed parsing of \c and \N escapes to be more + web-compatible. + + * runtime/RegExp.cpp: + (JSC::RegExp::RegExp): Only fall back on PCRE if WREC has not reported + a syntax error. + + * wrec/WREC.cpp: + (JSC::WREC::Generator::compileRegExp): Fixed some error reporting to + match PCRE. + + * wrec/WRECParser.cpp: Added error messages that match PCRE. + + (JSC::WREC::Parser::consumeGreedyQuantifier): + (JSC::WREC::Parser::parseParentheses): + (JSC::WREC::Parser::parseCharacterClass): + (JSC::WREC::Parser::parseNonCharacterEscape): Updated the above functions to + use the new setError API. + + (JSC::WREC::Parser::consumeEscape): Relaxed parsing of \c \N \u \x \B + to be more web-compatible. + + (JSC::WREC::Parser::parseAlternative): Distinguish between a malformed + quantifier and a quantifier with no prefix, like PCRE does. + + (JSC::WREC::Parser::consumeParenthesesType): Updated to use the new setError API. + + * wrec/WRECParser.h: + (JSC::WREC::Parser::error): + (JSC::WREC::Parser::syntaxError): + (JSC::WREC::Parser::parsePattern): + (JSC::WREC::Parser::reset): + (JSC::WREC::Parser::setError): Store error messages instead of error codes, + to provide for exception messages. Use a setter for reporting errors, so + errors detected early are not overwritten by errors detected later. + +2008-12-09 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Oliver Hunt. + + Use va_args to access cti function arguments. + https://bugs.webkit.org/show_bug.cgi?id=22774 + + This may be a minor regression, but we'll take the hit if so to reduce fragility. + + * interpreter/Interpreter.cpp: + * interpreter/Interpreter.h: + +2008-12-09 Sam Weinig <sam@webkit.org> + + Reviewed twice by Cameron Zwarich. + + Fix for https://bugs.webkit.org/show_bug.cgi?id=22752 + Clear SymbolTable after codegen for Function codeblocks that + don't require an activation + + This is a ~1.5MB improvement on Membuster-head. + + * bytecode/CodeBlock.cpp: + (JSC::CodeBlock::dumpStatistics): Add logging of non-empty symbol tables + and total size used by symbol tables. + * bytecompiler/BytecodeGenerator.cpp: + (JSC::BytecodeGenerator::generate): Clear the symbol table here. + +2008-12-09 Sam Weinig <sam@webkit.org> + + Reviewed by Geoffrey Garen. + + Remove unnecessary extra lookup when throwing an exception. + We used to first lookup the target offset using getHandlerForVPC + and then we would lookup the native code stub using + nativeExceptionCodeForHandlerVPC. Instead, we can just pass around + the HandlerInfo. + + * bytecode/CodeBlock.cpp: + (JSC::CodeBlock::handlerForVPC): Return the HandlerInfo. + * bytecode/CodeBlock.h: Remove nativeExceptionCodeForHandlerVPC. + + * interpreter/Interpreter.cpp: + (JSC::Interpreter::throwException): Return a HandlerInfo instead of + and Instruction offset. + (JSC::Interpreter::privateExecute): Get the offset from HandlerInfo. + (JSC::Interpreter::cti_op_throw): Get the native code from the HandleInfo. + (JSC::Interpreter::cti_vm_throw): Ditto. + * interpreter/Interpreter.h: + +2008-12-09 Eric Seidel <eric@webkit.org> + + Build fix only, no review. + + Speculative fix for the Chromium-Windows bot. + Add JavaScriptCore/os-win32 to the include path (for stdint.h) + Strangely it builds fine on my local windows box (or at least doesn't hit this error) + + * JavaScriptCore.scons: + +2008-12-09 Eric Seidel <eric@webkit.org> + + No review, build fix only. + + Add ExecutableAllocator files missing from Scons build. + + * JavaScriptCore.scons: + +2008-12-09 Dimitri Glazkov <dglazkov@chromium.org> + + Reviewed by Timothy Hatcher. + + https://bugs.webkit.org/show_bug.cgi?id=22631 + Allow ScriptCallFrame query names of functions in the call stack. + + * JavaScriptCore.exp: added InternalFunction::name and + UString operator==() as exported symbol + +2008-12-08 Judit Jasz <jasy@inf.u-szeged.hu> + + Reviewed and tweaked by Cameron Zwarich. + + Bug 22352: Annotate opcodes with their length + <https://bugs.webkit.org/show_bug.cgi?id=22352> + + * bytecode/Opcode.cpp: + * bytecode/Opcode.h: + * interpreter/Interpreter.cpp: + (JSC::Interpreter::privateExecute): + * jit/JIT.cpp: + (JSC::JIT::privateCompileMainPass): + (JSC::JIT::privateCompileSlowCases): + +2008-12-08 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Oliver Hunt. + + Implemented more of the relaxed and somewhat weird rules for deciding + how to interpret a non-pattern-character. + + * wrec/Escapes.h: + (JSC::WREC::Escape::): + (JSC::WREC::Escape::Escape): Eliminated Escape::None because it was + unused. If you see an '\\', it's either a valid escape or an error. + + * wrec/Quantifier.h: + (JSC::WREC::Quantifier::Quantifier): + * wrec/WRECGenerator.cpp: + (JSC::WREC::Generator::generateNonGreedyQuantifier): + (JSC::WREC::Generator::generateGreedyQuantifier): Renamed "noMaxSpecified" + to "Infinity", since that's what it means. + + * wrec/WRECParser.cpp: + (JSC::WREC::Parser::consumeGreedyQuantifier): Re-wrote {n,m} parsing rules + because they were too strict before. Added support for backtracking + in the case where the {n,m} fails to parse as a quantifier, and yet is + not a syntax error. + + (JSC::WREC::Parser::parseCharacterClass): + (JSC::WREC::Parser::parseNonCharacterEscape): Eliminated Escape::None, + as above. + + (JSC::WREC::Parser::consumeEscape): Don't treat ASCII and _ escapes + as syntax errors. See fast/regex/non-pattern-characters.html. + + * wrec/WRECParser.h: + (JSC::WREC::Parser::SavedState::SavedState): + (JSC::WREC::Parser::SavedState::restore): Added a state backtracker, + since parsing {n,m} forms requires backtracking if the form turns out + not to be a quantifier. + +2008-12-08 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Oliver Hunt. + + Refactored WREC parsing so that only one piece of code needs to know + the relaxed and somewhat weird rules for deciding how to interpret a + non-pattern-character, in preparation for implementing those rules. + + Also, implemented the relaxed and somewhat weird rules for '}' and ']'. + + * wrec/WREC.cpp: Reduced the regular expression size limit. Now that + WREC handles ']' properly, it compiles fast/js/regexp-charclass-crash.html, + which makes it hang at the old limit. (The old limit was based on the + misimpression that the same value in PCRE limited the regular expression + pattern size; in reality, it limited the expected compiled regular + expression size. WREC doesn't have a way to calculate an expected + compiled regular expression size, but this should be good enough.) + + * wrec/WRECParser.cpp: + (JSC::WREC::parsePatternCharacterSequence): Nixed this function because + it contained a second copy of the logic for handling non-pattern-characters, + which is about to get a lot more complicated. + + (JSC::WREC::PatternCharacterSequence::PatternCharacterSequence): + (JSC::WREC::PatternCharacterSequence::size): + (JSC::WREC::PatternCharacterSequence::append): + (JSC::WREC::PatternCharacterSequence::flush): Helper object for generating + an optimized sequence of pattern characters. + + (JSC::WREC::Parser::parseNonCharacterEscape): Renamed to reflect the fact + that the main parseAlternative loop handles character escapes. + + (JSC::WREC::Parser::parseAlternative): Moved pattern character sequence + logic from parsePatternCharacterSequence to here, using + PatternCharacterSequence to help with the details. + + * wrec/WRECParser.h: Updated for renames. + +2008-12-08 Alexey Proskuryakov <ap@webkit.org> + + Reviewed by Geoff Garen. + + <rdar://problem/6166088> Give JSGlobalContextCreate a behavior that is concurrency aware, + and un-deprecate it + + * API/JSContextRef.cpp: (JSGlobalContextCreate): + * API/JSContextRef.h: + Use a unique context group for the context, unless the application was linked against old + JavaScriptCore. + +2008-12-08 Sam Weinig <sam@webkit.org> + + Reviewed by Cameron Zwarich. + + Fix for <rdar://problem/6428332> Remove the CTI return address table from CodeBlock + + Step 1: + + Remove use of jitReturnAddressVPCMap when looking for vPC to store Structures + in for cached lookup. Instead, use the offset in the StructureStubInfo that is + already required. + + * bytecode/CodeBlock.cpp: + (JSC::CodeBlock::dumpStatistics): Fix extraneous semicolon. + * interpreter/Interpreter.cpp: + (JSC::Interpreter::tryCTICachePutByID): + (JSC::Interpreter::tryCTICacheGetByID): + (JSC::Interpreter::cti_op_get_by_id_self_fail): + (JSC::Interpreter::cti_op_get_by_id_proto_list): + * jit/JIT.h: + (JSC::JIT::compileGetByIdSelf): + (JSC::JIT::compileGetByIdProto): + (JSC::JIT::compileGetByIdChain): + (JSC::JIT::compilePutByIdReplace): + (JSC::JIT::compilePutByIdTransition): + * jit/JITPropertyAccess.cpp: + (JSC::JIT::privateCompilePutByIdTransition): + (JSC::JIT::patchGetByIdSelf): + (JSC::JIT::patchPutByIdReplace): + (JSC::JIT::privateCompilePatchGetArrayLength): Remove extra call to getStubInfo. + (JSC::JIT::privateCompileGetByIdSelf): + (JSC::JIT::privateCompileGetByIdProto): + (JSC::JIT::privateCompileGetByIdChain): + (JSC::JIT::privateCompilePutByIdReplace): + +2008-12-08 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Oliver Hunt. + + Port the op_j?n?eq_null JIT code generation to use the MacroAssembler, + and clean up slightly at the same time. The 'j' forms currently compare, + then set a register, then compare again, then branch. Branch directly on + the result of the first compare. + + Around a 1% progression on deltablue, crypto & early boyer, for about 1/2% + overall on v8-tests. + + * jit/JIT.cpp: + (JSC::JIT::privateCompileMainPass): + * jit/JITPropertyAccess.cpp: + (JSC::JIT::compileGetByIdSlowCase): + +2008-12-08 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Geoff Garen. + + Expand MacroAssembler to support more operations, required by the JIT. + + Generally adds more operations and permutations of operands to the existing + interface. Rename 'jset' to 'jnz' and 'jnset' to 'jz', which seem clearer, + and require that immediate pointer operands (though not pointer addresses to + load and store instructions) are wrapped in a ImmPtr() type, akin to Imm32(). + + No performance impact. + + * assembler/MacroAssembler.h: + (JSC::MacroAssembler::): + (JSC::MacroAssembler::ImmPtr::ImmPtr): + (JSC::MacroAssembler::add32): + (JSC::MacroAssembler::and32): + (JSC::MacroAssembler::or32): + (JSC::MacroAssembler::sub32): + (JSC::MacroAssembler::xor32): + (JSC::MacroAssembler::loadPtr): + (JSC::MacroAssembler::load32): + (JSC::MacroAssembler::storePtr): + (JSC::MacroAssembler::store32): + (JSC::MacroAssembler::poke): + (JSC::MacroAssembler::move): + (JSC::MacroAssembler::testImm32): + (JSC::MacroAssembler::jae32): + (JSC::MacroAssembler::jb32): + (JSC::MacroAssembler::jePtr): + (JSC::MacroAssembler::je32): + (JSC::MacroAssembler::jnePtr): + (JSC::MacroAssembler::jne32): + (JSC::MacroAssembler::jnzPtr): + (JSC::MacroAssembler::jnz32): + (JSC::MacroAssembler::jzPtr): + (JSC::MacroAssembler::jz32): + (JSC::MacroAssembler::joSub32): + (JSC::MacroAssembler::jump): + (JSC::MacroAssembler::sete32): + (JSC::MacroAssembler::setne32): + (JSC::MacroAssembler::setnz32): + (JSC::MacroAssembler::setz32): + * assembler/X86Assembler.h: + (JSC::X86Assembler::addl_mr): + (JSC::X86Assembler::andl_i8r): + (JSC::X86Assembler::cmpl_rm): + (JSC::X86Assembler::cmpl_mr): + (JSC::X86Assembler::cmpl_i8m): + (JSC::X86Assembler::subl_mr): + (JSC::X86Assembler::testl_i32m): + (JSC::X86Assembler::xorl_i32r): + (JSC::X86Assembler::movl_rm): + (JSC::X86Assembler::modRm_opmsib): + * jit/JIT.cpp: + (JSC::JIT::privateCompileMainPass): + * jit/JITInlineMethods.h: + (JSC::JIT::emitGetVirtualRegister): + (JSC::JIT::emitPutCTIArgConstant): + (JSC::JIT::emitPutCTIParam): + (JSC::JIT::emitPutImmediateToCallFrameHeader): + (JSC::JIT::emitInitRegister): + (JSC::JIT::checkStructure): + (JSC::JIT::emitJumpIfJSCell): + (JSC::JIT::emitJumpIfNotJSCell): + (JSC::JIT::emitJumpSlowCaseIfNotImmNum): + +2008-12-08 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Sam Weinig. + + Fixed a bug where WREC would allow a quantifier whose minimum was + greater than its maximum. + + * wrec/Quantifier.h: + (JSC::WREC::Quantifier::Quantifier): ASSERT that the quantifier is not + backwards. + + * wrec/WRECParser.cpp: + (JSC::WREC::Parser::consumeGreedyQuantifier): Verify that the minimum + is not greater than the maximum. + +2008-12-08 Eric Seidel <eric@webkit.org> + + Build fix only, no review. + + * JavaScriptCore.scons: add bytecode/JumpTable.cpp + +2008-12-08 Sam Weinig <sam@webkit.org> + + Reviewed by Geoffrey Garen. + + Patch for https://bugs.webkit.org/show_bug.cgi?id=22716 + <rdar://problem/6428315> + Add RareData structure to CodeBlock for infrequently used auxiliary data + members. + + Reduces memory on Membuster-head by ~.5MB + + * bytecode/CodeBlock.cpp: + (JSC::CodeBlock::dump): + (JSC::CodeBlock::dumpStatistics): + (JSC::CodeBlock::mark): + (JSC::CodeBlock::getHandlerForVPC): + (JSC::CodeBlock::nativeExceptionCodeForHandlerVPC): + (JSC::CodeBlock::shrinkToFit): + * bytecode/CodeBlock.h: + (JSC::CodeBlock::numberOfExceptionHandlers): + (JSC::CodeBlock::addExceptionHandler): + (JSC::CodeBlock::exceptionHandler): + (JSC::CodeBlock::addFunction): + (JSC::CodeBlock::function): + (JSC::CodeBlock::addUnexpectedConstant): + (JSC::CodeBlock::unexpectedConstant): + (JSC::CodeBlock::addRegExp): + (JSC::CodeBlock::regexp): + (JSC::CodeBlock::numberOfImmediateSwitchJumpTables): + (JSC::CodeBlock::addImmediateSwitchJumpTable): + (JSC::CodeBlock::immediateSwitchJumpTable): + (JSC::CodeBlock::numberOfCharacterSwitchJumpTables): + (JSC::CodeBlock::addCharacterSwitchJumpTable): + (JSC::CodeBlock::characterSwitchJumpTable): + (JSC::CodeBlock::numberOfStringSwitchJumpTables): + (JSC::CodeBlock::addStringSwitchJumpTable): + (JSC::CodeBlock::stringSwitchJumpTable): + (JSC::CodeBlock::evalCodeCache): + (JSC::CodeBlock::createRareDataIfNecessary): + +2008-11-26 Peter Kasting <pkasting@google.com> + + Reviewed by Anders Carlsson. + + https://bugs.webkit.org/show_bug.cgi?id=16814 + Allow ports to disable ActiveX->NPAPI conversion for Media Player. + Improve handling of miscellaneous ActiveX objects. + + * wtf/Platform.h: Add another ENABLE(...). + +2008-12-08 Sam Weinig <sam@webkit.org> + + Reviewed by Mark Rowe. + + Add dumping of CodeBlock member structure usage. + + * bytecode/CodeBlock.cpp: + (JSC::CodeBlock::dumpStatistics): + * bytecode/EvalCodeCache.h: + (JSC::EvalCodeCache::isEmpty): + +2008-12-08 David Kilzer <ddkilzer@apple.com> + + Bug 22555: Sort "children" sections in Xcode project files + + <https://bugs.webkit.org/show_bug.cgi?id=22555> + + Reviewed by Eric Seidel. + + * JavaScriptCore.xcodeproj/project.pbxproj: Sorted. + +2008-12-08 Tony Chang <tony@chromium.org> + + Reviewed by Eric Seidel. + + Enable Pan scrolling only when building on PLATFORM(WIN_OS) + Previously platforms like Apple Windows WebKit, Cairo Windows WebKit, + Wx and Chromium were enabling it explicitly, now we just turn it on + for all WIN_OS, later platforms can turn it off as needed on Windows + (or turn it on under Linux, etc.) + https://bugs.webkit.org/show_bug.cgi?id=22698 + + * wtf/Platform.h: + +2008-12-08 Sam Weinig <sam@webkit.org> + + Reviewed by Cameron Zwarich. + + Add basic memory statistics dumping for CodeBlock. + + * bytecode/CodeBlock.cpp: + (JSC::CodeBlock::dumpStatistics): + (JSC::CodeBlock::CodeBlock): + (JSC::CodeBlock::~CodeBlock): + * bytecode/CodeBlock.h: + +2008-12-08 Simon Hausmann <simon.hausmann@nokia.com> + + Fix the Linux build with newer gcc/glibc. + + * jit/ExecutableAllocatorPosix.cpp: Include unistd.h for + getpagesize(), according to + http://opengroup.org/onlinepubs/007908775/xsh/getpagesize.html + +2008-12-08 Simon Hausmann <simon.hausmann@nokia.com> + + Fix the build with Qt on Windows. + + * JavaScriptCore.pri: Compile ExecutableAllocatorWin.cpp on Windows. + +2008-12-07 Oliver Hunt <oliver@apple.com> + + Reviewed by NOBODY (Buildfix). + + Fix non-WREC builds + + * runtime/RegExp.cpp: + (JSC::RegExp::RegExp): + +2008-12-07 Oliver Hunt <oliver@apple.com> + + Reviewed by NOBODY (Build fix). + + Put ENABLE(ASSEMBLER) guards around use of ExecutableAllocator in global data + + Correct Qt and Gtk project files + + * GNUmakefile.am: + * JavaScriptCore.pri: + * runtime/JSGlobalData.h: + +2008-12-07 Oliver Hunt <oliver@apple.com> + + Reviewed by NOBODY (Build fix). + + Add new files to other projects. + + * GNUmakefile.am: + * JavaScriptCore.pri: + * JavaScriptCore.pro: + +2008-12-07 Oliver Hunt <oliver@apple.com> + + Rubber stamped by Mark Rowe. + + Rename ExecutableAllocatorMMAP to the more sensible ExecutableAllocatorPosix + + * JavaScriptCore.xcodeproj/project.pbxproj: + * jit/ExecutableAllocator.h: + * jit/ExecutableAllocatorPosix.cpp: Renamed from JavaScriptCore/jit/ExecutableAllocatorMMAP.cpp. + (JSC::ExecutableAllocator::intializePageSize): + (JSC::ExecutablePool::systemAlloc): + (JSC::ExecutablePool::systemRelease): + +2008-12-07 Oliver Hunt <oliver@apple.com> + + Reviewed by Cameron Zwarich and Sam Weinig + + <rdar://problem/6309878> Need more granular control over allocation of executable memory (21783) + <https://bugs.webkit.org/show_bug.cgi?id=21783> + + Add a new allocator for use by the JIT that provides executable pages, so + we can get rid of the current hack that makes the entire heap executable. + + 1-2% progression on SunSpider-v8, 1% on SunSpider. Reduces memory usage as well! + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: + * JavaScriptCore.vcproj/jsc/jsc.vcproj: + * JavaScriptCore.xcodeproj/project.pbxproj: + * assembler/AssemblerBuffer.h: + (JSC::AssemblerBuffer::size): + (JSC::AssemblerBuffer::executableCopy): + * assembler/MacroAssembler.h: + (JSC::MacroAssembler::size): + (JSC::MacroAssembler::copyCode): + * assembler/X86Assembler.h: + (JSC::X86Assembler::size): + (JSC::X86Assembler::executableCopy): + * bytecode/CodeBlock.cpp: + (JSC::CodeBlock::~CodeBlock): + * bytecode/CodeBlock.h: + (JSC::CodeBlock::executablePool): + (JSC::CodeBlock::setExecutablePool): + * bytecode/Instruction.h: + (JSC::PolymorphicAccessStructureList::derefStructures): + * interpreter/Interpreter.cpp: + (JSC::Interpreter::~Interpreter): + * interpreter/Interpreter.h: + * jit/ExecutableAllocator.cpp: Added. + * jit/ExecutableAllocator.h: Added. + (JSC::ExecutablePool::create): + (JSC::ExecutablePool::alloc): + (JSC::ExecutablePool::~ExecutablePool): + (JSC::ExecutablePool::available): + (JSC::ExecutablePool::ExecutablePool): + (JSC::ExecutablePool::poolAllocate): + (JSC::ExecutableAllocator::ExecutableAllocator): + (JSC::ExecutableAllocator::poolForSize): + (JSC::ExecutablePool::sizeForAllocation): + * jit/ExecutableAllocatorMMAP.cpp: Added. + (JSC::ExecutableAllocator::intializePageSize): + (JSC::ExecutablePool::systemAlloc): + (JSC::ExecutablePool::systemRelease): + * jit/ExecutableAllocatorWin.cpp: Added. + (JSC::ExecutableAllocator::intializePageSize): + (JSC::ExecutablePool::systemAlloc): + (JSC::ExecutablePool::systemRelease): + * jit/JIT.cpp: + (JSC::JIT::privateCompile): + (JSC::JIT::privateCompileCTIMachineTrampolines): + * jit/JIT.h: + (JSC::JIT::compileCTIMachineTrampolines): + * jit/JITPropertyAccess.cpp: + (JSC::JIT::privateCompilePutByIdTransition): + (JSC::JIT::privateCompilePatchGetArrayLength): + (JSC::JIT::privateCompileGetByIdSelf): + (JSC::JIT::privateCompileGetByIdProto): + (JSC::JIT::privateCompileGetByIdSelfList): + (JSC::JIT::privateCompileGetByIdProtoList): + (JSC::JIT::privateCompileGetByIdChainList): + (JSC::JIT::privateCompileGetByIdChain): + (JSC::JIT::privateCompilePutByIdReplace): + * parser/Nodes.cpp: + (JSC::RegExpNode::emitBytecode): + * runtime/JSGlobalData.h: + (JSC::JSGlobalData::poolForSize): + * runtime/RegExp.cpp: + (JSC::RegExp::RegExp): + (JSC::RegExp::create): + (JSC::RegExp::~RegExp): + * runtime/RegExp.h: + * runtime/RegExpConstructor.cpp: + (JSC::constructRegExp): + * runtime/RegExpPrototype.cpp: + (JSC::regExpProtoFuncCompile): + * runtime/StringPrototype.cpp: + (JSC::stringProtoFuncMatch): + (JSC::stringProtoFuncSearch): + * wrec/WREC.cpp: + (JSC::WREC::Generator::compileRegExp): + * wrec/WRECGenerator.h: + * wtf/FastMalloc.cpp: + * wtf/FastMalloc.h: + * wtf/TCSystemAlloc.cpp: + (TryMmap): + (TryVirtualAlloc): + (TryDevMem): + (TCMalloc_SystemRelease): + +2008-12-06 Sam Weinig <sam@webkit.org> + + Fix the Gtk build. + + * jit/JITPropertyAccess.cpp: + (JSC::JIT::compileGetByIdHotPath): + (JSC::JIT::compilePutByIdHotPath): + +2008-12-06 Sam Weinig <sam@webkit.org> + + Reviewed by Cameron Zwarich, + + Move CodeBlock constructor into the .cpp file. + + Sunspider reports a .7% progression, but I can only assume this + is noise. + + * bytecode/CodeBlock.cpp: + (JSC::CodeBlock::CodeBlock): + * bytecode/CodeBlock.h: + +2008-12-06 Sam Weinig <sam@webkit.org> + + Reviewed by Cameron Zwarich. + + Split JumpTable code into its own file. + + * GNUmakefile.am: + * JavaScriptCore.pri: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: + * JavaScriptCore.xcodeproj/project.pbxproj: + * JavaScriptCoreSources.bkl: + * bytecode/CodeBlock.cpp: + * bytecode/CodeBlock.h: + * bytecode/JumpTable.cpp: Copied from bytecode/CodeBlock.cpp. + * bytecode/JumpTable.h: Copied from bytecode/CodeBlock.h. + +2008-12-05 Sam Weinig <sam@webkit.org> + + Reviewed by Cameron Zwarich. + + Fix for https://bugs.webkit.org/show_bug.cgi?id=22715 + Encapsulate more CodeBlock members in preparation + of moving some of them to a rare data structure. + + * bytecode/CodeBlock.cpp: + (JSC::locationForOffset): + (JSC::printConditionalJump): + (JSC::printGetByIdOp): + (JSC::printPutByIdOp): + (JSC::CodeBlock::printStructure): + (JSC::CodeBlock::printStructures): + (JSC::CodeBlock::dump): + (JSC::CodeBlock::~CodeBlock): + (JSC::CodeBlock::unlinkCallers): + (JSC::CodeBlock::derefStructures): + (JSC::CodeBlock::refStructures): + (JSC::CodeBlock::mark): + (JSC::CodeBlock::getHandlerForVPC): + (JSC::CodeBlock::nativeExceptionCodeForHandlerVPC): + (JSC::CodeBlock::lineNumberForVPC): + (JSC::CodeBlock::expressionRangeForVPC): + (JSC::CodeBlock::shrinkToFit): + * bytecode/CodeBlock.h: + (JSC::CodeBlock::CodeBlock): + (JSC::CodeBlock::addCaller): + (JSC::CodeBlock::removeCaller): + (JSC::CodeBlock::isKnownNotImmediate): + (JSC::CodeBlock::isConstantRegisterIndex): + (JSC::CodeBlock::getConstant): + (JSC::CodeBlock::isTemporaryRegisterIndex): + (JSC::CodeBlock::getStubInfo): + (JSC::CodeBlock::getCallLinkInfo): + (JSC::CodeBlock::instructions): + (JSC::CodeBlock::setJITCode): + (JSC::CodeBlock::jitCode): + (JSC::CodeBlock::ownerNode): + (JSC::CodeBlock::setGlobalData): + (JSC::CodeBlock::setThisRegister): + (JSC::CodeBlock::thisRegister): + (JSC::CodeBlock::setNeedsFullScopeChain): + (JSC::CodeBlock::needsFullScopeChain): + (JSC::CodeBlock::setUsesEval): + (JSC::CodeBlock::usesEval): + (JSC::CodeBlock::setUsesArguments): + (JSC::CodeBlock::usesArguments): + (JSC::CodeBlock::codeType): + (JSC::CodeBlock::source): + (JSC::CodeBlock::sourceOffset): + (JSC::CodeBlock::addGlobalResolveInstruction): + (JSC::CodeBlock::numberOfPropertyAccessInstructions): + (JSC::CodeBlock::addPropertyAccessInstruction): + (JSC::CodeBlock::propertyAccessInstruction): + (JSC::CodeBlock::numberOfCallLinkInfos): + (JSC::CodeBlock::addCallLinkInfo): + (JSC::CodeBlock::callLinkInfo): + (JSC::CodeBlock::numberOfJumpTargets): + (JSC::CodeBlock::addJumpTarget): + (JSC::CodeBlock::jumpTarget): + (JSC::CodeBlock::lastJumpTarget): + (JSC::CodeBlock::numberOfExceptionHandlers): + (JSC::CodeBlock::addExceptionHandler): + (JSC::CodeBlock::exceptionHandler): + (JSC::CodeBlock::addExpressionInfo): + (JSC::CodeBlock::numberOfLineInfos): + (JSC::CodeBlock::addLineInfo): + (JSC::CodeBlock::lastLineInfo): + (JSC::CodeBlock::jitReturnAddressVPCMap): + (JSC::CodeBlock::numberOfIdentifiers): + (JSC::CodeBlock::addIdentifier): + (JSC::CodeBlock::identifier): + (JSC::CodeBlock::numberOfConstantRegisters): + (JSC::CodeBlock::addConstantRegister): + (JSC::CodeBlock::constantRegister): + (JSC::CodeBlock::addFunction): + (JSC::CodeBlock::function): + (JSC::CodeBlock::addFunctionExpression): + (JSC::CodeBlock::functionExpression): + (JSC::CodeBlock::addUnexpectedConstant): + (JSC::CodeBlock::unexpectedConstant): + (JSC::CodeBlock::addRegExp): + (JSC::CodeBlock::regexp): + (JSC::CodeBlock::symbolTable): + (JSC::CodeBlock::evalCodeCache): + New inline setters/getters. + + (JSC::ProgramCodeBlock::ProgramCodeBlock): + (JSC::ProgramCodeBlock::~ProgramCodeBlock): + (JSC::ProgramCodeBlock::clearGlobalObject): + * bytecode/SamplingTool.cpp: + (JSC::ScopeSampleRecord::sample): + (JSC::SamplingTool::dump): + * bytecompiler/BytecodeGenerator.cpp: + * bytecompiler/BytecodeGenerator.h: + * bytecompiler/Label.h: + * interpreter/CallFrame.cpp: + * interpreter/Interpreter.cpp: + * jit/JIT.cpp: + * jit/JITCall.cpp: + * jit/JITInlineMethods.h: + * jit/JITPropertyAccess.cpp: + * parser/Nodes.cpp: + * runtime/Arguments.h: + * runtime/ExceptionHelpers.cpp: + * runtime/JSActivation.cpp: + * runtime/JSActivation.h: + * runtime/JSGlobalObject.cpp: + Change direct access to use new getter/setters. + +2008-12-05 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Oliver Hunt. + + Prevent GCC4.2 from hanging when trying to compile Interpreter.cpp. + Added "-fno-var-tracking" compiler flag. + + https://bugs.webkit.org/show_bug.cgi?id=22704 + + * JavaScriptCore.xcodeproj/project.pbxproj: + +2008-12-05 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Oliver Hunt. + + Ordering of branch operands in MacroAssembler in unnecessarily inconsistent. + + je, jg etc take an immediate operand as the second argument, but for the + equality branches (je, jne) the immediate operand was the first argument. This + was unnecessarily inconsistent. Change je, jne methods to take the immediate + as the second argument. + + https://bugs.webkit.org/show_bug.cgi?id=22703 + + * assembler/MacroAssembler.h: + (JSC::MacroAssembler::je32): + (JSC::MacroAssembler::jne32): + * jit/JIT.cpp: + (JSC::JIT::compileOpStrictEq): + * wrec/WRECGenerator.cpp: + (JSC::WREC::Generator::generateEnter): + (JSC::WREC::Generator::generateNonGreedyQuantifier): + (JSC::WREC::Generator::generateGreedyQuantifier): + (JSC::WREC::Generator::generatePatternCharacterPair): + (JSC::WREC::Generator::generatePatternCharacter): + (JSC::WREC::Generator::generateCharacterClassInvertedRange): + (JSC::WREC::Generator::generateCharacterClassInverted): + (JSC::WREC::Generator::generateAssertionBOL): + (JSC::WREC::Generator::generateAssertionWordBoundary): + +2008-12-05 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Geoff Garen. + + Second tranche of porting JIT.cpp to MacroAssembler interface. + + * assembler/MacroAssembler.h: + (JSC::MacroAssembler::mul32): + (JSC::MacroAssembler::jl32): + (JSC::MacroAssembler::jnzSub32): + (JSC::MacroAssembler::joAdd32): + (JSC::MacroAssembler::joMul32): + (JSC::MacroAssembler::jzSub32): + * jit/JIT.cpp: + (JSC::JIT::emitSlowScriptCheck): + (JSC::JIT::privateCompileMainPass): + (JSC::JIT::privateCompileSlowCases): + (JSC::JIT::privateCompileCTIMachineTrampolines): + * jit/JIT.h: + * jit/JITInlineMethods.h: + (JSC::JIT::emitJumpIfNotJSCell): + (JSC::JIT::emitJumpSlowCaseIfNotJSCell): + +2008-12-05 David Kilzer <ddkilzer@apple.com> + + Bug 22609: Provide a build-time choice when generating hash tables for properties of built-in DOM objects + + <https://bugs.webkit.org/show_bug.cgi?id=22609> + <rdar://problem/6331749> + + Reviewed by Darin Adler. + + Initial patch by Yosen Lin. Adapted for ToT WebKit by David Kilzer. + + Added back the code that generates a "compact" hash (instead of a + perfect hash) as a build-time option using the + ENABLE(PERFECT_HASH_SIZE) macro as defined in Lookup.h. + + * create_hash_table: Rename variables to differentiate perfect hash + values from compact hash values. Added back code to compute compact + hash tables. Generate both hash table sizes and emit + conditionalized code based on ENABLE(PERFECT_HASH_SIZE). + * runtime/Lookup.cpp: + (JSC::HashTable::createTable): Added version of createTable() for + use with compact hash tables. + (JSC::HashTable::deleteTable): Updated to work with compact hash + tables. + * runtime/Lookup.h: Defined ENABLE(PERFECT_HASH_SIZE) macro here. + (JSC::HashEntry::initialize): Set m_next to zero when using compact + hash tables. + (JSC::HashEntry::setNext): Added for compact hash tables. + (JSC::HashEntry::next): Added for compact hash tables. + (JSC::HashTable::entry): Added version of entry() for use with + compact hash tables. + * runtime/Structure.cpp: + (JSC::Structure::getEnumerablePropertyNames): Updated to work with + compact hash tables. + +2008-12-05 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Geoff Garen. + + Remove redundant calls to JIT::emitSlowScriptCheck. + This is checked in the hot path, so is not needed on the slow path - and the code + was being planted before the start of the slow case, so was completely unreachable! + + * jit/JIT.cpp: + (JSC::JIT::privateCompileSlowCases): + +2008-12-05 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Geoff Garen. + + Move JIT::compileOpStrictEq to MacroAssembler interface. + + The rewrite also looks like a small (<1%) performance progression. + + https://bugs.webkit.org/show_bug.cgi?id=22697 + + * jit/JIT.cpp: + (JSC::JIT::compileOpStrictEq): + (JSC::JIT::privateCompileSlowCases): + * jit/JIT.h: + * jit/JITInlineMethods.h: + (JSC::JIT::emitJumpIfJSCell): + (JSC::JIT::emitJumpSlowCaseIfJSCell): + +2008-12-05 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Geoff Garen. + + Remove m_assembler from MacroAssembler::Jump. + Keeping a pointer allowed for some syntactic sugar - "link()" looks nicer + than "link(this)". But maintaining this doubles the size of Jump, which + is even more unfortunate for the JIT, since there are many large structures + holding JmpSrcs. Probably best to remove it. + + https://bugs.webkit.org/show_bug.cgi?id=22693 + + * assembler/MacroAssembler.h: + (JSC::MacroAssembler::Jump::Jump): + (JSC::MacroAssembler::Jump::link): + (JSC::MacroAssembler::Jump::linkTo): + (JSC::MacroAssembler::JumpList::link): + (JSC::MacroAssembler::JumpList::linkTo): + (JSC::MacroAssembler::jae32): + (JSC::MacroAssembler::je32): + (JSC::MacroAssembler::je16): + (JSC::MacroAssembler::jg32): + (JSC::MacroAssembler::jge32): + (JSC::MacroAssembler::jl32): + (JSC::MacroAssembler::jle32): + (JSC::MacroAssembler::jnePtr): + (JSC::MacroAssembler::jne32): + (JSC::MacroAssembler::jnset32): + (JSC::MacroAssembler::jset32): + (JSC::MacroAssembler::jump): + (JSC::MacroAssembler::jzSub32): + (JSC::MacroAssembler::joAdd32): + (JSC::MacroAssembler::call): + * wrec/WREC.cpp: + (JSC::WREC::Generator::compileRegExp): + * wrec/WRECGenerator.cpp: + (JSC::WREC::Generator::generateEnter): + (JSC::WREC::Generator::generateBackreferenceQuantifier): + (JSC::WREC::Generator::generateNonGreedyQuantifier): + (JSC::WREC::Generator::generateGreedyQuantifier): + (JSC::WREC::Generator::generatePatternCharacter): + (JSC::WREC::Generator::generateCharacterClassInvertedRange): + (JSC::WREC::Generator::generateCharacterClassInverted): + (JSC::WREC::Generator::generateCharacterClass): + (JSC::WREC::Generator::generateParenthesesAssertion): + (JSC::WREC::Generator::generateParenthesesInvertedAssertion): + (JSC::WREC::Generator::generateParenthesesNonGreedy): + (JSC::WREC::Generator::generateParenthesesResetTrampoline): + (JSC::WREC::Generator::generateAssertionBOL): + (JSC::WREC::Generator::generateAssertionEOL): + (JSC::WREC::Generator::generateAssertionWordBoundary): + (JSC::WREC::Generator::generateBackreference): + (JSC::WREC::Generator::terminateAlternative): + (JSC::WREC::Generator::terminateDisjunction): + * wrec/WRECParser.h: + +2008-12-05 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Geoffrey Garen. + + Simplify JIT generated checks for timeout code, by moving more work into the C function. + https://bugs.webkit.org/show_bug.cgi?id=22688 + + * interpreter/Interpreter.cpp: + (JSC::Interpreter::cti_timeout_check): + * interpreter/Interpreter.h: + * jit/JIT.cpp: + (JSC::JIT::emitSlowScriptCheck): + +2008-12-05 Sam Weinig <sam@webkit.org> + + Reviewed by Geoffrey Garen. + + Encapsulate access to jump tables in the CodeBlock in preparation + of moving them to a rare data structure. + + * bytecode/CodeBlock.cpp: + (JSC::CodeBlock::dump): + (JSC::CodeBlock::shrinkToFit): + * bytecode/CodeBlock.h: + (JSC::CodeBlock::numberOfImmediateSwitchJumpTables): + (JSC::CodeBlock::addImmediateSwitchJumpTable): + (JSC::CodeBlock::immediateSwitchJumpTable): + (JSC::CodeBlock::numberOfCharacterSwitchJumpTables): + (JSC::CodeBlock::addCharacterSwitchJumpTable): + (JSC::CodeBlock::characterSwitchJumpTable): + (JSC::CodeBlock::numberOfStringSwitchJumpTables): + (JSC::CodeBlock::addStringSwitchJumpTable): + (JSC::CodeBlock::stringSwitchJumpTable): + * bytecompiler/BytecodeGenerator.cpp: + (JSC::BytecodeGenerator::generate): + (JSC::BytecodeGenerator::endSwitch): + * interpreter/Interpreter.cpp: + (JSC::Interpreter::privateExecute): + (JSC::Interpreter::cti_op_switch_imm): + (JSC::Interpreter::cti_op_switch_char): + (JSC::Interpreter::cti_op_switch_string): + * jit/JIT.cpp: + (JSC::JIT::privateCompileMainPass): + +2008-12-05 Adam Roben <aroben@apple.com> + + Windows build fix after r39020 + + * jit/JITInlineMethods.h: + (JSC::JIT::restoreArgumentReference): + (JSC::JIT::restoreArgumentReferenceForTrampoline): + Add some apparently-missing __. + +2008-12-04 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Darin Adler. + + https://bugs.webkit.org/show_bug.cgi?id=22673 + + Added support for the assertion (?=) and inverted assertion (?!) atoms + in WREC. + + * wrec/WRECGenerator.cpp: + (JSC::WREC::Generator::generateParenthesesAssertion): + (JSC::WREC::Generator::generateParenthesesInvertedAssertion): Split the + old (unused) generateParentheses into these two functions, with more + limited capabilities. + + * wrec/WRECGenerator.h: + (JSC::WREC::Generator::): Moved an enum to the top of the class definition, + to match the WebKit style, and removed a defunct comment. + + * wrec/WRECParser.cpp: + (JSC::WREC::Parser::parseParentheses): + (JSC::WREC::Parser::consumeParenthesesType): + * wrec/WRECParser.h: + (JSC::WREC::Parser::): Added support for parsing (?=) and (?!). + +2008-12-05 Simon Hausmann <simon.hausmann@nokia.com> + + Rubber-stamped by Tor Arne Vestbø. + + Disable the JIT for the Qt build alltogether again, after observing + more miscompilations in a wider range of newer gcc versions. + + * JavaScriptCore.pri: + +2008-12-05 Simon Hausmann <simon.hausmann@nokia.com> + + Reviewed by Tor Arne Vestbø. + + Disable the JIT for the Qt build on Linux unless gcc is >= 4.2, + due to miscompilations. + + * JavaScriptCore.pri: + +2008-12-04 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Geoff Garen. + + Start porting the JIT to use the MacroAssembler. + + https://bugs.webkit.org/show_bug.cgi?id=22671 + No change in performance. + + * assembler/MacroAssembler.h: + (JSC::MacroAssembler::Jump::operator X86Assembler::JmpSrc): + (JSC::MacroAssembler::add32): + (JSC::MacroAssembler::and32): + (JSC::MacroAssembler::lshift32): + (JSC::MacroAssembler::rshift32): + (JSC::MacroAssembler::storePtr): + (JSC::MacroAssembler::store32): + (JSC::MacroAssembler::poke): + (JSC::MacroAssembler::move): + (JSC::MacroAssembler::compareImm32ForBranchEquality): + (JSC::MacroAssembler::jnePtr): + (JSC::MacroAssembler::jnset32): + (JSC::MacroAssembler::jset32): + (JSC::MacroAssembler::jzeroSub32): + (JSC::MacroAssembler::joverAdd32): + (JSC::MacroAssembler::call): + * assembler/X86Assembler.h: + (JSC::X86Assembler::shll_i8r): + * jit/JIT.cpp: + (JSC::JIT::privateCompileMainPass): + (JSC::JIT::privateCompile): + (JSC::JIT::privateCompileCTIMachineTrampolines): + * jit/JIT.h: + * jit/JITArithmetic.cpp: + (JSC::JIT::compileBinaryArithOp): + * jit/JITInlineMethods.h: + (JSC::JIT::emitGetVirtualRegister): + (JSC::JIT::emitPutCTIArg): + (JSC::JIT::emitPutCTIArgConstant): + (JSC::JIT::emitGetCTIArg): + (JSC::JIT::emitPutCTIArgFromVirtualRegister): + (JSC::JIT::emitPutCTIParam): + (JSC::JIT::emitGetCTIParam): + (JSC::JIT::emitPutToCallFrameHeader): + (JSC::JIT::emitPutImmediateToCallFrameHeader): + (JSC::JIT::emitGetFromCallFrameHeader): + (JSC::JIT::emitPutVirtualRegister): + (JSC::JIT::emitInitRegister): + (JSC::JIT::emitNakedCall): + (JSC::JIT::restoreArgumentReference): + (JSC::JIT::restoreArgumentReferenceForTrampoline): + (JSC::JIT::emitCTICall): + (JSC::JIT::checkStructure): + (JSC::JIT::emitJumpSlowCaseIfNotJSCell): + (JSC::JIT::emitJumpSlowCaseIfNotImmNum): + (JSC::JIT::emitJumpSlowCaseIfNotImmNums): + (JSC::JIT::emitFastArithDeTagImmediate): + (JSC::JIT::emitFastArithDeTagImmediateJumpIfZero): + (JSC::JIT::emitFastArithReTagImmediate): + (JSC::JIT::emitFastArithPotentiallyReTagImmediate): + (JSC::JIT::emitFastArithImmToInt): + (JSC::JIT::emitFastArithIntToImmOrSlowCase): + (JSC::JIT::emitFastArithIntToImmNoCheck): + (JSC::JIT::emitTagAsBoolImmediate): + * jit/JITPropertyAccess.cpp: + (JSC::JIT::privateCompilePutByIdTransition): + +2008-12-04 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Oliver Hunt. + + Some refactoring for generateGreedyQuantifier. + + SunSpider reports no change (possibly a 0.3% speedup). + + * wrec/WRECGenerator.cpp: + (JSC::WREC::Generator::generateGreedyQuantifier): Clarified label + meanings and unified some logic to simplify things. + + * wrec/WRECParser.h: + (JSC::WREC::Parser::parseAlternative): Added a version of parseAlternative + that can jump to a Label, instead of a JumpList, upon failure. (Eventually, + when we have a true Label class, this will be redundant.) This makes + things easier for generateGreedyQuantifier, because it can avoid + explicitly linking things. + +2008-12-04 Simon Hausmann <simon.hausmann@nokia.com> + + Reviewed by Holger Freyther. + + Fix crashes in the Qt build on Linux/i386 with non-executable memory + by enabling TCSystemAlloc and the PROT_EXEC flag for mmap. + + * JavaScriptCore.pri: Enable the use of TCSystemAlloc if the JIT is + enabled. + * wtf/TCSystemAlloc.cpp: Extend the PROT_EXEC permissions to + PLATFORM(QT). + +2008-12-04 Simon Hausmann <simon.hausmann@nokia.com> + + Reviewed by Tor Arne Vestbø. + + Enable ENABLE_JIT_OPTIMIZE_CALL, ENABLE_JIT_OPTIMIZE_PROPERTY_ACCESS + and ENABLE_JIT_OPTIMIZE_ARITHMETIC, as suggested by Niko. + + * JavaScriptCore.pri: + +2008-12-04 Kent Hansen <khansen@trolltech.com> + + Reviewed by Simon Hausmann. + + Enable the JSC jit for the Qt build by default for release builds on + linux-g++ and win32-msvc. + + * JavaScriptCore.pri: + +2008-12-04 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Oliver Hunt. + + Allow JIT to function without property access repatching and arithmetic optimizations. + Controlled by ENABLE_JIT_OPTIMIZE_PROPERTY_ACCESS and ENABLE_JIT_OPTIMIZE_ARITHMETIC switches. + + https://bugs.webkit.org/show_bug.cgi?id=22643 + + * JavaScriptCore.xcodeproj/project.pbxproj: + * jit/JIT.cpp: + (JSC::JIT::privateCompileMainPass): + (JSC::JIT::privateCompileSlowCases): + * jit/JIT.h: + * jit/JITArithmetic.cpp: Copied from jit/JIT.cpp. + (JSC::JIT::compileBinaryArithOp): + (JSC::JIT::compileBinaryArithOpSlowCase): + * jit/JITPropertyAccess.cpp: Copied from jit/JIT.cpp. + (JSC::JIT::compileGetByIdHotPath): + (JSC::JIT::compileGetByIdSlowCase): + (JSC::JIT::compilePutByIdHotPath): + (JSC::JIT::compilePutByIdSlowCase): + (JSC::resizePropertyStorage): + (JSC::transitionWillNeedStorageRealloc): + (JSC::JIT::privateCompilePutByIdTransition): + (JSC::JIT::patchGetByIdSelf): + (JSC::JIT::patchPutByIdReplace): + (JSC::JIT::privateCompilePatchGetArrayLength): + * wtf/Platform.h: + +2008-12-03 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Oliver Hunt. + + Optimized sequences of characters in regular expressions by comparing + two characters at a time. + + 1-2% speedup on SunSpider, 19-25% speedup on regexp-dna. + + * assembler/MacroAssembler.h: + (JSC::MacroAssembler::load32): + (JSC::MacroAssembler::jge32): Filled out a few more macro methods. + + * assembler/X86Assembler.h: + (JSC::X86Assembler::movl_mr): Added a verion of movl_mr that operates + without an offset, to allow the macro assembler to optmize for that case. + + * wrec/WREC.cpp: + (JSC::WREC::Generator::compileRegExp): Test the saved value of index + instead of the index register when checking for "end of input." The + index register doesn't increment by 1 in an orderly fashion, so testing + it for == "end of input" is not valid. + + Also, jump all the way to "return failure" upon reaching "end of input," + instead of executing the next alternative. This is more logical, and + it's a slight optimization in the case of an expression with many alternatives. + + * wrec/WRECGenerator.cpp: + (JSC::WREC::Generator::generateIncrementIndex): Added support for + jumping to a failure label in the case where the index has reached "end + of input." + + (JSC::WREC::Generator::generatePatternCharacterSequence): + (JSC::WREC::Generator::generatePatternCharacterPair): This is the + optmization. It's basically like generatePatternCharacter, but it runs two + characters at a time. + + (JSC::WREC::Generator::generatePatternCharacter): Changed to use isASCII, + since it's clearer than comparing to a magic hex value. + + * wrec/WRECGenerator.h: + +2008-12-03 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Cameron Zwarich. + + Allow JIT to operate without the call-repatching optimization. + Controlled by ENABLE(JIT_OPTIMIZE_CALL), defaults on, disabling + this leads to significant performance regression. + + https://bugs.webkit.org/show_bug.cgi?id=22639 + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: + * JavaScriptCore.xcodeproj/project.pbxproj: + * jit/JIT.cpp: + (JSC::JIT::privateCompileSlowCases): + * jit/JIT.h: + * jit/JITCall.cpp: Copied from jit/JIT.cpp. + (JSC::JIT::compileOpCallInitializeCallFrame): + (JSC::JIT::compileOpCallSetupArgs): + (JSC::JIT::compileOpCallEvalSetupArgs): + (JSC::JIT::compileOpConstructSetupArgs): + (JSC::JIT::compileOpCall): + (JSC::JIT::compileOpCallSlowCase): + (JSC::unreachable): + * jit/JITInlineMethods.h: Copied from jit/JIT.cpp. + (JSC::JIT::checkStructure): + (JSC::JIT::emitFastArithPotentiallyReTagImmediate): + (JSC::JIT::emitTagAsBoolImmediate): + * wtf/Platform.h: + +2008-12-03 Eric Seidel <eric@webkit.org> + + Rubber-stamped by David Hyatt. + + Make HAVE_ACCESSIBILITY only define if !defined + + * wtf/Platform.h: + +2008-12-03 Sam Weinig <sam@webkit.org> + + Fix build. + + * assembler/X86Assembler.h: + (JSC::X86Assembler::orl_i32r): + +2008-12-03 Sam Weinig <sam@webkit.org> + + Reviewed by Geoffrey Garen. + + Remove shared AssemblerBuffer 1MB buffer and instead give AssemblerBuffer + an 256 byte inline capacity. + + 1% progression on Sunspider. + + * assembler/AssemblerBuffer.h: + (JSC::AssemblerBuffer::AssemblerBuffer): + (JSC::AssemblerBuffer::~AssemblerBuffer): + (JSC::AssemblerBuffer::grow): + * assembler/MacroAssembler.h: + (JSC::MacroAssembler::MacroAssembler): + * assembler/X86Assembler.h: + (JSC::X86Assembler::X86Assembler): + * interpreter/Interpreter.cpp: + (JSC::Interpreter::Interpreter): + * interpreter/Interpreter.h: + * jit/JIT.cpp: + (JSC::JIT::JIT): + * parser/Nodes.cpp: + (JSC::RegExpNode::emitBytecode): + * runtime/RegExp.cpp: + (JSC::RegExp::RegExp): + (JSC::RegExp::create): + * runtime/RegExp.h: + * runtime/RegExpConstructor.cpp: + (JSC::constructRegExp): + * runtime/RegExpPrototype.cpp: + (JSC::regExpProtoFuncCompile): + * runtime/StringPrototype.cpp: + (JSC::stringProtoFuncMatch): + (JSC::stringProtoFuncSearch): + * wrec/WREC.cpp: + (JSC::WREC::Generator::compileRegExp): + * wrec/WRECGenerator.h: + (JSC::WREC::Generator::Generator): + * wrec/WRECParser.h: + (JSC::WREC::Parser::Parser): + +2008-12-03 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Oliver Hunt, with help from Gavin Barraclough. + + orl_i32r was actually coded as an 8bit OR. So, I renamed orl_i32r to + orl_i8r, changed all orl_i32r clients to use orl_i8r, and then added + a new orl_i32r that actually does a 32bit OR. + + (32bit OR is currently unused, but a patch I'm working on uses it.) + + * assembler/MacroAssembler.h: + (JSC::MacroAssembler::or32): Updated to choose between 8bit and 32bit OR. + + * assembler/X86Assembler.h: + (JSC::X86Assembler::orl_i8r): The old orl_i32r. + (JSC::X86Assembler::orl_i32r): The new orl_i32r. + + * jit/JIT.cpp: + (JSC::JIT::emitFastArithPotentiallyReTagImmediate): + (JSC::JIT::emitTagAsBoolImmediate): Use orl_i8r, since we're ORing 8bit + values. + +2008-12-03 Dean Jackson <dino@apple.com> + + Reviewed by Dan Bernstein. + + Helper functions for turn -> degrees. + https://bugs.webkit.org/show_bug.cgi?id=22497 + + * wtf/MathExtras.h: + (turn2deg): + (deg2turn): + +2008-12-02 Cameron Zwarich <zwarich@apple.com> + + Reviewed by Geoff Garen. + + Bug 22504: Crashes during code generation occur due to refing of ignoredResult() + <https://bugs.webkit.org/show_bug.cgi?id=22504> + + Since ignoredResult() was implemented by casting 1 to a RegisterID*, any + attempt to ref ignoredResult() results in a crash. This will occur in + code generation of a function body where a node emits another node with + the dst that was passed to it, and then refs the returned RegisterID*. + + To fix this problem, make ignoredResult() a member function of + BytecodeGenerator that simply returns a pointe to a fixed RegisterID + member of BytecodeGenerator. + + * bytecompiler/BytecodeGenerator.h: + (JSC::BytecodeGenerator::ignoredResult): + * bytecompiler/RegisterID.h: + * parser/Nodes.cpp: + (JSC::NullNode::emitBytecode): + (JSC::BooleanNode::emitBytecode): + (JSC::NumberNode::emitBytecode): + (JSC::StringNode::emitBytecode): + (JSC::RegExpNode::emitBytecode): + (JSC::ThisNode::emitBytecode): + (JSC::ResolveNode::emitBytecode): + (JSC::ObjectLiteralNode::emitBytecode): + (JSC::PostfixResolveNode::emitBytecode): + (JSC::PostfixBracketNode::emitBytecode): + (JSC::PostfixDotNode::emitBytecode): + (JSC::DeleteValueNode::emitBytecode): + (JSC::VoidNode::emitBytecode): + (JSC::TypeOfResolveNode::emitBytecode): + (JSC::TypeOfValueNode::emitBytecode): + (JSC::PrefixResolveNode::emitBytecode): + (JSC::AssignResolveNode::emitBytecode): + (JSC::CommaNode::emitBytecode): + (JSC::ForNode::emitBytecode): + (JSC::ForInNode::emitBytecode): + (JSC::ReturnNode::emitBytecode): + (JSC::ThrowNode::emitBytecode): + (JSC::FunctionBodyNode::emitBytecode): + (JSC::FuncDeclNode::emitBytecode): + +2008-12-02 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Cameron Zwarich. + + Fixed https://bugs.webkit.org/show_bug.cgi?id=22537 + REGRESSION (r38745): Assertion failure in jsSubstring() at ge.com + + The bug was that index would become greater than length, so our + "end of input" checks, which all check "index == length", would fail. + + The solution is to check for end of input before incrementing index, + to ensure that index is always <= length. + + As a side benefit, generateJumpIfEndOfInput can now use je instead of + jg, which should be slightly faster. + + * wrec/WREC.cpp: + (JSC::WREC::Generator::compileRegExp): + * wrec/WRECGenerator.cpp: + (JSC::WREC::Generator::generateJumpIfEndOfInput): + +2008-12-02 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Geoffrey Garen. + + Plant shift right immediate instructions, which are awesome. + https://bugs.webkit.org/show_bug.cgi?id=22610 + ~5% on the v8-crypto test. + + * jit/JIT.cpp: + (JSC::JIT::privateCompileMainPass): + (JSC::JIT::privateCompileSlowCases): + +2008-12-02 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Sam Weinig. + + Cleaned up SegmentedVector by abstracting segment access into helper + functions. + + SunSpider reports no change. + + * bytecompiler/SegmentedVector.h: + (JSC::SegmentedVector::SegmentedVector): + (JSC::SegmentedVector::~SegmentedVector): + (JSC::SegmentedVector::size): + (JSC::SegmentedVector::at): + (JSC::SegmentedVector::operator[]): + (JSC::SegmentedVector::last): + (JSC::SegmentedVector::append): + (JSC::SegmentedVector::removeLast): + (JSC::SegmentedVector::grow): + (JSC::SegmentedVector::clear): + (JSC::SegmentedVector::deleteAllSegments): + (JSC::SegmentedVector::segmentFor): + (JSC::SegmentedVector::subscriptFor): + (JSC::SegmentedVector::ensureSegmentsFor): + (JSC::SegmentedVector::ensureSegment): + +2008-12-02 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Geoffrey Garen. (Patch by Cameron Zwarich <zwarich@apple.com>.) + + Fixed https://bugs.webkit.org/show_bug.cgi?id=22482 + REGRESSION (r37991): Occasionally see "Scene rendered incorrectly" + message when running the V8 Raytrace benchmark + + Rolled out r37991. It didn't properly save xmm0, which is caller-save, + before calling helper functions. + + SunSpider and v8 benchmarks show little change -- possibly a .2% + SunSpider regression, possibly a .2% v8 benchmark speedup. + + * assembler/X86Assembler.h: + (JSC::X86Assembler::): + * bytecode/CodeBlock.cpp: + (JSC::CodeBlock::dump): + * bytecode/Instruction.h: + (JSC::Instruction::): + * bytecompiler/BytecodeGenerator.cpp: + (JSC::BytecodeGenerator::emitUnaryOp): + * bytecompiler/BytecodeGenerator.h: + (JSC::BytecodeGenerator::emitToJSNumber): + (JSC::BytecodeGenerator::emitTypeOf): + (JSC::BytecodeGenerator::emitGetPropertyNames): + * interpreter/Interpreter.cpp: + (JSC::Interpreter::privateExecute): + * interpreter/Interpreter.h: + * jit/JIT.cpp: + (JSC::JIT::privateCompileMainPass): + (JSC::JIT::privateCompileSlowCases): + * jit/JIT.h: + * parser/Nodes.cpp: + (JSC::UnaryOpNode::emitBytecode): + (JSC::BinaryOpNode::emitBytecode): + (JSC::EqualNode::emitBytecode): + * parser/ResultType.h: + (JSC::ResultType::isReusable): + (JSC::ResultType::mightBeNumber): + * runtime/JSNumberCell.h: + +2008-12-01 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Geoffrey Garen. + + Remove unused (sampling only, and derivable) argument to JIT::emitCTICall. + https://bugs.webkit.org/show_bug.cgi?id=22587 + + * jit/JIT.cpp: + (JSC::JIT::emitCTICall): + (JSC::JIT::compileOpCall): + (JSC::JIT::emitSlowScriptCheck): + (JSC::JIT::compileBinaryArithOpSlowCase): + (JSC::JIT::privateCompileMainPass): + (JSC::JIT::privateCompileSlowCases): + (JSC::JIT::privateCompile): + * jit/JIT.h: + +2008-12-02 Dimitri Glazkov <dglazkov@chromium.org> + + Reviewed by Eric Seidel. + + Fix the inheritance chain for JSFunction. + + * runtime/JSFunction.cpp: + (JSC::JSFunction::info): Add InternalFunction::info as parent class + +2008-12-02 Simon Hausmann <hausmann@webkit.org> + + Reviewed by Tor Arne Vestbø. + + Fix ability to include JavaScriptCore.pri from other .pro files. + + * JavaScriptCore.pri: Moved -O3 setting into the .pro files. + * JavaScriptCore.pro: + * jsc.pro: + +2008-12-01 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Cameron Zwarich, with help from Gavin Barraclough. + + Fixed https://bugs.webkit.org/show_bug.cgi?id=22583. + + Refactored regular expression parsing to parse sequences of characters + as a single unit, in preparation for optimizing sequences of characters. + + SunSpider reports no change. + + * JavaScriptCore.xcodeproj/project.pbxproj: + * wrec/Escapes.h: Added. Set of classes for representing an escaped + token in a pattern. + + * wrec/Quantifier.h: + (JSC::WREC::Quantifier::Quantifier): Simplified this constructor slightly, + to match the new Escape constructor. + + * wrec/WRECGenerator.cpp: + (JSC::WREC::Generator::generatePatternCharacterSequence): + * wrec/WRECGenerator.h: Added an interface for generating a sequence + of pattern characters at a time. It doesn't do anything special yet. + + * wrec/WRECParser.cpp: + (JSC::WREC::Parser::consumeGreedyQuantifier): + (JSC::WREC::Parser::consumeQuantifier): Renamed "parse" to "consume" in + these functions, to match "consumeEscape." + + (JSC::WREC::Parser::parsePatternCharacterSequence): New function for + iteratively aggregating a sequence of characters in a pattern. + + (JSC::WREC::Parser::parseCharacterClassQuantifier): + (JSC::WREC::Parser::parseBackreferenceQuantifier): Renamed "parse" to + "consume" in these functions, to match "consumeEscape." + + (JSC::WREC::Parser::parseCharacterClass): Refactored to use the common + escape processing code in consumeEscape. + + (JSC::WREC::Parser::parseEscape): Refactored to use the common + escape processing code in consumeEscape. + + (JSC::WREC::Parser::consumeEscape): Factored escaped token processing + into a common function, since we were doing this in a few places. + + (JSC::WREC::Parser::parseTerm): Refactored to use the common + escape processing code in consumeEscape. + + * wrec/WRECParser.h: + (JSC::WREC::Parser::consumeOctal): Refactored to use a helper function + for reading a digit. + +2008-12-01 Cameron Zwarich <zwarich@apple.com> + + Reviewed by Oliver Hunt. + + Bug 20340: SegmentedVector segment allocations can lead to unsafe use of temporary registers + <https://bugs.webkit.org/show_bug.cgi?id=20340> + + SegmentedVector currently frees segments and reallocates them when used + as a stack. This can lead to unsafe use of pointers into freed segments. + + In order to fix this problem, SegmentedVector will be changed to only + grow and never shrink. Also, rename the reserveCapacity() member + function to grow() to match the actual usage in BytecodeGenerator, where + this function is used to allocate a group of registers at once, rather + than merely saving space for them. + + * bytecompiler/BytecodeGenerator.cpp: + (JSC::BytecodeGenerator::BytecodeGenerator): Use grow() instead of + reserveCapacity(). + * bytecompiler/SegmentedVector.h: + (JSC::SegmentedVector::SegmentedVector): + (JSC::SegmentedVector::last): + (JSC::SegmentedVector::append): + (JSC::SegmentedVector::removeLast): + (JSC::SegmentedVector::grow): Renamed from reserveCapacity(). + (JSC::SegmentedVector::clear): + +2008-12-01 Mark Rowe <mrowe@apple.com> + + Rubber-stamped by Anders Carlsson. + + Disable WREC for x86_64 since memory allocated by the system allocator is not marked executable, + which causes 64-bit debug builds to crash. Once we have a dedicated allocator for executable + memory we can turn this back on. + + * wtf/Platform.h: + +2008-12-01 Antti Koivisto <antti@apple.com> + + Reviewed by Maciej Stachowiak. + + Restore inline buffer after vector is shrunk back below its inline capacity. + + * wtf/Vector.h: + (WTF::): + (WTF::VectorBuffer::restoreInlineBufferIfNeeded): + (WTF::::shrinkCapacity): + +2008-11-30 Antti Koivisto <antti@apple.com> + + Reviewed by Mark Rowe. + + Try to return free pages in the current thread cache too. + + * wtf/FastMalloc.cpp: + (WTF::TCMallocStats::releaseFastMallocFreeMemory): + +2008-12-01 David Levin <levin@chromium.org> + + Reviewed by Alexey Proskuryakov. + + https://bugs.webkit.org/show_bug.cgi?id=22567 + Make HashTable work as expected with respect to threads. Specifically, it has class-level + thread safety and constant methods work on constant objects without synchronization. + + No observable change in behavior, so no test. This only affects debug builds. + + * wtf/HashTable.cpp: + (WTF::hashTableStatsMutex): + (WTF::HashTableStats::~HashTableStats): + (WTF::HashTableStats::recordCollisionAtCount): + Guarded variable access with a mutex. + + * wtf/HashTable.h: + (WTF::::lookup): + (WTF::::lookupForWriting): + (WTF::::fullLookupForWriting): + (WTF::::add): + (WTF::::reinsert): + (WTF::::remove): + (WTF::::rehash): + Changed increments of static variables to use atomicIncrement. + + (WTF::::invalidateIterators): + (WTF::addIterator): + (WTF::removeIterator): + Guarded mutable access with a mutex. + +2008-11-29 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Cameron Zwarich. + + Enable WREC on PLATFORM(X86_64). This change predominantly requires changes to the + WREC::Generator::generateEnter method to support the x86-64 ABI, and addition of + support for a limited number of quadword operations in the X86Assembler. + + This patch will cause the JS heap to be allocated with RWX permissions on 64-bit Mac + platforms. This is a regression with respect to previous 64-bit behaviour, but is no + more permissive than on 32-bit builds. This issue should be addressed at some point. + (This is tracked by bug #21783.) + + https://bugs.webkit.org/show_bug.cgi?id=22554 + Greater than 4x speedup on regexp-dna, on x86-64. + + * assembler/MacroAssembler.h: + (JSC::MacroAssembler::addPtr): + (JSC::MacroAssembler::loadPtr): + (JSC::MacroAssembler::storePtr): + (JSC::MacroAssembler::pop): + (JSC::MacroAssembler::push): + (JSC::MacroAssembler::move): + * assembler/X86Assembler.h: + (JSC::X86Assembler::): + (JSC::X86Assembler::movq_rr): + (JSC::X86Assembler::addl_i8m): + (JSC::X86Assembler::addl_i32r): + (JSC::X86Assembler::addq_i8r): + (JSC::X86Assembler::addq_i32r): + (JSC::X86Assembler::movq_mr): + (JSC::X86Assembler::movq_rm): + * wrec/WREC.h: + * wrec/WRECGenerator.cpp: + (JSC::WREC::Generator::generateEnter): + (JSC::WREC::Generator::generateReturnSuccess): + (JSC::WREC::Generator::generateReturnFailure): + * wtf/Platform.h: + * wtf/TCSystemAlloc.cpp: + +2008-12-01 Cameron Zwarich <zwarich@apple.com> + + Reviewed by Sam Weinig. + + Preliminary work for bug 20340: SegmentedVector segment allocations can lead to unsafe use of temporary registers + <https://bugs.webkit.org/show_bug.cgi?id=20340> + + SegmentedVector currently frees segments and reallocates them when used + as a stack. This can lead to unsafe use of pointers into freed segments. + + In order to fix this problem, SegmentedVector will be changed to only + grow and never shrink, with the sole exception of clearing all of its + data, a capability that is required by Lexer. This patch changes the + public interface to only allow for these capabilities. + + * bytecompiler/BytecodeGenerator.cpp: + (JSC::BytecodeGenerator::BytecodeGenerator): Use reserveCapacity() + instead of resize() for m_globals and m_parameters. + * bytecompiler/SegmentedVector.h: + (JSC::SegmentedVector::resize): Removed. + (JSC::SegmentedVector::reserveCapacity): Added. + (JSC::SegmentedVector::clear): Added. + (JSC::SegmentedVector::shrink): Removed. + (JSC::SegmentedVector::grow): Removed. + * parser/Lexer.cpp: + (JSC::Lexer::clear): Use clear() instead of resize(0). + +2008-11-30 Sam Weinig <sam@webkit.org> + + Reviewed by Mark Rowe. + + Renames jumps to m_jumps in JumpList. + + * assembler/MacroAssembler.h: + (JSC::MacroAssembler::JumpList::link): + (JSC::MacroAssembler::JumpList::linkTo): + (JSC::MacroAssembler::JumpList::append): + +2008-11-30 Antti Koivisto <antti@apple.com> + + Reviewed by Mark Rowe. + + https://bugs.webkit.org/show_bug.cgi?id=22557 + + Report free size in central and thread caches too. + + * wtf/FastMalloc.cpp: + (WTF::TCMallocStats::fastMallocStatistics): + * wtf/FastMalloc.h: + +2008-11-29 Antti Koivisto <antti@apple.com> + + Reviewed by Dan Bernstein. + + https://bugs.webkit.org/show_bug.cgi?id=22557 + Add statistics for JavaScript GC heap. + + * JavaScriptCore.exp: + * runtime/Collector.cpp: + (JSC::Heap::objectCount): + (JSC::addToStatistics): + (JSC::Heap::statistics): + * runtime/Collector.h: + +2008-11-29 Antti Koivisto <antti@apple.com> + + Fix debug build by adding a stub method. + + * wtf/FastMalloc.cpp: + (WTF::fastMallocStatistics): + +2008-11-29 Antti Koivisto <antti@apple.com> + + Reviewed by Alexey Proskuryakov. + + https://bugs.webkit.org/show_bug.cgi?id=22557 + + Add function for getting basic statistics from FastMalloc. + + * JavaScriptCore.exp: + * wtf/FastMalloc.cpp: + (WTF::DLL_Length): + (WTF::TCMalloc_PageHeap::ReturnedBytes): + (WTF::TCMallocStats::fastMallocStatistics): + * wtf/FastMalloc.h: + +2008-11-29 Cameron Zwarich <zwarich@apple.com> + + Not reviewed. + + The C++ standard does not automatically grant the friendships of an + enclosing class to its nested subclasses, so we should do so explicitly. + This fixes the GCC 4.0 build, although both GCC 4.2 and Visual C++ 2005 + accept the incorrect code as it is. + + * assembler/MacroAssembler.h: + +2008-11-29 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Cameron Zwarich. + + Add the class MacroAssembler to provide some abstraction of code generation, + and change WREC to make use of this class, rather than directly accessing + the X86Assembler. + + This patch also allows WREC to be compiled without the rest of the JIT enabled. + + * JavaScriptCore.xcodeproj/project.pbxproj: + * assembler/MacroAssembler.h: Added. + (JSC::MacroAssembler::): + (JSC::MacroAssembler::MacroAssembler): + (JSC::MacroAssembler::copyCode): + (JSC::MacroAssembler::Address::Address): + (JSC::MacroAssembler::ImplicitAddress::ImplicitAddress): + (JSC::MacroAssembler::BaseIndex::BaseIndex): + (JSC::MacroAssembler::Label::Label): + (JSC::MacroAssembler::Jump::Jump): + (JSC::MacroAssembler::Jump::link): + (JSC::MacroAssembler::Jump::linkTo): + (JSC::MacroAssembler::JumpList::link): + (JSC::MacroAssembler::JumpList::linkTo): + (JSC::MacroAssembler::JumpList::append): + (JSC::MacroAssembler::Imm32::Imm32): + (JSC::MacroAssembler::add32): + (JSC::MacroAssembler::or32): + (JSC::MacroAssembler::sub32): + (JSC::MacroAssembler::loadPtr): + (JSC::MacroAssembler::load32): + (JSC::MacroAssembler::load16): + (JSC::MacroAssembler::storePtr): + (JSC::MacroAssembler::store32): + (JSC::MacroAssembler::pop): + (JSC::MacroAssembler::push): + (JSC::MacroAssembler::peek): + (JSC::MacroAssembler::poke): + (JSC::MacroAssembler::move): + (JSC::MacroAssembler::compareImm32ForBranch): + (JSC::MacroAssembler::compareImm32ForBranchEquality): + (JSC::MacroAssembler::jae32): + (JSC::MacroAssembler::je32): + (JSC::MacroAssembler::je16): + (JSC::MacroAssembler::jg32): + (JSC::MacroAssembler::jge32): + (JSC::MacroAssembler::jl32): + (JSC::MacroAssembler::jle32): + (JSC::MacroAssembler::jne32): + (JSC::MacroAssembler::jump): + (JSC::MacroAssembler::breakpoint): + (JSC::MacroAssembler::ret): + * assembler/X86Assembler.h: + (JSC::X86Assembler::cmpw_rm): + * interpreter/Interpreter.cpp: + (JSC::Interpreter::Interpreter): + * interpreter/Interpreter.h: + (JSC::Interpreter::assemblerBuffer): + * runtime/RegExp.cpp: + (JSC::RegExp::RegExp): + * wrec/WREC.cpp: + (JSC::WREC::Generator::compileRegExp): + * wrec/WREC.h: + * wrec/WRECFunctors.cpp: + (JSC::WREC::GeneratePatternCharacterFunctor::generateAtom): + (JSC::WREC::GenerateCharacterClassFunctor::generateAtom): + (JSC::WREC::GenerateBackreferenceFunctor::generateAtom): + (JSC::WREC::GenerateParenthesesNonGreedyFunctor::generateAtom): + * wrec/WRECFunctors.h: + (JSC::WREC::GenerateParenthesesNonGreedyFunctor::GenerateParenthesesNonGreedyFunctor): + * wrec/WRECGenerator.cpp: + (JSC::WREC::Generator::generateEnter): + (JSC::WREC::Generator::generateReturnSuccess): + (JSC::WREC::Generator::generateSaveIndex): + (JSC::WREC::Generator::generateIncrementIndex): + (JSC::WREC::Generator::generateLoadCharacter): + (JSC::WREC::Generator::generateJumpIfEndOfInput): + (JSC::WREC::Generator::generateJumpIfNotEndOfInput): + (JSC::WREC::Generator::generateReturnFailure): + (JSC::WREC::Generator::generateBacktrack1): + (JSC::WREC::Generator::generateBacktrackBackreference): + (JSC::WREC::Generator::generateBackreferenceQuantifier): + (JSC::WREC::Generator::generateNonGreedyQuantifier): + (JSC::WREC::Generator::generateGreedyQuantifier): + (JSC::WREC::Generator::generatePatternCharacter): + (JSC::WREC::Generator::generateCharacterClassInvertedRange): + (JSC::WREC::Generator::generateCharacterClassInverted): + (JSC::WREC::Generator::generateCharacterClass): + (JSC::WREC::Generator::generateParentheses): + (JSC::WREC::Generator::generateParenthesesNonGreedy): + (JSC::WREC::Generator::generateParenthesesResetTrampoline): + (JSC::WREC::Generator::generateAssertionBOL): + (JSC::WREC::Generator::generateAssertionEOL): + (JSC::WREC::Generator::generateAssertionWordBoundary): + (JSC::WREC::Generator::generateBackreference): + (JSC::WREC::Generator::terminateAlternative): + (JSC::WREC::Generator::terminateDisjunction): + * wrec/WRECGenerator.h: + (JSC::WREC::Generator::Generator): + * wrec/WRECParser.cpp: + (JSC::WREC::Parser::parsePatternCharacterQualifier): + (JSC::WREC::Parser::parseCharacterClassQuantifier): + (JSC::WREC::Parser::parseBackreferenceQuantifier): + (JSC::WREC::Parser::parseParentheses): + (JSC::WREC::Parser::parseCharacterClass): + (JSC::WREC::Parser::parseOctalEscape): + (JSC::WREC::Parser::parseEscape): + (JSC::WREC::Parser::parseTerm): + (JSC::WREC::Parser::parseDisjunction): + * wrec/WRECParser.h: + (JSC::WREC::Parser::Parser): + (JSC::WREC::Parser::parsePattern): + (JSC::WREC::Parser::parseAlternative): + * wtf/Platform.h: + +2008-11-28 Simon Hausmann <hausmann@webkit.org> + + Reviewed by Tor Arne Vestbø. + + Fix compilation on Windows CE + + Port away from the use of errno after calling strtol(), instead + detect conversion errors by checking the result and the stop + position. + + * runtime/DateMath.cpp: + (JSC::parseLong): + (JSC::parseDate): + +2008-11-28 Joerg Bornemann <joerg.bornemann@trolltech.com> + + Reviewed by Simon Hausmann. + + Implement lowResUTCTime() on Windows CE using GetSystemTime as _ftime() is not available. + + * runtime/DateMath.cpp: + (JSC::lowResUTCTime): + +2008-11-28 Simon Hausmann <hausmann@webkit.org> + + Rubber-stamped by Tor Arne Vestbø. + + Removed unnecessary inclusion of errno.h, which also fixes compilation on Windows CE. + + * runtime/JSGlobalObjectFunctions.cpp: + +2008-11-27 Cameron Zwarich <zwarich@apple.com> + + Not reviewed. + + r38825 made JSFunction::m_body private, but some inspector code in + WebCore sets the field. Add setters for it. + + * runtime/JSFunction.h: + (JSC::JSFunction::setBody): + +2008-11-27 Sam Weinig <sam@webkit.org> + + Reviewed by Cameron Zwarich. + + Fix FIXME by adding accessor for JSFunction's m_body property. + + * interpreter/Interpreter.cpp: + (JSC::Interpreter::cti_op_call_JSFunction): + (JSC::Interpreter::cti_vm_dontLazyLinkCall): + (JSC::Interpreter::cti_vm_lazyLinkCall): + * profiler/Profiler.cpp: + (JSC::createCallIdentifierFromFunctionImp): + * runtime/Arguments.h: + (JSC::Arguments::getArgumentsData): + (JSC::Arguments::Arguments): + * runtime/FunctionPrototype.cpp: + (JSC::functionProtoFuncToString): + * runtime/JSFunction.h: + (JSC::JSFunction::JSFunction): + (JSC::JSFunction::body): + +2008-11-27 Sam Weinig <sam@webkit.org> + + Reviewed by Oliver Hunt. + + Remove unused member variables from ProgramNode. + + * parser/Nodes.h: + +2008-11-27 Brent Fulgham <bfulgham@gmail.com> + + Reviewed by Alexey Proskuryakov. + + Enable mouse panning feaure on Windows Cairo build. + See http://bugs.webkit.org/show_bug.cgi?id=22525 + + * wtf/Platform.h: Enable mouse panning feaure on Windows Cairo build. + +2008-11-27 Alp Toker <alp@nuanti.com> + + Change recently introduced C++ comments in Platform.h to C comments to + fix the minidom build with traditional C. + + Build GtkLauncher and minidom with the '-ansi' compiler flag to detect + API header breakage at build time. + + * GNUmakefile.am: + * wtf/Platform.h: + +2008-11-27 Alp Toker <alp@nuanti.com> + + Remove C++ comment from JavaScriptCore API headers (introduced r35449). + Fixes build for ANSI C applications using the public API. + + * API/WebKitAvailability.h: + +2008-11-26 Eric Seidel <eric@webkit.org> + + No review, build fix only. + + Fix the JSC Chromium Mac build by adding JavaScriptCore/icu into the include path + + * JavaScriptCore.scons: + +2008-11-25 Cameron Zwarich <zwarich@apple.com> + + Reviewed by Maciej Stachowiak. + + Remove the unused member function JSFunction::getParameterName(). + + * runtime/JSFunction.cpp: + * runtime/JSFunction.h: + +2008-11-24 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Geoff Garen. + + Polymorpic caching for get by id chain. Similar to the polymorphic caching already implemented + for self and proto accesses (implemented by allowing multiple trampolines to be JIT genertaed, + and linked together) - the get by id chain caching is implemented as a genericization of the + proto list caching, allowing cached access lists to contain a mix of proto and proto chain + accesses (since in JS style inheritance hierarchies you may commonly see a mix of properties + being overridden on the direct prototype, or higher up its prototype chain). + + In order to allow this patch to compile there is a fix to appease gcc 4.2 compiler issues + (removing the jumps between fall-through cases in privateExecute). + + This patch also removes redundant immediate checking from the reptach code, and fixes a related + memory leak (failure to deallocate trampolines). + + ~2% progression on v8 tests (bulk on the win on deltablue) + + * bytecode/Instruction.h: + (JSC::PolymorphicAccessStructureList::PolymorphicStubInfo::): + (JSC::PolymorphicAccessStructureList::PolymorphicStubInfo::set): + (JSC::PolymorphicAccessStructureList::PolymorphicAccessStructureList): + (JSC::PolymorphicAccessStructureList::derefStructures): + * interpreter/Interpreter.cpp: + (JSC::countPrototypeChainEntriesAndCheckForProxies): + (JSC::Interpreter::tryCacheGetByID): + (JSC::Interpreter::privateExecute): + (JSC::Interpreter::tryCTICacheGetByID): + (JSC::Interpreter::cti_op_get_by_id_self_fail): + (JSC::getPolymorphicAccessStructureListSlot): + (JSC::Interpreter::cti_op_get_by_id_proto_list): + * interpreter/Interpreter.h: + * jit/JIT.cpp: + (JSC::JIT::privateCompileGetByIdProto): + (JSC::JIT::privateCompileGetByIdSelfList): + (JSC::JIT::privateCompileGetByIdProtoList): + (JSC::JIT::privateCompileGetByIdChainList): + (JSC::JIT::privateCompileGetByIdChain): + (JSC::JIT::privateCompilePatchGetArrayLength): + * jit/JIT.h: + (JSC::JIT::compileGetByIdChainList): + +2008-11-25 Cameron Zwarich <zwarich@apple.com> + + Reviewed by Alexey Proskuryakov. + + Move the collect() call in Heap::heapAllocate() that is conditionally + compiled under COLLECT_ON_EVERY_ALLOCATION so that it is before we get + information about the heap. This was causing assertion failures for me + while I was reducing a bug. + + * runtime/Collector.cpp: + (JSC::Heap::heapAllocate): + +2008-11-24 Cameron Zwarich <zwarich@apple.com> + + Reviewed by Geoff Garen. + + Bug 13790: Function declarations are not treated as statements (used to affect starcraft2.com) + <https://bugs.webkit.org/show_bug.cgi?id=13790> + + Modify the parser to treat function declarations as statements, + simplifying the grammar in the process. Technically, according to the + grammar in the ECMA spec, function declarations are not statements and + can not be used everywhere that statements can, but it is not worth the + possibility compatibility issues just to stick to the spec in this case. + + * parser/Grammar.y: + * parser/Nodes.cpp: + (JSC::FuncDeclNode::emitBytecode): Avoid returning ignoredResult() + as a result, because it causes a crash in DoWhileNode::emitBytecode(). + +2008-11-24 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Sam Weinig. + + Unroll the regexp matching loop by 1. 10% speedup on simple matching + stress test. No change on SunSpider. + + (I decided not to unroll to arbitrary levels because the returns diminsh + quickly.) + + * wrec/WREC.cpp: + (JSC::WREC::compileRegExp): + * wrec/WRECGenerator.cpp: + (JSC::WREC::Generator::generateJumpIfEndOfInput): + (JSC::WREC::Generator::generateJumpIfNotEndOfInput): + * wrec/WRECGenerator.h: + * wrec/WRECParser.h: + (JSC::WREC::Parser::error): + (JSC::WREC::Parser::parsePattern): + +2008-11-24 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Sam Weinig. + + Removed some unnecessary "Generator::" prefixes. + + * wrec/WRECGenerator.cpp: + (JSC::WREC::Generator::generateEnter): + (JSC::WREC::Generator::generateReturnSuccess): + (JSC::WREC::Generator::generateSaveIndex): + (JSC::WREC::Generator::generateIncrementIndex): + (JSC::WREC::Generator::generateLoopIfNotEndOfInput): + (JSC::WREC::Generator::generateReturnFailure): + +2008-11-24 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Sam Weinig. + + Made a bunch of WREC::Parser functions private, and added an explicit + "reset()" function, so a parser can be reused. + + * wrec/WRECParser.h: + (JSC::WREC::Parser::Parser): + (JSC::WREC::Parser::generator): + (JSC::WREC::Parser::ignoreCase): + (JSC::WREC::Parser::multiline): + (JSC::WREC::Parser::recordSubpattern): + (JSC::WREC::Parser::numSubpatterns): + (JSC::WREC::Parser::parsePattern): + (JSC::WREC::Parser::parseAlternative): + (JSC::WREC::Parser::reset): + +2008-11-24 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Cameron Zwarich. + + Implement repatching for get by id chain. + Previously the access is performed in a function stub, in the repatch form + the trampoline is not called to; instead the hot path is relinked to jump + directly to the trampoline, if it fails it will jump to the slow case. + + https://bugs.webkit.org/show_bug.cgi?id=22449 + 3% progression on deltablue. + + * jit/JIT.cpp: + (JSC::JIT::privateCompileGetByIdProto): + (JSC::JIT::privateCompileGetByIdChain): + +2008-11-24 Joerg Bornemann <joerg.bornemann@trolltech.com> + + Reviewed by Simon Hausmann. + + https://bugs.webkit.org/show_bug.cgi?id=20746 + + Various small compilation fixes to make the Qt port of WebKit + compile on Windows CE. + + * config.h: Don't set _CRT_RAND_S for CE, it's not available. + * jsc.cpp: Disabled use of debugger includes for CE. It + does not have the debugging functions. + * runtime/DateMath.cpp: Use localtime() on Windows CE. + * wtf/Assertions.cpp: Compile on Windows CE without debugger. + * wtf/Assertions.h: Include windows.h before defining ASSERT. + * wtf/MathExtras.h: Include stdlib.h instead of xmath.h. + * wtf/Platform.h: Disable ERRNO_H and detect endianess based + on the Qt endianess. On Qt for Windows CE the endianess is + defined by the vendor specific build spec. + * wtf/Threading.h: Use the volatile-less atomic functions. + * wtf/dtoa.cpp: Compile without errno. + * wtf/win/MainThreadWin.cpp: Don't include windows.h on CE after + Assertions.h due to the redefinition of ASSERT. + +2008-11-22 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Cameron Zwarich. + + Replace accidentally deleted immediate check from get by id chain trampoline. + https://bugs.webkit.org/show_bug.cgi?id=22413 + + * jit/JIT.cpp: + (JSC::JIT::privateCompileGetByIdChain): + +2008-11-21 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Oliver Hunt. + + Add (really) polymorphic caching for get by id self. + Very similar to caching of prototype accesses, described below. + + Oh, also, probably shouldn't have been leaking those structure list objects. + + 4% preogression on deltablue. + + * bytecode/CodeBlock.cpp: + (JSC::CodeBlock::dump): + (JSC::CodeBlock::derefStructures): + (JSC::PrototypeStructureList::derefStructures): + * bytecode/Instruction.h: + * bytecode/Opcode.h: + * interpreter/Interpreter.cpp: + (JSC::Interpreter::privateExecute): + (JSC::Interpreter::cti_op_get_by_id_self_fail): + * jit/JIT.cpp: + (JSC::JIT::privateCompileMainPass): + (JSC::JIT::privateCompileGetByIdSelfList): + (JSC::JIT::patchGetByIdSelf): + * jit/JIT.h: + (JSC::JIT::compileGetByIdSelfList): + +2008-11-21 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Sam Weinig. + + Fixed many crashes seen 'round the world (but only in release builds). + + Update outputParameter offset to reflect slight re-ordering of push + instructions in r38669. + + * wrec/WRECGenerator.cpp: + +2008-11-21 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Sam Weinig. + + A little more RegExp refactoring. + + Deployed a helper function for reading the next character. Used the "link + vector of jumps" helper in a place I missed before. + + * wrec/WRECGenerator.cpp: + (JSC::WREC::Generator::generateLoadCharacter): + (JSC::WREC::Generator::generatePatternCharacter): + (JSC::WREC::Generator::generateCharacterClass): + (JSC::WREC::Generator::generateAssertionEOL): + (JSC::WREC::Generator::generateAssertionWordBoundary): + * wrec/WRECGenerator.h: + +2008-11-21 Alexey Proskuryakov <ap@webkit.org> + + Reviewed by Dan Bernstein. + + https://bugs.webkit.org/show_bug.cgi?id=22402 + Replace abort() with CRASH() + + * wtf/Assertions.h: Added a different method to crash, which should work even is 0xbbadbeef + is a valid memory address. + + * runtime/Collector.cpp: + * wtf/FastMalloc.cpp: + * wtf/FastMalloc.h: + * wtf/TCSpinLock.h: + Replace abort() with CRASH(). + +2008-11-21 Alexey Proskuryakov <ap@webkit.org> + + Reverted fix for bug 22042 (Replace abort() with CRASH()), because it was breaking + FOR_EACH_OPCODE_ID macro somehow, making Safari crash. + + * runtime/Collector.cpp: + (JSC::Heap::heapAllocate): + (JSC::Heap::collect): + * wtf/Assertions.h: + * wtf/FastMalloc.cpp: + (WTF::fastMalloc): + (WTF::fastCalloc): + (WTF::fastRealloc): + (WTF::InitSizeClasses): + (WTF::PageHeapAllocator::New): + (WTF::TCMallocStats::do_malloc): + * wtf/FastMalloc.h: + * wtf/TCSpinLock.h: + (TCMalloc_SpinLock::Init): + (TCMalloc_SpinLock::Finalize): + (TCMalloc_SpinLock::Lock): + (TCMalloc_SpinLock::Unlock): + +2008-11-21 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Sam Weinig. + + A little more RegExp refactoring. + + Moved all assembly from WREC.cpp into WRECGenerator helper functions. + This should help with portability and readability. + + Removed ASSERTs after calls to executableCopy(), and changed + executableCopy() to ASSERT instead. + + * assembler/X86Assembler.h: + (JSC::X86Assembler::executableCopy): + * jit/JIT.cpp: + (JSC::JIT::privateCompile): + (JSC::JIT::privateCompileGetByIdSelf): + (JSC::JIT::privateCompileGetByIdProto): + (JSC::JIT::privateCompileGetByIdChain): + (JSC::JIT::privateCompilePutByIdReplace): + (JSC::JIT::privateCompilePutByIdTransition): + (JSC::JIT::privateCompileCTIMachineTrampolines): + (JSC::JIT::privateCompilePatchGetArrayLength): + * wrec/WREC.cpp: + (JSC::WREC::compileRegExp): + * wrec/WRECGenerator.cpp: + (JSC::WREC::Generator::generateEnter): + (JSC::WREC::Generator::generateReturnSuccess): + (JSC::WREC::Generator::generateSaveIndex): + (JSC::WREC::Generator::generateIncrementIndex): + (JSC::WREC::Generator::generateLoopIfNotEndOfInput): + (JSC::WREC::Generator::generateReturnFailure): + * wrec/WRECGenerator.h: + * wrec/WRECParser.h: + (JSC::WREC::Parser::ignoreCase): + (JSC::WREC::Parser::generator): + +2008-11-21 Alexey Proskuryakov <ap@webkit.org> + + Build fix. + + * wtf/Assertions.h: Use ::abort for C++ code. + +2008-11-21 Alexey Proskuryakov <ap@webkit.org> + + Reviewed by Sam Weinig. + + https://bugs.webkit.org/show_bug.cgi?id=22402 + Replace abort() with CRASH() + + * wtf/Assertions.h: Added abort() after an attempt to crash for extra safety. + + * runtime/Collector.cpp: + * wtf/FastMalloc.cpp: + * wtf/FastMalloc.h: + * wtf/TCSpinLock.h: + Replace abort() with CRASH(). + +2008-11-21 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Sam Weinig. + + Renamed wrec => generator. + + * wrec/WRECFunctors.cpp: + (JSC::WREC::GeneratePatternCharacterFunctor::generateAtom): + (JSC::WREC::GeneratePatternCharacterFunctor::backtrack): + (JSC::WREC::GenerateCharacterClassFunctor::generateAtom): + (JSC::WREC::GenerateCharacterClassFunctor::backtrack): + (JSC::WREC::GenerateBackreferenceFunctor::generateAtom): + (JSC::WREC::GenerateBackreferenceFunctor::backtrack): + (JSC::WREC::GenerateParenthesesNonGreedyFunctor::generateAtom): + +2008-11-19 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Darin Adler. + + Add support for (really) polymorphic caching of prototype accesses. + + If a cached prototype access misses, cti_op_get_by_id_proto_list is called. + When this occurs the Structure pointers from the instruction stream are copied + off into a new ProtoStubInfo object. A second prototype access trampoline is + generated, and chained onto the first. Subsequent missed call to + cti_op_get_by_id_proto_list_append, which append futher new trampolines, up to + PROTOTYPE_LIST_CACHE_SIZE (currently 4). If any of the misses result in an + access other than to a direct prototype property, list formation is halted (or + for the initial miss, does not take place at all). + + Separate fail case functions are provided for each access since this contributes + to the performance progression (enables better processor branch prediction). + + Overall this is a near 5% progression on v8, with around 10% wins on richards + and deltablue. + + * bytecode/CodeBlock.cpp: + (JSC::CodeBlock::dump): + (JSC::CodeBlock::derefStructures): + * bytecode/Instruction.h: + (JSC::ProtoStructureList::ProtoStubInfo::set): + (JSC::ProtoStructureList::ProtoStructureList): + (JSC::Instruction::Instruction): + (JSC::Instruction::): + * bytecode/Opcode.h: + * interpreter/Interpreter.cpp: + (JSC::Interpreter::privateExecute): + (JSC::Interpreter::tryCTICacheGetByID): + (JSC::Interpreter::cti_op_put_by_id_fail): + (JSC::Interpreter::cti_op_get_by_id_self_fail): + (JSC::Interpreter::cti_op_get_by_id_proto_list): + (JSC::Interpreter::cti_op_get_by_id_proto_list_append): + (JSC::Interpreter::cti_op_get_by_id_proto_list_full): + (JSC::Interpreter::cti_op_get_by_id_proto_fail): + (JSC::Interpreter::cti_op_get_by_id_chain_fail): + (JSC::Interpreter::cti_op_get_by_id_array_fail): + (JSC::Interpreter::cti_op_get_by_id_string_fail): + * interpreter/Interpreter.h: + * jit/JIT.cpp: + (JSC::JIT::privateCompileMainPass): + (JSC::JIT::privateCompileGetByIdSelf): + (JSC::JIT::privateCompileGetByIdProto): + (JSC::JIT::privateCompileGetByIdProtoList): + (JSC::JIT::privateCompileGetByIdChain): + (JSC::JIT::privateCompileCTIMachineTrampolines): + (JSC::JIT::privateCompilePatchGetArrayLength): + * jit/JIT.h: + (JSC::JIT::compileGetByIdProtoList): + +2008-11-20 Sam Weinig <sam@webkit.org> + + Try and fix the tiger build. + + * parser/Grammar.y: + +2008-11-20 Eric Seidel <eric@webkit.org> + + Reviewed by Darin Adler. + + Make JavaScriptCore Chromium build under Windows (cmd only, cygwin almost works) + https://bugs.webkit.org/show_bug.cgi?id=22347 + + * JavaScriptCore.scons: + * parser/Parser.cpp: Add using std::auto_ptr since we use auto_ptr + +2008-11-20 Steve Falkenburg <sfalken@apple.com> + + Fix build. + + Reviewed by Sam Weinig. + + * parser/Parser.cpp: + (JSC::Parser::reparse): + +2008-11-20 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Sam Weinig. + + A little more RegExp refactoring. + + Created a helper function in the assembler for linking a vector of + JmpSrc to a location, and deployed it in a bunch of places. + + * JavaScriptCore.xcodeproj/project.pbxproj: + * assembler/X86Assembler.h: + (JSC::X86Assembler::link): + * wrec/WREC.cpp: + (JSC::WREC::compileRegExp): + * wrec/WRECGenerator.cpp: + (JSC::WREC::Generator::generateNonGreedyQuantifier): + (JSC::WREC::Generator::generateGreedyQuantifier): + (JSC::WREC::Generator::generateCharacterClassInverted): + (JSC::WREC::Generator::generateParentheses): + (JSC::WREC::Generator::generateParenthesesResetTrampoline): + (JSC::WREC::Generator::generateAssertionBOL): + (JSC::WREC::Generator::generateAssertionEOL): + (JSC::WREC::Generator::generateAssertionWordBoundary): + (JSC::WREC::Generator::terminateAlternative): + (JSC::WREC::Generator::terminateDisjunction): + * wrec/WRECParser.cpp: + * wrec/WRECParser.h: + (JSC::WREC::Parser::consumeHex): + +2008-11-20 Sam Weinig <sam@webkit.org> + + Fix non-mac builds. + + * parser/Lexer.cpp: + * parser/Parser.cpp: + +2008-11-20 Sam Weinig <sam@webkit.org> + + Reviewed by Darin Adler. + + Patch for https://bugs.webkit.org/show_bug.cgi?id=22385 + <rdar://problem/6390179> + Lazily reparse FunctionBodyNodes on first execution. + + - Saves 57MB on Membuster head. + + * bytecompiler/BytecodeGenerator.cpp: + (JSC::BytecodeGenerator::generate): Remove vector shrinking since this is now + handled by destroying the ScopeNodeData after generation. + + * parser/Grammar.y: Add alternate NoNode version of the grammar + that does not create nodes. This is used to lazily create FunctionBodyNodes + on first execution. + + * parser/Lexer.cpp: + (JSC::Lexer::setCode): Fix bug where on reparse, the Lexer was confused about + what position and length meant. Position is the current position in the original + data buffer (important for getting correct line/column information) and length + the end offset in the original buffer. + * parser/Lexer.h: + (JSC::Lexer::sourceCode): Positions are relative to the beginning of the buffer. + + * parser/Nodes.cpp: + (JSC::ScopeNodeData::ScopeNodeData): Move initialization of ScopeNode data here. + (JSC::ScopeNode::ScopeNode): Add constructor that only sets the JSGlobalData + for FunctionBodyNode stubs. + (JSC::ScopeNode::~ScopeNode): Release m_children now that we don't inherit from + BlockNode. + (JSC::ScopeNode::releaseNodes): Ditto. + (JSC::EvalNode::generateBytecode): Only shrink m_children, as we need to keep around + the rest of the data. + (JSC::FunctionBodyNode::FunctionBodyNode): Add constructor that only sets the + JSGlobalData. + (JSC::FunctionBodyNode::create): Ditto. + (JSC::FunctionBodyNode::generateBytecode): If we don't have the data, do a reparse + to construct it. Then after generation, destroy the data. + (JSC::ProgramNode::generateBytecode): After generation, destroy the AST data. + * parser/Nodes.h: + (JSC::ExpressionNode::): Add isFuncExprNode for FunctionConstructor. + (JSC::StatementNode::): Add isExprStatementNode for FunctionConstructor. + (JSC::ExprStatementNode::): Ditto. + (JSC::ExprStatementNode::expr): Add accessor for FunctionConstructor. + (JSC::FuncExprNode::): Add isFuncExprNode for FunctionConstructor + + (JSC::ScopeNode::adoptData): Adopts a ScopeNodeData. + (JSC::ScopeNode::data): Accessor for ScopeNodeData. + (JSC::ScopeNode::destroyData): Deletes the ScopeNodeData. + (JSC::ScopeNode::setFeatures): Added. + (JSC::ScopeNode::varStack): Added assert. + (JSC::ScopeNode::functionStack): Ditto. + (JSC::ScopeNode::children): Ditto. + (JSC::ScopeNode::neededConstants): Ditto. + Factor m_varStack, m_functionStack, m_children and m_numConstants into ScopeNodeData. + + * parser/Parser.cpp: + (JSC::Parser::reparse): Reparse the SourceCode in the FunctionBodyNode and set + set up the ScopeNodeData for it. + * parser/Parser.h: + + * parser/SourceCode.h: + (JSC::SourceCode::endOffset): Added for use in the lexer. + + * runtime/FunctionConstructor.cpp: + (JSC::getFunctionBody): Assuming a ProgramNode with one FunctionExpression in it, + get the FunctionBodyNode. Any issues signifies a parse failure in constructFunction. + (JSC::constructFunction): Make parsing functions in the form new Function(""), easier + by concatenating the strings together (with some glue) and parsing the function expression + as a ProgramNode from which we can receive the FunctionBodyNode. This has the added benefit + of not having special parsing code for the arguments and lazily constructing the + FunctionBodyNode's AST on first execution. + + * runtime/Identifier.h: + (JSC::operator!=): Added. + +2008-11-20 Sam Weinig <sam@webkit.org> + + Reviewed by Geoffrey Garen. + + Speedup the lexer to offset coming re-parsing patch. + + - .6% progression on Sunspider. + + * bytecompiler/SegmentedVector.h: + (JSC::SegmentedVector::shrink): Fixed bug where m_size would not be + set when shrinking to 0. + + * parser/Lexer.cpp: + (JSC::Lexer::Lexer): + (JSC::Lexer::isIdentStart): Use isASCIIAlpha and isASCII to avoid going into ICU in the common cases. + (JSC::Lexer::isIdentPart): Use isASCIIAlphanumeric and isASCII to avoid going into ICU in the common cases + (JSC::isDecimalDigit): Use version in ASCIICType.h. Inlining it was a regression. + (JSC::Lexer::isHexDigit): Ditto. + (JSC::Lexer::isOctalDigit): Ditto. + (JSC::Lexer::clear): Resize the m_identifiers SegmentedVector to initial + capacity + * parser/Lexer.h: Remove unused m_strings vector. Make m_identifiers + a SegmentedVector<Identifier> to avoid allocating a new Identifier* for + each identifier found. The SegmentedVector is need so we can passes + references to the Identifier to the parser, which remain valid even when + the vector is resized. + (JSC::Lexer::makeIdentifier): Inline and return a reference to the added + Identifier. + +2008-11-20 Sam Weinig <sam@webkit.org> + + Reviewed by Darin Adler. + + Add isASCII to ASCIICType. Use coming soon! + + * wtf/ASCIICType.h: + (WTF::isASCII): + +2008-11-20 Sam Weinig <sam@webkit.org> + + Reviewed by Darin Adler. + + Add OwnPtr constructor and OwnPtr::adopt that take an auto_ptr. + + * wtf/OwnPtr.h: + (WTF::OwnPtr::OwnPtr): + (WTF::OwnPtr::adopt): + +2008-11-20 Alexey Proskuryakov <ap@webkit.org> + + Reviewed by Darin Adler. + + https://bugs.webkit.org/show_bug.cgi?id=22364 + Crashes seen on Tiger buildbots due to worker threads exhausting pthread keys + + * runtime/Collector.cpp: + (JSC::Heap::Heap): + (JSC::Heap::destroy): + (JSC::Heap::makeUsableFromMultipleThreads): + (JSC::Heap::registerThread): + * runtime/Collector.h: + Pthread key for tracking threads is only created on request now, because this is a limited + resource, and thread tracking is not needed for worker heaps, or for WebCore heap. + + * API/JSContextRef.cpp: (JSGlobalContextCreateInGroup): Call makeUsableFromMultipleThreads(). + + * runtime/JSGlobalData.cpp: (JSC::JSGlobalData::sharedInstance): Ditto. + + * runtime/JSGlobalData.h: (JSC::JSGlobalData::makeUsableFromMultipleThreads): Just forward + the call to Heap, which clients need not know about, ideally. + +2008-11-20 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Sam Weinig. + + A little more WREC refactoring. + + Removed the "Register" suffix from register names in WREC, and renamed: + currentPosition => index + currentValue => character + quantifierCount => repeatCount + + Added a top-level parsePattern function to the WREC parser, which + allowed me to remove the error() and atEndOfPattern() accessors. + + Factored out an MSVC customization into a constant. + + Renamed nextLabel => beginPattern. + + * wrec/WREC.cpp: + (JSC::WREC::compileRegExp): + * wrec/WRECGenerator.cpp: + (JSC::WREC::Generator::generateBacktrack1): + (JSC::WREC::Generator::generateBacktrackBackreference): + (JSC::WREC::Generator::generateBackreferenceQuantifier): + (JSC::WREC::Generator::generateNonGreedyQuantifier): + (JSC::WREC::Generator::generateGreedyQuantifier): + (JSC::WREC::Generator::generatePatternCharacter): + (JSC::WREC::Generator::generateCharacterClassInvertedRange): + (JSC::WREC::Generator::generateCharacterClassInverted): + (JSC::WREC::Generator::generateCharacterClass): + (JSC::WREC::Generator::generateParentheses): + (JSC::WREC::Generator::generateParenthesesResetTrampoline): + (JSC::WREC::Generator::generateAssertionBOL): + (JSC::WREC::Generator::generateAssertionEOL): + (JSC::WREC::Generator::generateAssertionWordBoundary): + (JSC::WREC::Generator::generateBackreference): + (JSC::WREC::Generator::generateDisjunction): + (JSC::WREC::Generator::terminateDisjunction): + * wrec/WRECGenerator.h: + * wrec/WRECParser.h: + (JSC::WREC::Parser::parsePattern): + +2008-11-19 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Darin Adler. + + https://bugs.webkit.org/show_bug.cgi?id=22361 + A little more RegExp refactoring. + + Consistently named variables holding the starting position at which + regexp matching should begin to "startOffset". + + A few more "regExpObject" => "regExpConstructor" changes. + + Refactored RegExpObject::match for clarity, and replaced a slow "get" + of the "global" property with a fast access to the global bit. + + Made the error message you see when RegExpObject::match has no input a + little more informative, as in Firefox. + + * runtime/RegExp.cpp: + (JSC::RegExp::match): + * runtime/RegExp.h: + * runtime/RegExpObject.cpp: + (JSC::RegExpObject::match): + * runtime/StringPrototype.cpp: + (JSC::stringProtoFuncReplace): + (JSC::stringProtoFuncMatch): + (JSC::stringProtoFuncSearch): + +2008-11-19 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Sam Weinig. + + A little more refactoring. + + Removed the "emit" and "emitUnlinked" prefixes from the assembler. + + Moved the JmpSrc and JmpDst class definitions to the top of the X86 + assembler class, in accordance with WebKit style guidelines. + + * assembler/X86Assembler.h: + (JSC::X86Assembler::JmpSrc::JmpSrc): + (JSC::X86Assembler::JmpDst::JmpDst): + (JSC::X86Assembler::int3): + (JSC::X86Assembler::pushl_m): + (JSC::X86Assembler::popl_m): + (JSC::X86Assembler::movl_rr): + (JSC::X86Assembler::addl_rr): + (JSC::X86Assembler::addl_i8r): + (JSC::X86Assembler::addl_i8m): + (JSC::X86Assembler::addl_i32r): + (JSC::X86Assembler::addl_mr): + (JSC::X86Assembler::andl_rr): + (JSC::X86Assembler::andl_i32r): + (JSC::X86Assembler::cmpl_i8r): + (JSC::X86Assembler::cmpl_rr): + (JSC::X86Assembler::cmpl_rm): + (JSC::X86Assembler::cmpl_mr): + (JSC::X86Assembler::cmpl_i32r): + (JSC::X86Assembler::cmpl_i32m): + (JSC::X86Assembler::cmpl_i8m): + (JSC::X86Assembler::cmpw_rm): + (JSC::X86Assembler::orl_rr): + (JSC::X86Assembler::orl_mr): + (JSC::X86Assembler::orl_i32r): + (JSC::X86Assembler::subl_rr): + (JSC::X86Assembler::subl_i8r): + (JSC::X86Assembler::subl_i8m): + (JSC::X86Assembler::subl_i32r): + (JSC::X86Assembler::subl_mr): + (JSC::X86Assembler::testl_i32r): + (JSC::X86Assembler::testl_i32m): + (JSC::X86Assembler::testl_rr): + (JSC::X86Assembler::xorl_i8r): + (JSC::X86Assembler::xorl_rr): + (JSC::X86Assembler::sarl_i8r): + (JSC::X86Assembler::sarl_CLr): + (JSC::X86Assembler::shl_i8r): + (JSC::X86Assembler::shll_CLr): + (JSC::X86Assembler::imull_rr): + (JSC::X86Assembler::imull_i32r): + (JSC::X86Assembler::idivl_r): + (JSC::X86Assembler::negl_r): + (JSC::X86Assembler::movl_mr): + (JSC::X86Assembler::movzbl_rr): + (JSC::X86Assembler::movzwl_mr): + (JSC::X86Assembler::movl_rm): + (JSC::X86Assembler::movl_i32r): + (JSC::X86Assembler::movl_i32m): + (JSC::X86Assembler::leal_mr): + (JSC::X86Assembler::jmp_r): + (JSC::X86Assembler::jmp_m): + (JSC::X86Assembler::movsd_mr): + (JSC::X86Assembler::xorpd_mr): + (JSC::X86Assembler::movsd_rm): + (JSC::X86Assembler::movd_rr): + (JSC::X86Assembler::cvtsi2sd_rr): + (JSC::X86Assembler::cvttsd2si_rr): + (JSC::X86Assembler::addsd_mr): + (JSC::X86Assembler::subsd_mr): + (JSC::X86Assembler::mulsd_mr): + (JSC::X86Assembler::addsd_rr): + (JSC::X86Assembler::subsd_rr): + (JSC::X86Assembler::mulsd_rr): + (JSC::X86Assembler::ucomis_rr): + (JSC::X86Assembler::pextrw_irr): + (JSC::X86Assembler::call): + (JSC::X86Assembler::jmp): + (JSC::X86Assembler::jne): + (JSC::X86Assembler::jnz): + (JSC::X86Assembler::je): + (JSC::X86Assembler::jl): + (JSC::X86Assembler::jb): + (JSC::X86Assembler::jle): + (JSC::X86Assembler::jbe): + (JSC::X86Assembler::jge): + (JSC::X86Assembler::jg): + (JSC::X86Assembler::ja): + (JSC::X86Assembler::jae): + (JSC::X86Assembler::jo): + (JSC::X86Assembler::jp): + (JSC::X86Assembler::js): + (JSC::X86Assembler::predictNotTaken): + (JSC::X86Assembler::convertToFastCall): + (JSC::X86Assembler::restoreArgumentReference): + (JSC::X86Assembler::restoreArgumentReferenceForTrampoline): + (JSC::X86Assembler::modRm_rr): + (JSC::X86Assembler::modRm_rr_Unchecked): + (JSC::X86Assembler::modRm_rm): + (JSC::X86Assembler::modRm_rm_Unchecked): + (JSC::X86Assembler::modRm_rmsib): + (JSC::X86Assembler::modRm_opr): + (JSC::X86Assembler::modRm_opr_Unchecked): + (JSC::X86Assembler::modRm_opm): + (JSC::X86Assembler::modRm_opm_Unchecked): + (JSC::X86Assembler::modRm_opmsib): + * jit/JIT.cpp: + (JSC::JIT::emitNakedCall): + (JSC::JIT::emitNakedFastCall): + (JSC::JIT::emitCTICall): + (JSC::JIT::emitJumpSlowCaseIfNotJSCell): + (JSC::JIT::emitJumpSlowCaseIfNotImmNum): + (JSC::JIT::emitFastArithDeTagImmediateJumpIfZero): + (JSC::JIT::emitFastArithIntToImmOrSlowCase): + (JSC::JIT::emitArithIntToImmWithJump): + (JSC::JIT::compileOpCall): + (JSC::JIT::compileOpStrictEq): + (JSC::JIT::emitSlowScriptCheck): + (JSC::JIT::putDoubleResultToJSNumberCellOrJSImmediate): + (JSC::JIT::compileBinaryArithOp): + (JSC::JIT::privateCompileMainPass): + (JSC::JIT::privateCompileSlowCases): + (JSC::JIT::privateCompile): + (JSC::JIT::privateCompileGetByIdSelf): + (JSC::JIT::privateCompileGetByIdProto): + (JSC::JIT::privateCompileGetByIdChain): + (JSC::JIT::privateCompilePutByIdReplace): + (JSC::JIT::privateCompilePutByIdTransition): + (JSC::JIT::privateCompileCTIMachineTrampolines): + (JSC::JIT::privateCompilePatchGetArrayLength): + * wrec/WREC.cpp: + (JSC::WREC::compileRegExp): + * wrec/WRECGenerator.cpp: + (JSC::WREC::Generator::generateBackreferenceQuantifier): + (JSC::WREC::Generator::generateNonGreedyQuantifier): + (JSC::WREC::Generator::generateGreedyQuantifier): + (JSC::WREC::Generator::generatePatternCharacter): + (JSC::WREC::Generator::generateCharacterClassInvertedRange): + (JSC::WREC::Generator::generateCharacterClassInverted): + (JSC::WREC::Generator::generateCharacterClass): + (JSC::WREC::Generator::generateParentheses): + (JSC::WREC::Generator::generateParenthesesNonGreedy): + (JSC::WREC::Generator::generateParenthesesResetTrampoline): + (JSC::WREC::Generator::generateAssertionBOL): + (JSC::WREC::Generator::generateAssertionEOL): + (JSC::WREC::Generator::generateAssertionWordBoundary): + (JSC::WREC::Generator::generateBackreference): + (JSC::WREC::Generator::generateDisjunction): + +2008-11-19 Simon Hausmann <hausmann@webkit.org> + + Sun CC build fix, removed trailing comman for last enum value. + + * wtf/unicode/qt4/UnicodeQt4.h: + (WTF::Unicode::): + +2008-11-19 Mark Rowe <mrowe@apple.com> + + Reviewed by Alexey Proskuryakov. + + Expand the workaround for Apple GCC compiler bug <rdar://problem/6354696> to all versions of GCC 4.0.1. + It has been observed with builds 5465 (Xcode 3.0) and 5484 (Xcode 3.1), and there is no evidence + that it has been fixed in newer builds of GCC 4.0.1. + + This addresses <https://bugs.webkit.org/show_bug.cgi?id=22351> (WebKit nightly crashes on launch on 10.4.11). + + * wtf/StdLibExtras.h: + +2008-11-18 Cameron Zwarich <zwarich@apple.com> + + Reviewed by Maciej Stachowiak and Geoff Garen. + + Bug 22287: ASSERTION FAILED: Not enough jumps linked in slow case codegen in CTI::privateCompileSlowCases()) + <https://bugs.webkit.org/show_bug.cgi?id=22287> + + Fix a typo in the number cell reuse code where the first and second + operands are sometimes confused. + + * jit/JIT.cpp: + (JSC::JIT::compileBinaryArithOpSlowCase): + +2008-11-18 Dan Bernstein <mitz@apple.com> + + - try to fix the Windows build + + * interpreter/Interpreter.cpp: + (JSC::Interpreter::privateExecute): + +2008-11-18 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Sam Weinig. + + Minor RegExp cleanup. + + SunSpider says no change. + + * runtime/RegExpObject.cpp: + (JSC::RegExpObject::match): Renamed "regExpObj" to "regExpConstructor". + + * wrec/WREC.cpp: + (JSC::WREC::compileRegExp): Instead of checking for a NULL output vector, + ASSERT that the output vector is not NULL. (The rest of WREC is not + safe to use with a NULL output vector, and we probably don't want to + spend the time and/or performance to make it safe.) + +2008-11-18 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Darin Adler. + + A little more renaming and refactoring. + + VM_CHECK_EXCEPTION() => CHECK_FOR_EXCEPTION(). + NEXT_INSTRUCTION => NEXT_INSTRUCTION(). + + Removed the "Error_" and "TempError_" prefixes from WREC error types. + + Refactored the WREC parser so it doesn't need a "setError" function, + and changed "isEndOfPattern" and its use -- they read kind of backwards + before. + + Changed our "TODO:" error messages at least to say something, since you + can't say "TODO:" in shipping software. + + * interpreter/Interpreter.cpp: + (JSC::Interpreter::privateExecute): + (JSC::Interpreter::cti_op_convert_this): + (JSC::Interpreter::cti_op_add): + (JSC::Interpreter::cti_op_pre_inc): + (JSC::Interpreter::cti_op_loop_if_less): + (JSC::Interpreter::cti_op_loop_if_lesseq): + (JSC::Interpreter::cti_op_put_by_id): + (JSC::Interpreter::cti_op_put_by_id_second): + (JSC::Interpreter::cti_op_put_by_id_generic): + (JSC::Interpreter::cti_op_put_by_id_fail): + (JSC::Interpreter::cti_op_get_by_id): + (JSC::Interpreter::cti_op_get_by_id_second): + (JSC::Interpreter::cti_op_get_by_id_generic): + (JSC::Interpreter::cti_op_get_by_id_fail): + (JSC::Interpreter::cti_op_instanceof): + (JSC::Interpreter::cti_op_del_by_id): + (JSC::Interpreter::cti_op_mul): + (JSC::Interpreter::cti_op_call_NotJSFunction): + (JSC::Interpreter::cti_op_resolve): + (JSC::Interpreter::cti_op_construct_NotJSConstruct): + (JSC::Interpreter::cti_op_get_by_val): + (JSC::Interpreter::cti_op_resolve_func): + (JSC::Interpreter::cti_op_sub): + (JSC::Interpreter::cti_op_put_by_val): + (JSC::Interpreter::cti_op_put_by_val_array): + (JSC::Interpreter::cti_op_lesseq): + (JSC::Interpreter::cti_op_loop_if_true): + (JSC::Interpreter::cti_op_negate): + (JSC::Interpreter::cti_op_resolve_skip): + (JSC::Interpreter::cti_op_resolve_global): + (JSC::Interpreter::cti_op_div): + (JSC::Interpreter::cti_op_pre_dec): + (JSC::Interpreter::cti_op_jless): + (JSC::Interpreter::cti_op_not): + (JSC::Interpreter::cti_op_jtrue): + (JSC::Interpreter::cti_op_post_inc): + (JSC::Interpreter::cti_op_eq): + (JSC::Interpreter::cti_op_lshift): + (JSC::Interpreter::cti_op_bitand): + (JSC::Interpreter::cti_op_rshift): + (JSC::Interpreter::cti_op_bitnot): + (JSC::Interpreter::cti_op_resolve_with_base): + (JSC::Interpreter::cti_op_mod): + (JSC::Interpreter::cti_op_less): + (JSC::Interpreter::cti_op_neq): + (JSC::Interpreter::cti_op_post_dec): + (JSC::Interpreter::cti_op_urshift): + (JSC::Interpreter::cti_op_bitxor): + (JSC::Interpreter::cti_op_bitor): + (JSC::Interpreter::cti_op_push_scope): + (JSC::Interpreter::cti_op_to_jsnumber): + (JSC::Interpreter::cti_op_in): + (JSC::Interpreter::cti_op_del_by_val): + * wrec/WREC.cpp: + (JSC::WREC::compileRegExp): + * wrec/WRECParser.cpp: + (JSC::WREC::Parser::parseGreedyQuantifier): + (JSC::WREC::Parser::parseParentheses): + (JSC::WREC::Parser::parseCharacterClass): + (JSC::WREC::Parser::parseEscape): + * wrec/WRECParser.h: + (JSC::WREC::Parser::): + (JSC::WREC::Parser::atEndOfPattern): + +2008-11-18 Alexey Proskuryakov <ap@webkit.org> + + Reviewed by Darin Adler. + + https://bugs.webkit.org/show_bug.cgi?id=22337 + Enable workers by default + + * Configurations/JavaScriptCore.xcconfig: Define ENABLE_WORKERS. + +2008-11-18 Alexey Proskuryakov <ap@webkit.org> + + - Windows build fix + + * wrec/WRECFunctors.h: + * wrec/WRECGenerator.h: + * wrec/WRECParser.h: + CharacterClass is a struct, not a class, fix forward declarations. + +2008-11-18 Dan Bernstein <mitz@apple.com> + + - Windows build fix + + * assembler/X86Assembler.h: + +2008-11-17 Geoffrey Garen <ggaren@apple.com> + + Not reviewed. + + Try to fix gtk build. + + * wrec/Quantifier.h: + +2008-11-17 Geoffrey Garen <ggaren@apple.com> + + Not reviewed. + + Try to fix gtk build. + + * assembler/AssemblerBuffer.h: + +2008-11-17 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Sam Weinig. + + Split WREC classes out into individual files, with a few modifications + to more closely match the WebKit coding style. + + * GNUmakefile.am: + * JavaScriptCore.scons: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: + * JavaScriptCore.xcodeproj/project.pbxproj: + * assembler/X86Assembler.h: + * runtime/RegExp.cpp: + * wrec/CharacterClass.cpp: Copied from wrec/CharacterClassConstructor.cpp. + (JSC::WREC::CharacterClass::newline): + (JSC::WREC::CharacterClass::digits): + (JSC::WREC::CharacterClass::spaces): + (JSC::WREC::CharacterClass::wordchar): + (JSC::WREC::CharacterClass::nondigits): + (JSC::WREC::CharacterClass::nonspaces): + (JSC::WREC::CharacterClass::nonwordchar): + * wrec/CharacterClass.h: Copied from wrec/CharacterClassConstructor.h. + * wrec/CharacterClassConstructor.cpp: + (JSC::WREC::CharacterClassConstructor::addSortedRange): + (JSC::WREC::CharacterClassConstructor::append): + * wrec/CharacterClassConstructor.h: + * wrec/Quantifier.h: Copied from wrec/WREC.h. + * wrec/WREC.cpp: + (JSC::WREC::compileRegExp): + * wrec/WREC.h: + * wrec/WRECFunctors.cpp: Copied from wrec/WREC.cpp. + * wrec/WRECFunctors.h: Copied from wrec/WREC.cpp. + (JSC::WREC::GenerateAtomFunctor::~GenerateAtomFunctor): + (JSC::WREC::GeneratePatternCharacterFunctor::GeneratePatternCharacterFunctor): + (JSC::WREC::GenerateCharacterClassFunctor::GenerateCharacterClassFunctor): + (JSC::WREC::GenerateBackreferenceFunctor::GenerateBackreferenceFunctor): + (JSC::WREC::GenerateParenthesesNonGreedyFunctor::GenerateParenthesesNonGreedyFunctor): + * wrec/WRECGenerator.cpp: Copied from wrec/WREC.cpp. + (JSC::WREC::Generator::generatePatternCharacter): + (JSC::WREC::Generator::generateCharacterClassInvertedRange): + (JSC::WREC::Generator::generateCharacterClassInverted): + (JSC::WREC::Generator::generateCharacterClass): + (JSC::WREC::Generator::generateParentheses): + (JSC::WREC::Generator::generateAssertionBOL): + (JSC::WREC::Generator::generateAssertionEOL): + (JSC::WREC::Generator::generateAssertionWordBoundary): + * wrec/WRECGenerator.h: Copied from wrec/WREC.h. + * wrec/WRECParser.cpp: Copied from wrec/WREC.cpp. + (JSC::WREC::Parser::parseGreedyQuantifier): + (JSC::WREC::Parser::parseCharacterClassQuantifier): + (JSC::WREC::Parser::parseParentheses): + (JSC::WREC::Parser::parseCharacterClass): + (JSC::WREC::Parser::parseEscape): + (JSC::WREC::Parser::parseTerm): + * wrec/WRECParser.h: Copied from wrec/WREC.h. + (JSC::WREC::Parser::): + (JSC::WREC::Parser::Parser): + (JSC::WREC::Parser::setError): + (JSC::WREC::Parser::error): + (JSC::WREC::Parser::recordSubpattern): + (JSC::WREC::Parser::numSubpatterns): + (JSC::WREC::Parser::ignoreCase): + (JSC::WREC::Parser::multiline): + +2008-11-17 Geoffrey Garen <ggaren@apple.com> + + Not reviewed. + + Try to fix a few builds. + + * JavaScriptCoreSources.bkl: + +2008-11-17 Geoffrey Garen <ggaren@apple.com> + + Not reviewed. + + Try to fix a few builds. + + * JavaScriptCore.pri: + * JavaScriptCore.scons: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: + +2008-11-17 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Sam Weinig. + + Moved VM/CTI.* => jit/JIT.*. + + Removed VM. + + * GNUmakefile.am: + * JavaScriptCore.pri: + * JavaScriptCore.scons: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: + * JavaScriptCore.xcodeproj/project.pbxproj: + * VM/CTI.cpp: Removed. + * VM/CTI.h: Removed. + * bytecode/CodeBlock.cpp: + * interpreter/Interpreter.cpp: + * jit: Added. + * jit/JIT.cpp: Copied from VM/CTI.cpp. + * jit/JIT.h: Copied from VM/CTI.h. + * runtime/RegExp.cpp: + +2008-11-17 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Sam Weinig. + + Moved runtime/ExecState.* => interpreter/CallFrame.*. + + * API/JSBase.cpp: + * API/OpaqueJSString.cpp: + * GNUmakefile.am: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: + * JavaScriptCore.xcodeproj/project.pbxproj: + * debugger/DebuggerCallFrame.h: + * interpreter/CallFrame.cpp: Copied from runtime/ExecState.cpp. + * interpreter/CallFrame.h: Copied from runtime/ExecState.h. + * interpreter/Interpreter.cpp: + * parser/Nodes.cpp: + * profiler/ProfileGenerator.cpp: + * profiler/Profiler.cpp: + * runtime/ClassInfo.h: + * runtime/Collector.cpp: + * runtime/Completion.cpp: + * runtime/ExceptionHelpers.cpp: + * runtime/ExecState.cpp: Removed. + * runtime/ExecState.h: Removed. + * runtime/Identifier.cpp: + * runtime/JSFunction.cpp: + * runtime/JSGlobalObjectFunctions.cpp: + * runtime/JSLock.cpp: + * runtime/JSNumberCell.h: + * runtime/JSObject.h: + * runtime/JSString.h: + * runtime/Lookup.h: + * runtime/PropertyNameArray.h: + +2008-11-17 Geoffrey Garen <ggaren@apple.com> + + Not reviewed. + + Try to fix Windows build. + + * API/APICast.h: + +2008-11-17 Geoffrey Garen <ggaren@apple.com> + + Not reviewed. + + Try to fix Windows build. + + * API/APICast.h: + * runtime/ExecState.h: + +2008-11-17 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Sam Weinig. + + Moved VM/SamplingTool.* => bytecode/SamplingTool.*. + + * GNUmakefile.am: + * JavaScriptCore.pri: + * JavaScriptCore.scons: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: + * JavaScriptCore.xcodeproj/project.pbxproj: + * JavaScriptCoreSources.bkl: + * VM/SamplingTool.cpp: Removed. + * VM/SamplingTool.h: Removed. + * bytecode/SamplingTool.cpp: Copied from VM/SamplingTool.cpp. + * bytecode/SamplingTool.h: Copied from VM/SamplingTool.h. + * jsc.cpp: + (runWithScripts): + +2008-11-17 Geoffrey Garen <ggaren@apple.com> + + Not reviewed. + + Try to fix Windows build. + + * runtime/ExecState.h: + +2008-11-17 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Sam Weinig. + + Moved VM/ExceptionHelpers.cpp => runtime/ExceptionHelpers.cpp. + + * GNUmakefile.am: + * JavaScriptCore.pri: + * JavaScriptCore.scons: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: + * JavaScriptCore.xcodeproj/project.pbxproj: + * JavaScriptCoreSources.bkl: + * VM/ExceptionHelpers.cpp: Removed. + * runtime/ExceptionHelpers.cpp: Copied from VM/ExceptionHelpers.cpp. + +2008-11-17 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Sam Weinig. + + Moved VM/RegisterFile.cpp => interpreter/RegisterFile.cpp. + + * AllInOneFile.cpp: + * GNUmakefile.am: + * JavaScriptCore.pri: + * JavaScriptCore.scons: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: + * JavaScriptCore.xcodeproj/project.pbxproj: + * JavaScriptCoreSources.bkl: + * VM/RegisterFile.cpp: Removed. + * interpreter/RegisterFile.cpp: Copied from VM/RegisterFile.cpp. + +2008-11-17 Geoffrey Garen <ggaren@apple.com> + + Not reviewed. + + Try to fix Windows build. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: + +2008-11-17 Geoffrey Garen <ggaren@apple.com> + + Not reviewed. + + Try to fix Windows build. + + * JavaScriptCore.vcproj/jsc/jsc.vcproj: + +2008-11-17 Geoffrey Garen <ggaren@apple.com> + + Not reviewed. + + Try to fix Windows build. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: + +2008-11-17 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Sam Weinig. + + Moved: + VM/ExceptionHelpers.h => runtime/ExceptionHelpers.h + VM/Register.h => interpreter/Register.h + VM/RegisterFile.h => interpreter/RegisterFile.h + + + * GNUmakefile.am: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: + * JavaScriptCore.xcodeproj/project.pbxproj: + * VM/ExceptionHelpers.h: Removed. + * VM/Register.h: Removed. + * VM/RegisterFile.h: Removed. + * interpreter/Register.h: Copied from VM/Register.h. + * interpreter/RegisterFile.h: Copied from VM/RegisterFile.h. + * runtime/ExceptionHelpers.h: Copied from VM/ExceptionHelpers.h. + +2008-11-17 Geoffrey Garen <ggaren@apple.com> + + Not reviewed. + + Try to fix Qt build. + + * JavaScriptCore.pri: + +2008-11-17 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Sam Weinig. + + Moved VM/Machine.cpp => interpreter/Interpreter.cpp. + + * DerivedSources.make: + * GNUmakefile.am: + * JavaScriptCore.pri: + * JavaScriptCore.scons: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: + * JavaScriptCore.xcodeproj/project.pbxproj: + * JavaScriptCoreSources.bkl: + * VM/Machine.cpp: Removed. + * interpreter/Interpreter.cpp: Copied from VM/Machine.cpp. + +2008-11-17 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Sam Weinig. + + Moved VM/Machine.h => interpreter/Interpreter.h + + * GNUmakefile.am: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: + * JavaScriptCore.xcodeproj/project.pbxproj: + * VM/CTI.cpp: + * VM/CTI.h: + * VM/ExceptionHelpers.cpp: + * VM/Machine.cpp: + * VM/Machine.h: Removed. + * VM/SamplingTool.cpp: + * bytecode/CodeBlock.cpp: + * bytecompiler/BytecodeGenerator.cpp: + * bytecompiler/BytecodeGenerator.h: + * debugger/DebuggerCallFrame.cpp: + * interpreter: Added. + * interpreter/Interpreter.h: Copied from VM/Machine.h. + * profiler/ProfileGenerator.cpp: + * runtime/Arguments.h: + * runtime/ArrayPrototype.cpp: + * runtime/Collector.cpp: + * runtime/Completion.cpp: + * runtime/ExecState.h: + * runtime/FunctionPrototype.cpp: + * runtime/JSActivation.cpp: + * runtime/JSFunction.cpp: + * runtime/JSGlobalData.cpp: + * runtime/JSGlobalObject.cpp: + * runtime/JSGlobalObjectFunctions.cpp: + * wrec/WREC.cpp: + +2008-11-17 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Sam Weinig. + + Moved runtime/Interpreter.cpp => runtime/Completion.cpp. + + Moved functions from Interpreter.h to Completion.h, and removed + Interpreter.h from the project. + + * API/JSBase.cpp: + * AllInOneFile.cpp: + * GNUmakefile.am: + * JavaScriptCore.pri: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: + * JavaScriptCore.xcodeproj/project.pbxproj: + * JavaScriptCoreSources.bkl: + * jsc.cpp: + * runtime/Completion.cpp: Copied from runtime/Interpreter.cpp. + * runtime/Completion.h: + * runtime/Interpreter.cpp: Removed. + * runtime/Interpreter.h: Removed. + +2008-11-17 Gabor Loki <loki@inf.u-szeged.hu> + + Reviewed by Darin Adler. + + <https://bugs.webkit.org/show_bug.cgi?id=22312> + Fix PCRE include path problem on Qt-port + + * JavaScriptCore.pri: + * pcre/pcre.pri: + +2008-11-17 Gabor Loki <loki@inf.u-szeged.hu> + + Reviewed by Darin Adler. + + <https://bugs.webkit.org/show_bug.cgi?id=22313> + Add missing CTI source to the build system on Qt-port + + * JavaScriptCore.pri: + +2008-11-17 Geoffrey Garen <ggaren@apple.com> + + Not reviewed. + + Try to fix JSGlue build. + + * JavaScriptCore.xcodeproj/project.pbxproj: + +2008-11-17 Geoffrey Garen <ggaren@apple.com> + + Not reviewed. + + Try to fix Qt build. + + * jsc.pro: + +2008-11-17 Geoffrey Garen <ggaren@apple.com> + + Not reviewed. + + Try to fix Qt build. + + * JavaScriptCore.pri: + +2008-11-17 Geoffrey Garen <ggaren@apple.com> + + Not reviewed. + + Try to fix Qt build. + + * JavaScriptCore.pri: + +2008-11-17 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Sam Weinig. + + More file moves: + + VM/CodeBlock.* => bytecode/CodeBlock.* + VM/EvalCodeCache.h => bytecode/EvalCodeCache.h + VM/Instruction.h => bytecode/Instruction.h + VM/Opcode.* => bytecode/Opcode.* + + * GNUmakefile.am: + * JavaScriptCore.scons: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: + * JavaScriptCore.vcproj/jsc/jsc.vcproj: + * JavaScriptCore.xcodeproj/project.pbxproj: + * JavaScriptCoreSources.bkl: + * VM/CodeBlock.cpp: Removed. + * VM/CodeBlock.h: Removed. + * VM/EvalCodeCache.h: Removed. + * VM/Instruction.h: Removed. + * VM/Opcode.cpp: Removed. + * VM/Opcode.h: Removed. + * bytecode: Added. + * bytecode/CodeBlock.cpp: Copied from VM/CodeBlock.cpp. + * bytecode/CodeBlock.h: Copied from VM/CodeBlock.h. + * bytecode/EvalCodeCache.h: Copied from VM/EvalCodeCache.h. + * bytecode/Instruction.h: Copied from VM/Instruction.h. + * bytecode/Opcode.cpp: Copied from VM/Opcode.cpp. + * bytecode/Opcode.h: Copied from VM/Opcode.h. + * jsc.pro: + * jscore.bkl: + +2008-11-17 Geoffrey Garen <ggaren@apple.com> + + Not reviewed. + + Try to fix a few more builds. + + * GNUmakefile.am: + * JavaScriptCore.pri: + * JavaScriptCore.scons: + * JavaScriptCoreSources.bkl: + +2008-11-17 Geoffrey Garen <ggaren@apple.com> + + Not reviewed. + + Try to fix gtk build. + + * GNUmakefile.am: + +2008-11-17 Geoffrey Garen <ggaren@apple.com> + + Not reviewed. + + Try to fix Windows build. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: + +2008-11-17 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Sam Weinig. + + Some file moves: + + VM/LabelID.h => bytecompiler/Label.h + VM/RegisterID.h => bytecompiler/RegisterID.h + VM/SegmentedVector.h => bytecompiler/SegmentedVector.h + bytecompiler/CodeGenerator.* => bytecompiler/BytecodeGenerator.* + + * AllInOneFile.cpp: + * JavaScriptCore.xcodeproj/project.pbxproj: + * VM/LabelID.h: Removed. + * VM/RegisterID.h: Removed. + * VM/SegmentedVector.h: Removed. + * bytecompiler/BytecodeGenerator.cpp: Copied from bytecompiler/CodeGenerator.cpp. + * bytecompiler/BytecodeGenerator.h: Copied from bytecompiler/CodeGenerator.h. + * bytecompiler/CodeGenerator.cpp: Removed. + * bytecompiler/CodeGenerator.h: Removed. + * bytecompiler/Label.h: Copied from VM/LabelID.h. + * bytecompiler/LabelScope.h: + * bytecompiler/RegisterID.h: Copied from VM/RegisterID.h. + * bytecompiler/SegmentedVector.h: Copied from VM/SegmentedVector.h. + * jsc.cpp: + * parser/Nodes.cpp: + +2008-11-17 Geoffrey Garen <ggaren@apple.com> + + Not reviewed. + + Try to fix Windows build. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: + +2008-11-17 Geoffrey Garen <ggaren@apple.com> + + Not reviewed. + + Try to fix Windows build. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: + +2008-11-17 Geoffrey Garen <ggaren@apple.com> + + Not reviewed. + + Try to fix Windows build. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: + +2008-11-16 Geoffrey Garen <ggaren@apple.com> + + Not reviewed. + + Try to fix Windows build. + + * JavaScriptCore.vcproj/jsc/jsc.vcproj: + +2008-11-16 Geoffrey Garen <ggaren@apple.com> + + Not reviewed. + + Try to fix Windows build. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: + +2008-11-16 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Sam Weinig. + + Moved masm => assembler and split "AssemblerBuffer.h" out of "X86Assembler.h". + + Also renamed ENABLE_MASM to ENABLE_ASSEMBLER. + + * GNUmakefile.am: + * JavaScriptCore.xcodeproj/project.pbxproj: + * assembler: Added. + * assembler/AssemblerBuffer.h: Copied from masm/X86Assembler.h. + (JSC::AssemblerBuffer::AssemblerBuffer): + (JSC::AssemblerBuffer::~AssemblerBuffer): + (JSC::AssemblerBuffer::ensureSpace): + (JSC::AssemblerBuffer::isAligned): + (JSC::AssemblerBuffer::putByteUnchecked): + (JSC::AssemblerBuffer::putByte): + (JSC::AssemblerBuffer::putShortUnchecked): + (JSC::AssemblerBuffer::putShort): + (JSC::AssemblerBuffer::putIntUnchecked): + (JSC::AssemblerBuffer::putInt): + (JSC::AssemblerBuffer::data): + (JSC::AssemblerBuffer::size): + (JSC::AssemblerBuffer::reset): + (JSC::AssemblerBuffer::executableCopy): + (JSC::AssemblerBuffer::grow): + * assembler/X86Assembler.h: Copied from masm/X86Assembler.h. + * masm: Removed. + * masm/X86Assembler.h: Removed. + * wtf/Platform.h: + +2008-11-16 Geoffrey Garen <ggaren@apple.com> + + Not reviewed. + + Try to fix gtk build. + + * GNUmakefile.am: + +2008-11-16 Geoffrey Garen <ggaren@apple.com> + + Not reviewed. + + Fixed tyop. + + * VM/CTI.cpp: + +2008-11-16 Geoffrey Garen <ggaren@apple.com> + + Not reviewed. + + Try to fix windows build. + + * VM/CTI.cpp: + +2008-11-16 Geoffrey Garen <ggaren@apple.com> + + Not reviewed. + + Try to fix gtk build. + + * GNUmakefile.am: + +2008-11-16 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Sam Weinig. + + Renamed ENABLE_CTI and ENABLE(CTI) to ENABLE_JIT and ENABLE(JIT). + + * VM/CTI.cpp: + * VM/CTI.h: + * VM/CodeBlock.cpp: + (JSC::CodeBlock::~CodeBlock): + * VM/CodeBlock.h: + (JSC::CodeBlock::CodeBlock): + * VM/Machine.cpp: + (JSC::Interpreter::Interpreter): + (JSC::Interpreter::initialize): + (JSC::Interpreter::~Interpreter): + (JSC::Interpreter::execute): + (JSC::Interpreter::privateExecute): + * VM/Machine.h: + * bytecompiler/CodeGenerator.cpp: + (JSC::prepareJumpTableForStringSwitch): + * runtime/JSFunction.cpp: + (JSC::JSFunction::~JSFunction): + * runtime/JSGlobalData.h: + * wrec/WREC.h: + * wtf/Platform.h: + * wtf/TCSystemAlloc.cpp: + +2008-11-16 Geoffrey Garen <ggaren@apple.com> + + Not reviewed. + + Try to fix gtk build. + + * VM/CTI.cpp: + +2008-11-16 Geoffrey Garen <ggaren@apple.com> + + Reviewed by a few people on squirrelfish-dev. + + Renamed CTI => JIT. + + * VM/CTI.cpp: + (JSC::JIT::killLastResultRegister): + (JSC::JIT::emitGetVirtualRegister): + (JSC::JIT::emitGetVirtualRegisters): + (JSC::JIT::emitPutCTIArgFromVirtualRegister): + (JSC::JIT::emitPutCTIArg): + (JSC::JIT::emitGetCTIArg): + (JSC::JIT::emitPutCTIArgConstant): + (JSC::JIT::getConstantImmediateNumericArg): + (JSC::JIT::emitPutCTIParam): + (JSC::JIT::emitGetCTIParam): + (JSC::JIT::emitPutToCallFrameHeader): + (JSC::JIT::emitGetFromCallFrameHeader): + (JSC::JIT::emitPutVirtualRegister): + (JSC::JIT::emitInitRegister): + (JSC::JIT::printBytecodeOperandTypes): + (JSC::JIT::emitAllocateNumber): + (JSC::JIT::emitNakedCall): + (JSC::JIT::emitNakedFastCall): + (JSC::JIT::emitCTICall): + (JSC::JIT::emitJumpSlowCaseIfNotJSCell): + (JSC::JIT::linkSlowCaseIfNotJSCell): + (JSC::JIT::emitJumpSlowCaseIfNotImmNum): + (JSC::JIT::emitJumpSlowCaseIfNotImmNums): + (JSC::JIT::getDeTaggedConstantImmediate): + (JSC::JIT::emitFastArithDeTagImmediate): + (JSC::JIT::emitFastArithDeTagImmediateJumpIfZero): + (JSC::JIT::emitFastArithReTagImmediate): + (JSC::JIT::emitFastArithPotentiallyReTagImmediate): + (JSC::JIT::emitFastArithImmToInt): + (JSC::JIT::emitFastArithIntToImmOrSlowCase): + (JSC::JIT::emitFastArithIntToImmNoCheck): + (JSC::JIT::emitArithIntToImmWithJump): + (JSC::JIT::emitTagAsBoolImmediate): + (JSC::JIT::JIT): + (JSC::JIT::compileOpCallInitializeCallFrame): + (JSC::JIT::compileOpCallSetupArgs): + (JSC::JIT::compileOpCallEvalSetupArgs): + (JSC::JIT::compileOpConstructSetupArgs): + (JSC::JIT::compileOpCall): + (JSC::JIT::compileOpStrictEq): + (JSC::JIT::emitSlowScriptCheck): + (JSC::JIT::putDoubleResultToJSNumberCellOrJSImmediate): + (JSC::JIT::compileBinaryArithOp): + (JSC::JIT::compileBinaryArithOpSlowCase): + (JSC::JIT::privateCompileMainPass): + (JSC::JIT::privateCompileLinkPass): + (JSC::JIT::privateCompileSlowCases): + (JSC::JIT::privateCompile): + (JSC::JIT::privateCompileGetByIdSelf): + (JSC::JIT::privateCompileGetByIdProto): + (JSC::JIT::privateCompileGetByIdChain): + (JSC::JIT::privateCompilePutByIdReplace): + (JSC::JIT::privateCompilePutByIdTransition): + (JSC::JIT::unlinkCall): + (JSC::JIT::linkCall): + (JSC::JIT::privateCompileCTIMachineTrampolines): + (JSC::JIT::freeCTIMachineTrampolines): + (JSC::JIT::patchGetByIdSelf): + (JSC::JIT::patchPutByIdReplace): + (JSC::JIT::privateCompilePatchGetArrayLength): + (JSC::JIT::emitGetVariableObjectRegister): + (JSC::JIT::emitPutVariableObjectRegister): + * VM/CTI.h: + (JSC::JIT::compile): + (JSC::JIT::compileGetByIdSelf): + (JSC::JIT::compileGetByIdProto): + (JSC::JIT::compileGetByIdChain): + (JSC::JIT::compilePutByIdReplace): + (JSC::JIT::compilePutByIdTransition): + (JSC::JIT::compileCTIMachineTrampolines): + (JSC::JIT::compilePatchGetArrayLength): + * VM/CodeBlock.cpp: + (JSC::CodeBlock::unlinkCallers): + * VM/Machine.cpp: + (JSC::Interpreter::initialize): + (JSC::Interpreter::~Interpreter): + (JSC::Interpreter::execute): + (JSC::Interpreter::tryCTICachePutByID): + (JSC::Interpreter::tryCTICacheGetByID): + (JSC::Interpreter::cti_op_call_JSFunction): + (JSC::Interpreter::cti_vm_dontLazyLinkCall): + (JSC::Interpreter::cti_vm_lazyLinkCall): + * VM/Machine.h: + * VM/RegisterFile.h: + * parser/Nodes.h: + * runtime/JSArray.h: + * runtime/JSCell.h: + * runtime/JSFunction.h: + * runtime/JSImmediate.h: + * runtime/JSNumberCell.h: + * runtime/JSObject.h: + * runtime/JSString.h: + * runtime/JSVariableObject.h: + * runtime/ScopeChain.h: + * runtime/Structure.h: + * runtime/TypeInfo.h: + * runtime/UString.h: + +2008-11-16 Geoffrey Garen <ggaren@apple.com> + + Not reviewed. + + Try to fix wx build. + + * jscore.bkl: + +2008-11-16 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Sam Weinig. + + Nixed X86:: and X86Assembler:: prefixes in a lot of places using typedefs. + + * VM/CTI.cpp: + (JSC::CTI::emitGetVirtualRegister): + (JSC::CTI::emitGetVirtualRegisters): + (JSC::CTI::emitPutCTIArgFromVirtualRegister): + (JSC::CTI::emitPutCTIArg): + (JSC::CTI::emitGetCTIArg): + (JSC::CTI::emitPutCTIParam): + (JSC::CTI::emitGetCTIParam): + (JSC::CTI::emitPutToCallFrameHeader): + (JSC::CTI::emitGetFromCallFrameHeader): + (JSC::CTI::emitPutVirtualRegister): + (JSC::CTI::emitNakedCall): + (JSC::CTI::emitNakedFastCall): + (JSC::CTI::emitCTICall): + (JSC::CTI::emitJumpSlowCaseIfNotJSCell): + (JSC::CTI::emitJumpSlowCaseIfNotImmNum): + (JSC::CTI::emitJumpSlowCaseIfNotImmNums): + (JSC::CTI::emitFastArithDeTagImmediate): + (JSC::CTI::emitFastArithDeTagImmediateJumpIfZero): + (JSC::CTI::emitFastArithReTagImmediate): + (JSC::CTI::emitFastArithPotentiallyReTagImmediate): + (JSC::CTI::emitFastArithImmToInt): + (JSC::CTI::emitFastArithIntToImmOrSlowCase): + (JSC::CTI::emitFastArithIntToImmNoCheck): + (JSC::CTI::emitArithIntToImmWithJump): + (JSC::CTI::emitTagAsBoolImmediate): + (JSC::CTI::compileOpCall): + (JSC::CTI::compileOpStrictEq): + (JSC::CTI::emitSlowScriptCheck): + (JSC::CTI::putDoubleResultToJSNumberCellOrJSImmediate): + (JSC::CTI::compileBinaryArithOp): + (JSC::CTI::compileBinaryArithOpSlowCase): + (JSC::CTI::privateCompileMainPass): + (JSC::CTI::privateCompileSlowCases): + (JSC::CTI::privateCompile): + (JSC::CTI::privateCompileGetByIdSelf): + (JSC::CTI::privateCompileGetByIdProto): + (JSC::CTI::privateCompileGetByIdChain): + (JSC::CTI::privateCompilePutByIdReplace): + (JSC::CTI::privateCompilePutByIdTransition): + (JSC::CTI::privateCompileCTIMachineTrampolines): + (JSC::CTI::privateCompilePatchGetArrayLength): + (JSC::CTI::emitGetVariableObjectRegister): + (JSC::CTI::emitPutVariableObjectRegister): + * VM/CTI.h: + (JSC::CallRecord::CallRecord): + (JSC::JmpTable::JmpTable): + (JSC::SlowCaseEntry::SlowCaseEntry): + (JSC::CTI::JSRInfo::JSRInfo): + * wrec/WREC.h: + +2008-11-16 Geoffrey Garen <ggaren@apple.com> + + Not reviewed. + + Try to fix Qt build. + + * JavaScriptCore.pri: + +2008-11-16 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Sam Weinig. + + Renamed OBJECT_OFFSET => FIELD_OFFSET + + Nixed use of OBJECT_OFFSET outside of CTI.cpp by making CTI a friend in + more places. + + * VM/CTI.cpp: + (JSC::CTI::compileOpCallInitializeCallFrame): + (JSC::CTI::compileOpCall): + (JSC::CTI::emitSlowScriptCheck): + (JSC::CTI::putDoubleResultToJSNumberCellOrJSImmediate): + (JSC::CTI::compileBinaryArithOp): + (JSC::CTI::privateCompileMainPass): + (JSC::CTI::privateCompileSlowCases): + (JSC::CTI::privateCompile): + (JSC::CTI::privateCompileGetByIdSelf): + (JSC::CTI::privateCompileGetByIdProto): + (JSC::CTI::privateCompileGetByIdChain): + (JSC::CTI::privateCompilePutByIdReplace): + (JSC::CTI::privateCompilePutByIdTransition): + (JSC::CTI::privateCompileCTIMachineTrampolines): + (JSC::CTI::privateCompilePatchGetArrayLength): + (JSC::CTI::emitGetVariableObjectRegister): + (JSC::CTI::emitPutVariableObjectRegister): + * runtime/JSValue.h: + * runtime/JSVariableObject.h: + +2008-11-16 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Sam Weinig. + + Renames: + + X86Assembler::copy => X86Assembler::executableCopy + AssemblerBuffer::copy => AssemblerBuffer::executableCopy + + * VM/CTI.cpp: + (JSC::CTI::privateCompile): + (JSC::CTI::privateCompileGetByIdSelf): + (JSC::CTI::privateCompileGetByIdProto): + (JSC::CTI::privateCompileGetByIdChain): + (JSC::CTI::privateCompilePutByIdReplace): + (JSC::CTI::privateCompilePutByIdTransition): + (JSC::CTI::privateCompileCTIMachineTrampolines): + (JSC::CTI::privateCompilePatchGetArrayLength): + * masm/X86Assembler.h: + (JSC::AssemblerBuffer::executableCopy): + (JSC::X86Assembler::executableCopy): + * wrec/WREC.cpp: + (JSC::WREC::compileRegExp): + +2008-11-16 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Sam Weinig. + + Renamed WREC => JSC::WREC, removing JSC:: prefix in a lot of places. + Renamed WRECFunction => WREC::CompiledRegExp, and deployed this type + name in place of a few casts. + + * runtime/RegExp.cpp: + (JSC::RegExp::RegExp): + (JSC::RegExp::~RegExp): + (JSC::RegExp::match): + * runtime/RegExp.h: + * wrec/CharacterClassConstructor.cpp: + * wrec/CharacterClassConstructor.h: + * wrec/WREC.cpp: + (JSC::WREC::compileRegExp): + * wrec/WREC.h: + (JSC::WREC::Generator::Generator): + (JSC::WREC::Parser::Parser): + (JSC::WREC::Parser::parseAlternative): + +2008-11-16 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Sam Weinig. + + Renamed BytecodeInterpreter => Interpreter. + + * JavaScriptCore.exp: + * VM/CTI.cpp: + (JSC::): + (JSC::CTI::compileOpCall): + (JSC::CTI::emitSlowScriptCheck): + (JSC::CTI::compileBinaryArithOpSlowCase): + (JSC::CTI::privateCompileMainPass): + (JSC::CTI::privateCompileSlowCases): + (JSC::CTI::privateCompile): + (JSC::CTI::privateCompileGetByIdSelf): + (JSC::CTI::privateCompileGetByIdProto): + (JSC::CTI::privateCompileGetByIdChain): + (JSC::CTI::privateCompilePutByIdReplace): + (JSC::CTI::privateCompilePutByIdTransition): + (JSC::CTI::privateCompileCTIMachineTrampolines): + (JSC::CTI::freeCTIMachineTrampolines): + (JSC::CTI::patchGetByIdSelf): + (JSC::CTI::patchPutByIdReplace): + (JSC::CTI::privateCompilePatchGetArrayLength): + * VM/CTI.h: + * VM/CodeBlock.cpp: + (JSC::CodeBlock::printStructures): + (JSC::CodeBlock::derefStructures): + (JSC::CodeBlock::refStructures): + * VM/Machine.cpp: + (JSC::jsLess): + (JSC::jsLessEq): + (JSC::Interpreter::resolve): + (JSC::Interpreter::resolveSkip): + (JSC::Interpreter::resolveGlobal): + (JSC::Interpreter::resolveBase): + (JSC::Interpreter::resolveBaseAndProperty): + (JSC::Interpreter::resolveBaseAndFunc): + (JSC::Interpreter::slideRegisterWindowForCall): + (JSC::Interpreter::callEval): + (JSC::Interpreter::Interpreter): + (JSC::Interpreter::initialize): + (JSC::Interpreter::~Interpreter): + (JSC::Interpreter::dumpCallFrame): + (JSC::Interpreter::dumpRegisters): + (JSC::Interpreter::isOpcode): + (JSC::Interpreter::unwindCallFrame): + (JSC::Interpreter::throwException): + (JSC::Interpreter::execute): + (JSC::Interpreter::debug): + (JSC::Interpreter::resetTimeoutCheck): + (JSC::Interpreter::checkTimeout): + (JSC::Interpreter::createExceptionScope): + (JSC::Interpreter::tryCachePutByID): + (JSC::Interpreter::uncachePutByID): + (JSC::Interpreter::tryCacheGetByID): + (JSC::Interpreter::uncacheGetByID): + (JSC::Interpreter::privateExecute): + (JSC::Interpreter::retrieveArguments): + (JSC::Interpreter::retrieveCaller): + (JSC::Interpreter::retrieveLastCaller): + (JSC::Interpreter::findFunctionCallFrame): + (JSC::Interpreter::tryCTICachePutByID): + (JSC::Interpreter::tryCTICacheGetByID): + (JSC::Interpreter::cti_op_convert_this): + (JSC::Interpreter::cti_op_end): + (JSC::Interpreter::cti_op_add): + (JSC::Interpreter::cti_op_pre_inc): + (JSC::Interpreter::cti_timeout_check): + (JSC::Interpreter::cti_register_file_check): + (JSC::Interpreter::cti_op_loop_if_less): + (JSC::Interpreter::cti_op_loop_if_lesseq): + (JSC::Interpreter::cti_op_new_object): + (JSC::Interpreter::cti_op_put_by_id): + (JSC::Interpreter::cti_op_put_by_id_second): + (JSC::Interpreter::cti_op_put_by_id_generic): + (JSC::Interpreter::cti_op_put_by_id_fail): + (JSC::Interpreter::cti_op_get_by_id): + (JSC::Interpreter::cti_op_get_by_id_second): + (JSC::Interpreter::cti_op_get_by_id_generic): + (JSC::Interpreter::cti_op_get_by_id_fail): + (JSC::Interpreter::cti_op_instanceof): + (JSC::Interpreter::cti_op_del_by_id): + (JSC::Interpreter::cti_op_mul): + (JSC::Interpreter::cti_op_new_func): + (JSC::Interpreter::cti_op_call_JSFunction): + (JSC::Interpreter::cti_op_call_arityCheck): + (JSC::Interpreter::cti_vm_dontLazyLinkCall): + (JSC::Interpreter::cti_vm_lazyLinkCall): + (JSC::Interpreter::cti_op_push_activation): + (JSC::Interpreter::cti_op_call_NotJSFunction): + (JSC::Interpreter::cti_op_create_arguments): + (JSC::Interpreter::cti_op_create_arguments_no_params): + (JSC::Interpreter::cti_op_tear_off_activation): + (JSC::Interpreter::cti_op_tear_off_arguments): + (JSC::Interpreter::cti_op_profile_will_call): + (JSC::Interpreter::cti_op_profile_did_call): + (JSC::Interpreter::cti_op_ret_scopeChain): + (JSC::Interpreter::cti_op_new_array): + (JSC::Interpreter::cti_op_resolve): + (JSC::Interpreter::cti_op_construct_JSConstruct): + (JSC::Interpreter::cti_op_construct_NotJSConstruct): + (JSC::Interpreter::cti_op_get_by_val): + (JSC::Interpreter::cti_op_resolve_func): + (JSC::Interpreter::cti_op_sub): + (JSC::Interpreter::cti_op_put_by_val): + (JSC::Interpreter::cti_op_put_by_val_array): + (JSC::Interpreter::cti_op_lesseq): + (JSC::Interpreter::cti_op_loop_if_true): + (JSC::Interpreter::cti_op_negate): + (JSC::Interpreter::cti_op_resolve_base): + (JSC::Interpreter::cti_op_resolve_skip): + (JSC::Interpreter::cti_op_resolve_global): + (JSC::Interpreter::cti_op_div): + (JSC::Interpreter::cti_op_pre_dec): + (JSC::Interpreter::cti_op_jless): + (JSC::Interpreter::cti_op_not): + (JSC::Interpreter::cti_op_jtrue): + (JSC::Interpreter::cti_op_post_inc): + (JSC::Interpreter::cti_op_eq): + (JSC::Interpreter::cti_op_lshift): + (JSC::Interpreter::cti_op_bitand): + (JSC::Interpreter::cti_op_rshift): + (JSC::Interpreter::cti_op_bitnot): + (JSC::Interpreter::cti_op_resolve_with_base): + (JSC::Interpreter::cti_op_new_func_exp): + (JSC::Interpreter::cti_op_mod): + (JSC::Interpreter::cti_op_less): + (JSC::Interpreter::cti_op_neq): + (JSC::Interpreter::cti_op_post_dec): + (JSC::Interpreter::cti_op_urshift): + (JSC::Interpreter::cti_op_bitxor): + (JSC::Interpreter::cti_op_new_regexp): + (JSC::Interpreter::cti_op_bitor): + (JSC::Interpreter::cti_op_call_eval): + (JSC::Interpreter::cti_op_throw): + (JSC::Interpreter::cti_op_get_pnames): + (JSC::Interpreter::cti_op_next_pname): + (JSC::Interpreter::cti_op_push_scope): + (JSC::Interpreter::cti_op_pop_scope): + (JSC::Interpreter::cti_op_typeof): + (JSC::Interpreter::cti_op_is_undefined): + (JSC::Interpreter::cti_op_is_boolean): + (JSC::Interpreter::cti_op_is_number): + (JSC::Interpreter::cti_op_is_string): + (JSC::Interpreter::cti_op_is_object): + (JSC::Interpreter::cti_op_is_function): + (JSC::Interpreter::cti_op_stricteq): + (JSC::Interpreter::cti_op_nstricteq): + (JSC::Interpreter::cti_op_to_jsnumber): + (JSC::Interpreter::cti_op_in): + (JSC::Interpreter::cti_op_push_new_scope): + (JSC::Interpreter::cti_op_jmp_scopes): + (JSC::Interpreter::cti_op_put_by_index): + (JSC::Interpreter::cti_op_switch_imm): + (JSC::Interpreter::cti_op_switch_char): + (JSC::Interpreter::cti_op_switch_string): + (JSC::Interpreter::cti_op_del_by_val): + (JSC::Interpreter::cti_op_put_getter): + (JSC::Interpreter::cti_op_put_setter): + (JSC::Interpreter::cti_op_new_error): + (JSC::Interpreter::cti_op_debug): + (JSC::Interpreter::cti_vm_throw): + * VM/Machine.h: + * VM/Register.h: + * VM/SamplingTool.h: + (JSC::SamplingTool::SamplingTool): + * bytecompiler/CodeGenerator.cpp: + (JSC::BytecodeGenerator::generate): + (JSC::BytecodeGenerator::BytecodeGenerator): + * jsc.cpp: + (runWithScripts): + * runtime/ExecState.h: + (JSC::ExecState::interpreter): + * runtime/JSCell.h: + * runtime/JSFunction.h: + * runtime/JSGlobalData.cpp: + (JSC::JSGlobalData::JSGlobalData): + * runtime/JSGlobalData.h: + * runtime/JSString.h: + * wrec/WREC.cpp: + (WREC::compileRegExp): + * wrec/WREC.h: + +2008-11-16 Geoffrey Garen <ggaren@apple.com> + + Roll out r38461 (my last patch) because it broke the world. + +2008-11-16 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Sam Weinig. + + A few more renames: + + BytecodeInterpreter => Interpreter + WREC => JSC::WREC, removing JSC:: prefix in a lot of places + X86Assembler::copy => X86Assembler::executableCopy + AssemblerBuffer::copy => AssemblerBuffer::executableCopy + WRECFunction => WREC::RegExpFunction + OBJECT_OFFSET => FIELD_OFFSET + + Also: + + Nixed use of OBJECT_OFFSET outside of CTI.cpp by making CTI a friend in more places. + Nixed X86:: and X86Assembler:: prefixes in a lot of places using typedefs + + * JavaScriptCore.exp: + * VM/CTI.cpp: + (JSC::): + (JSC::CTI::emitGetVirtualRegister): + (JSC::CTI::emitGetVirtualRegisters): + (JSC::CTI::emitPutCTIArgFromVirtualRegister): + (JSC::CTI::emitPutCTIArg): + (JSC::CTI::emitGetCTIArg): + (JSC::CTI::emitPutCTIParam): + (JSC::CTI::emitGetCTIParam): + (JSC::CTI::emitPutToCallFrameHeader): + (JSC::CTI::emitGetFromCallFrameHeader): + (JSC::CTI::emitPutVirtualRegister): + (JSC::CTI::emitNakedCall): + (JSC::CTI::emitNakedFastCall): + (JSC::CTI::emitCTICall): + (JSC::CTI::emitJumpSlowCaseIfNotJSCell): + (JSC::CTI::emitJumpSlowCaseIfNotImmNum): + (JSC::CTI::emitJumpSlowCaseIfNotImmNums): + (JSC::CTI::emitFastArithDeTagImmediate): + (JSC::CTI::emitFastArithDeTagImmediateJumpIfZero): + (JSC::CTI::emitFastArithReTagImmediate): + (JSC::CTI::emitFastArithPotentiallyReTagImmediate): + (JSC::CTI::emitFastArithImmToInt): + (JSC::CTI::emitFastArithIntToImmOrSlowCase): + (JSC::CTI::emitFastArithIntToImmNoCheck): + (JSC::CTI::emitArithIntToImmWithJump): + (JSC::CTI::emitTagAsBoolImmediate): + (JSC::CTI::compileOpCallInitializeCallFrame): + (JSC::CTI::compileOpCall): + (JSC::CTI::compileOpStrictEq): + (JSC::CTI::emitSlowScriptCheck): + (JSC::CTI::putDoubleResultToJSNumberCellOrJSImmediate): + (JSC::CTI::compileBinaryArithOp): + (JSC::CTI::compileBinaryArithOpSlowCase): + (JSC::CTI::privateCompileMainPass): + (JSC::CTI::privateCompileSlowCases): + (JSC::CTI::privateCompile): + (JSC::CTI::privateCompileGetByIdSelf): + (JSC::CTI::privateCompileGetByIdProto): + (JSC::CTI::privateCompileGetByIdChain): + (JSC::CTI::privateCompilePutByIdReplace): + (JSC::CTI::privateCompilePutByIdTransition): + (JSC::CTI::privateCompileCTIMachineTrampolines): + (JSC::CTI::freeCTIMachineTrampolines): + (JSC::CTI::patchGetByIdSelf): + (JSC::CTI::patchPutByIdReplace): + (JSC::CTI::privateCompilePatchGetArrayLength): + (JSC::CTI::emitGetVariableObjectRegister): + (JSC::CTI::emitPutVariableObjectRegister): + * VM/CTI.h: + (JSC::CallRecord::CallRecord): + (JSC::JmpTable::JmpTable): + (JSC::SlowCaseEntry::SlowCaseEntry): + (JSC::CTI::JSRInfo::JSRInfo): + * VM/CodeBlock.cpp: + (JSC::CodeBlock::printStructures): + (JSC::CodeBlock::derefStructures): + (JSC::CodeBlock::refStructures): + * VM/Machine.cpp: + (JSC::jsLess): + (JSC::jsLessEq): + (JSC::Interpreter::resolve): + (JSC::Interpreter::resolveSkip): + (JSC::Interpreter::resolveGlobal): + (JSC::Interpreter::resolveBase): + (JSC::Interpreter::resolveBaseAndProperty): + (JSC::Interpreter::resolveBaseAndFunc): + (JSC::Interpreter::slideRegisterWindowForCall): + (JSC::Interpreter::callEval): + (JSC::Interpreter::Interpreter): + (JSC::Interpreter::initialize): + (JSC::Interpreter::~Interpreter): + (JSC::Interpreter::dumpCallFrame): + (JSC::Interpreter::dumpRegisters): + (JSC::Interpreter::isOpcode): + (JSC::Interpreter::unwindCallFrame): + (JSC::Interpreter::throwException): + (JSC::Interpreter::execute): + (JSC::Interpreter::debug): + (JSC::Interpreter::resetTimeoutCheck): + (JSC::Interpreter::checkTimeout): + (JSC::Interpreter::createExceptionScope): + (JSC::Interpreter::tryCachePutByID): + (JSC::Interpreter::uncachePutByID): + (JSC::Interpreter::tryCacheGetByID): + (JSC::Interpreter::uncacheGetByID): + (JSC::Interpreter::privateExecute): + (JSC::Interpreter::retrieveArguments): + (JSC::Interpreter::retrieveCaller): + (JSC::Interpreter::retrieveLastCaller): + (JSC::Interpreter::findFunctionCallFrame): + (JSC::Interpreter::tryCTICachePutByID): + (JSC::Interpreter::tryCTICacheGetByID): + (JSC::): + (JSC::Interpreter::cti_op_convert_this): + (JSC::Interpreter::cti_op_end): + (JSC::Interpreter::cti_op_add): + (JSC::Interpreter::cti_op_pre_inc): + (JSC::Interpreter::cti_timeout_check): + (JSC::Interpreter::cti_register_file_check): + (JSC::Interpreter::cti_op_loop_if_less): + (JSC::Interpreter::cti_op_loop_if_lesseq): + (JSC::Interpreter::cti_op_new_object): + (JSC::Interpreter::cti_op_put_by_id): + (JSC::Interpreter::cti_op_put_by_id_second): + (JSC::Interpreter::cti_op_put_by_id_generic): + (JSC::Interpreter::cti_op_put_by_id_fail): + (JSC::Interpreter::cti_op_get_by_id): + (JSC::Interpreter::cti_op_get_by_id_second): + (JSC::Interpreter::cti_op_get_by_id_generic): + (JSC::Interpreter::cti_op_get_by_id_fail): + (JSC::Interpreter::cti_op_instanceof): + (JSC::Interpreter::cti_op_del_by_id): + (JSC::Interpreter::cti_op_mul): + (JSC::Interpreter::cti_op_new_func): + (JSC::Interpreter::cti_op_call_JSFunction): + (JSC::Interpreter::cti_op_call_arityCheck): + (JSC::Interpreter::cti_vm_dontLazyLinkCall): + (JSC::Interpreter::cti_vm_lazyLinkCall): + (JSC::Interpreter::cti_op_push_activation): + (JSC::Interpreter::cti_op_call_NotJSFunction): + (JSC::Interpreter::cti_op_create_arguments): + (JSC::Interpreter::cti_op_create_arguments_no_params): + (JSC::Interpreter::cti_op_tear_off_activation): + (JSC::Interpreter::cti_op_tear_off_arguments): + (JSC::Interpreter::cti_op_profile_will_call): + (JSC::Interpreter::cti_op_profile_did_call): + (JSC::Interpreter::cti_op_ret_scopeChain): + (JSC::Interpreter::cti_op_new_array): + (JSC::Interpreter::cti_op_resolve): + (JSC::Interpreter::cti_op_construct_JSConstruct): + (JSC::Interpreter::cti_op_construct_NotJSConstruct): + (JSC::Interpreter::cti_op_get_by_val): + (JSC::Interpreter::cti_op_resolve_func): + (JSC::Interpreter::cti_op_sub): + (JSC::Interpreter::cti_op_put_by_val): + (JSC::Interpreter::cti_op_put_by_val_array): + (JSC::Interpreter::cti_op_lesseq): + (JSC::Interpreter::cti_op_loop_if_true): + (JSC::Interpreter::cti_op_negate): + (JSC::Interpreter::cti_op_resolve_base): + (JSC::Interpreter::cti_op_resolve_skip): + (JSC::Interpreter::cti_op_resolve_global): + (JSC::Interpreter::cti_op_div): + (JSC::Interpreter::cti_op_pre_dec): + (JSC::Interpreter::cti_op_jless): + (JSC::Interpreter::cti_op_not): + (JSC::Interpreter::cti_op_jtrue): + (JSC::Interpreter::cti_op_post_inc): + (JSC::Interpreter::cti_op_eq): + (JSC::Interpreter::cti_op_lshift): + (JSC::Interpreter::cti_op_bitand): + (JSC::Interpreter::cti_op_rshift): + (JSC::Interpreter::cti_op_bitnot): + (JSC::Interpreter::cti_op_resolve_with_base): + (JSC::Interpreter::cti_op_new_func_exp): + (JSC::Interpreter::cti_op_mod): + (JSC::Interpreter::cti_op_less): + (JSC::Interpreter::cti_op_neq): + (JSC::Interpreter::cti_op_post_dec): + (JSC::Interpreter::cti_op_urshift): + (JSC::Interpreter::cti_op_bitxor): + (JSC::Interpreter::cti_op_new_regexp): + (JSC::Interpreter::cti_op_bitor): + (JSC::Interpreter::cti_op_call_eval): + (JSC::Interpreter::cti_op_throw): + (JSC::Interpreter::cti_op_get_pnames): + (JSC::Interpreter::cti_op_next_pname): + (JSC::Interpreter::cti_op_push_scope): + (JSC::Interpreter::cti_op_pop_scope): + (JSC::Interpreter::cti_op_typeof): + (JSC::Interpreter::cti_op_is_undefined): + (JSC::Interpreter::cti_op_is_boolean): + (JSC::Interpreter::cti_op_is_number): + (JSC::Interpreter::cti_op_is_string): + (JSC::Interpreter::cti_op_is_object): + (JSC::Interpreter::cti_op_is_function): + (JSC::Interpreter::cti_op_stricteq): + (JSC::Interpreter::cti_op_nstricteq): + (JSC::Interpreter::cti_op_to_jsnumber): + (JSC::Interpreter::cti_op_in): + (JSC::Interpreter::cti_op_push_new_scope): + (JSC::Interpreter::cti_op_jmp_scopes): + (JSC::Interpreter::cti_op_put_by_index): + (JSC::Interpreter::cti_op_switch_imm): + (JSC::Interpreter::cti_op_switch_char): + (JSC::Interpreter::cti_op_switch_string): + (JSC::Interpreter::cti_op_del_by_val): + (JSC::Interpreter::cti_op_put_getter): + (JSC::Interpreter::cti_op_put_setter): + (JSC::Interpreter::cti_op_new_error): + (JSC::Interpreter::cti_op_debug): + (JSC::Interpreter::cti_vm_throw): + * VM/Machine.h: + * VM/Register.h: + * VM/SamplingTool.cpp: + (JSC::SamplingTool::dump): + * VM/SamplingTool.h: + (JSC::SamplingTool::SamplingTool): + * bytecompiler/CodeGenerator.cpp: + (JSC::BytecodeGenerator::generate): + (JSC::BytecodeGenerator::BytecodeGenerator): + * jsc.cpp: + (runWithScripts): + * masm/X86Assembler.h: + (JSC::AssemblerBuffer::executableCopy): + (JSC::X86Assembler::executableCopy): + * runtime/ExecState.h: + (JSC::ExecState::interpreter): + * runtime/JSCell.h: + * runtime/JSFunction.h: + * runtime/JSGlobalData.cpp: + (JSC::JSGlobalData::JSGlobalData): + * runtime/JSGlobalData.h: + * runtime/JSImmediate.h: + * runtime/JSString.h: + * runtime/JSValue.h: + * runtime/JSVariableObject.h: + * runtime/RegExp.cpp: + (JSC::RegExp::RegExp): + (JSC::RegExp::~RegExp): + (JSC::RegExp::match): + * runtime/RegExp.h: + * wrec/CharacterClassConstructor.cpp: + * wrec/CharacterClassConstructor.h: + * wrec/WREC.cpp: + (JSC::WREC::compileRegExp): + * wrec/WREC.h: + (JSC::WREC::Generator::Generator): + (JSC::WREC::Parser::): + (JSC::WREC::Parser::Parser): + (JSC::WREC::Parser::parseAlternative): + +2008-11-16 Greg Bolsinga <bolsinga@apple.com> + + Reviewed by Darin Adler. + + https://bugs.webkit.org/show_bug.cgi?id=21810 + Remove use of static C++ objects that are destroyed at exit time (destructors) + + Conditionally have the DEFINE_STATIC_LOCAL workaround <rdar://problem/6354696> + (Codegen issue with C++ static reference in gcc build 5465) based upon the compiler + build versions. It will use the: + static T& = *new T; + style for all other compilers. + + * wtf/StdLibExtras.h: + +2008-11-16 Alexey Proskuryakov <ap@webkit.org> + + Reviewed by Dan Bernstein. + + https://bugs.webkit.org/show_bug.cgi?id=22290 + Remove cross-heap GC and MessagePort multi-threading support + + It is broken (and may not be implementable at all), and no longer needed, as we + don't use MessagePorts for communication with workers any more. + + * JavaScriptCore.exp: + * runtime/Collector.cpp: + (JSC::Heap::collect): + * runtime/JSGlobalObject.cpp: + * runtime/JSGlobalObject.h: + Remove hooks for cross-heap GC. + +2008-11-15 Sam Weinig <sam@webkit.org> + + Reviewed by Cameron Zwarich. + + Cleanup jsc command line code a little. + + * jsc.cpp: + (functionQuit): + (main): Use standard exit status macros + (cleanupGlobalData): Factor out cleanup code into this function. + (printUsageStatement): Use standard exit status macros. + +2008-11-15 Sam Weinig <sam@webkit.org> + + Reviewed by Cameron Zwarich. + + Cleanup BytecodeGenerator constructors. + + * bytecompiler/CodeGenerator.cpp: + (JSC::BytecodeGenerator::BytecodeGenerator): + * bytecompiler/CodeGenerator.h: + * parser/Nodes.cpp: + (JSC::ProgramNode::generateBytecode): + +2008-11-15 Darin Adler <darin@apple.com> + + Rubber stamped by Geoff Garen. + + - do the long-planned StructureID -> Structure rename + + * API/JSCallbackConstructor.cpp: + (JSC::JSCallbackConstructor::JSCallbackConstructor): + * API/JSCallbackConstructor.h: + (JSC::JSCallbackConstructor::createStructure): + * API/JSCallbackFunction.h: + (JSC::JSCallbackFunction::createStructure): + * API/JSCallbackObject.h: + (JSC::JSCallbackObject::createStructure): + * API/JSCallbackObjectFunctions.h: + (JSC::::JSCallbackObject): + * API/JSValueRef.cpp: + (JSValueIsInstanceOfConstructor): + * GNUmakefile.am: + * JavaScriptCore.exp: + * JavaScriptCore.pri: + * JavaScriptCore.scons: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: + * JavaScriptCore.xcodeproj/project.pbxproj: + * JavaScriptCoreSources.bkl: + * VM/CTI.cpp: + (JSC::CTI::compileBinaryArithOp): + (JSC::CTI::privateCompileMainPass): + (JSC::CTI::privateCompileGetByIdSelf): + (JSC::CTI::privateCompileGetByIdProto): + (JSC::CTI::privateCompileGetByIdChain): + (JSC::CTI::privateCompilePutByIdReplace): + (JSC::transitionWillNeedStorageRealloc): + (JSC::CTI::privateCompilePutByIdTransition): + (JSC::CTI::patchGetByIdSelf): + (JSC::CTI::patchPutByIdReplace): + * VM/CTI.h: + (JSC::CTI::compileGetByIdSelf): + (JSC::CTI::compileGetByIdProto): + (JSC::CTI::compileGetByIdChain): + (JSC::CTI::compilePutByIdReplace): + (JSC::CTI::compilePutByIdTransition): + * VM/CodeBlock.cpp: + (JSC::CodeBlock::printStructure): + (JSC::CodeBlock::printStructures): + (JSC::CodeBlock::dump): + (JSC::CodeBlock::~CodeBlock): + (JSC::CodeBlock::derefStructures): + (JSC::CodeBlock::refStructures): + * VM/CodeBlock.h: + * VM/Instruction.h: + (JSC::Instruction::Instruction): + (JSC::Instruction::): + * VM/Machine.cpp: + (JSC::jsTypeStringForValue): + (JSC::jsIsObjectType): + (JSC::BytecodeInterpreter::resolveGlobal): + (JSC::BytecodeInterpreter::BytecodeInterpreter): + (JSC::cachePrototypeChain): + (JSC::BytecodeInterpreter::tryCachePutByID): + (JSC::BytecodeInterpreter::uncachePutByID): + (JSC::BytecodeInterpreter::tryCacheGetByID): + (JSC::BytecodeInterpreter::uncacheGetByID): + (JSC::BytecodeInterpreter::privateExecute): + (JSC::BytecodeInterpreter::tryCTICachePutByID): + (JSC::BytecodeInterpreter::tryCTICacheGetByID): + (JSC::BytecodeInterpreter::cti_op_instanceof): + (JSC::BytecodeInterpreter::cti_op_construct_JSConstruct): + (JSC::BytecodeInterpreter::cti_op_resolve_global): + (JSC::BytecodeInterpreter::cti_op_is_undefined): + * runtime/Arguments.h: + (JSC::Arguments::createStructure): + * runtime/ArrayConstructor.cpp: + (JSC::ArrayConstructor::ArrayConstructor): + * runtime/ArrayConstructor.h: + * runtime/ArrayPrototype.cpp: + (JSC::ArrayPrototype::ArrayPrototype): + * runtime/ArrayPrototype.h: + * runtime/BatchedTransitionOptimizer.h: + (JSC::BatchedTransitionOptimizer::BatchedTransitionOptimizer): + (JSC::BatchedTransitionOptimizer::~BatchedTransitionOptimizer): + * runtime/BooleanConstructor.cpp: + (JSC::BooleanConstructor::BooleanConstructor): + * runtime/BooleanConstructor.h: + * runtime/BooleanObject.cpp: + (JSC::BooleanObject::BooleanObject): + * runtime/BooleanObject.h: + * runtime/BooleanPrototype.cpp: + (JSC::BooleanPrototype::BooleanPrototype): + * runtime/BooleanPrototype.h: + * runtime/DateConstructor.cpp: + (JSC::DateConstructor::DateConstructor): + * runtime/DateConstructor.h: + * runtime/DateInstance.cpp: + (JSC::DateInstance::DateInstance): + * runtime/DateInstance.h: + * runtime/DatePrototype.cpp: + (JSC::DatePrototype::DatePrototype): + * runtime/DatePrototype.h: + (JSC::DatePrototype::createStructure): + * runtime/ErrorConstructor.cpp: + (JSC::ErrorConstructor::ErrorConstructor): + * runtime/ErrorConstructor.h: + * runtime/ErrorInstance.cpp: + (JSC::ErrorInstance::ErrorInstance): + * runtime/ErrorInstance.h: + * runtime/ErrorPrototype.cpp: + (JSC::ErrorPrototype::ErrorPrototype): + * runtime/ErrorPrototype.h: + * runtime/FunctionConstructor.cpp: + (JSC::FunctionConstructor::FunctionConstructor): + * runtime/FunctionConstructor.h: + * runtime/FunctionPrototype.cpp: + (JSC::FunctionPrototype::FunctionPrototype): + (JSC::FunctionPrototype::addFunctionProperties): + * runtime/FunctionPrototype.h: + (JSC::FunctionPrototype::createStructure): + * runtime/GlobalEvalFunction.cpp: + (JSC::GlobalEvalFunction::GlobalEvalFunction): + * runtime/GlobalEvalFunction.h: + * runtime/Identifier.h: + * runtime/InternalFunction.cpp: + (JSC::InternalFunction::InternalFunction): + * runtime/InternalFunction.h: + (JSC::InternalFunction::createStructure): + (JSC::InternalFunction::InternalFunction): + * runtime/JSActivation.cpp: + (JSC::JSActivation::JSActivation): + * runtime/JSActivation.h: + (JSC::JSActivation::createStructure): + * runtime/JSArray.cpp: + (JSC::JSArray::JSArray): + * runtime/JSArray.h: + (JSC::JSArray::createStructure): + * runtime/JSCell.h: + (JSC::JSCell::JSCell): + (JSC::JSCell::isObject): + (JSC::JSCell::isString): + (JSC::JSCell::structure): + (JSC::JSValue::needsThisConversion): + * runtime/JSFunction.cpp: + (JSC::JSFunction::construct): + * runtime/JSFunction.h: + (JSC::JSFunction::JSFunction): + (JSC::JSFunction::createStructure): + * runtime/JSGlobalData.cpp: + (JSC::JSGlobalData::JSGlobalData): + (JSC::JSGlobalData::createLeaked): + * runtime/JSGlobalData.h: + * runtime/JSGlobalObject.cpp: + (JSC::markIfNeeded): + (JSC::JSGlobalObject::reset): + * runtime/JSGlobalObject.h: + (JSC::JSGlobalObject::JSGlobalObject): + (JSC::JSGlobalObject::argumentsStructure): + (JSC::JSGlobalObject::arrayStructure): + (JSC::JSGlobalObject::booleanObjectStructure): + (JSC::JSGlobalObject::callbackConstructorStructure): + (JSC::JSGlobalObject::callbackFunctionStructure): + (JSC::JSGlobalObject::callbackObjectStructure): + (JSC::JSGlobalObject::dateStructure): + (JSC::JSGlobalObject::emptyObjectStructure): + (JSC::JSGlobalObject::errorStructure): + (JSC::JSGlobalObject::functionStructure): + (JSC::JSGlobalObject::numberObjectStructure): + (JSC::JSGlobalObject::prototypeFunctionStructure): + (JSC::JSGlobalObject::regExpMatchesArrayStructure): + (JSC::JSGlobalObject::regExpStructure): + (JSC::JSGlobalObject::stringObjectStructure): + (JSC::JSGlobalObject::createStructure): + (JSC::Structure::prototypeForLookup): + * runtime/JSNotAnObject.h: + (JSC::JSNotAnObject::createStructure): + * runtime/JSNumberCell.h: + (JSC::JSNumberCell::createStructure): + (JSC::JSNumberCell::JSNumberCell): + * runtime/JSObject.cpp: + (JSC::JSObject::mark): + (JSC::JSObject::put): + (JSC::JSObject::deleteProperty): + (JSC::JSObject::defineGetter): + (JSC::JSObject::defineSetter): + (JSC::JSObject::getPropertyAttributes): + (JSC::JSObject::getPropertyNames): + (JSC::JSObject::removeDirect): + (JSC::JSObject::createInheritorID): + * runtime/JSObject.h: + (JSC::JSObject::getDirect): + (JSC::JSObject::getDirectLocation): + (JSC::JSObject::hasCustomProperties): + (JSC::JSObject::hasGetterSetterProperties): + (JSC::JSObject::createStructure): + (JSC::JSObject::JSObject): + (JSC::JSObject::~JSObject): + (JSC::JSObject::prototype): + (JSC::JSObject::setPrototype): + (JSC::JSObject::setStructure): + (JSC::JSObject::inheritorID): + (JSC::JSObject::inlineGetOwnPropertySlot): + (JSC::JSObject::getOwnPropertySlotForWrite): + (JSC::JSCell::fastGetOwnPropertySlot): + (JSC::JSObject::putDirect): + (JSC::JSObject::putDirectWithoutTransition): + (JSC::JSObject::transitionTo): + * runtime/JSPropertyNameIterator.h: + (JSC::JSPropertyNameIterator::next): + * runtime/JSStaticScopeObject.h: + (JSC::JSStaticScopeObject::JSStaticScopeObject): + (JSC::JSStaticScopeObject::createStructure): + * runtime/JSString.h: + (JSC::JSString::JSString): + (JSC::JSString::createStructure): + * runtime/JSVariableObject.h: + (JSC::JSVariableObject::JSVariableObject): + * runtime/JSWrapperObject.h: + (JSC::JSWrapperObject::JSWrapperObject): + * runtime/MathObject.cpp: + (JSC::MathObject::MathObject): + * runtime/MathObject.h: + (JSC::MathObject::createStructure): + * runtime/NativeErrorConstructor.cpp: + (JSC::NativeErrorConstructor::NativeErrorConstructor): + * runtime/NativeErrorConstructor.h: + * runtime/NativeErrorPrototype.cpp: + (JSC::NativeErrorPrototype::NativeErrorPrototype): + * runtime/NativeErrorPrototype.h: + * runtime/NumberConstructor.cpp: + (JSC::NumberConstructor::NumberConstructor): + * runtime/NumberConstructor.h: + (JSC::NumberConstructor::createStructure): + * runtime/NumberObject.cpp: + (JSC::NumberObject::NumberObject): + * runtime/NumberObject.h: + * runtime/NumberPrototype.cpp: + (JSC::NumberPrototype::NumberPrototype): + * runtime/NumberPrototype.h: + * runtime/ObjectConstructor.cpp: + (JSC::ObjectConstructor::ObjectConstructor): + * runtime/ObjectConstructor.h: + * runtime/ObjectPrototype.cpp: + (JSC::ObjectPrototype::ObjectPrototype): + * runtime/ObjectPrototype.h: + * runtime/Operations.h: + (JSC::equalSlowCaseInline): + * runtime/PropertyNameArray.h: + (JSC::PropertyNameArrayData::setCachedStructure): + (JSC::PropertyNameArrayData::cachedStructure): + (JSC::PropertyNameArrayData::setCachedPrototypeChain): + (JSC::PropertyNameArrayData::cachedPrototypeChain): + (JSC::PropertyNameArrayData::PropertyNameArrayData): + * runtime/PrototypeFunction.cpp: + (JSC::PrototypeFunction::PrototypeFunction): + * runtime/PrototypeFunction.h: + * runtime/RegExpConstructor.cpp: + (JSC::RegExpConstructor::RegExpConstructor): + * runtime/RegExpConstructor.h: + (JSC::RegExpConstructor::createStructure): + * runtime/RegExpObject.cpp: + (JSC::RegExpObject::RegExpObject): + * runtime/RegExpObject.h: + (JSC::RegExpObject::createStructure): + * runtime/RegExpPrototype.cpp: + (JSC::RegExpPrototype::RegExpPrototype): + * runtime/RegExpPrototype.h: + * runtime/StringConstructor.cpp: + (JSC::StringConstructor::StringConstructor): + * runtime/StringConstructor.h: + * runtime/StringObject.cpp: + (JSC::StringObject::StringObject): + * runtime/StringObject.h: + (JSC::StringObject::createStructure): + * runtime/StringObjectThatMasqueradesAsUndefined.h: + (JSC::StringObjectThatMasqueradesAsUndefined::create): + (JSC::StringObjectThatMasqueradesAsUndefined::StringObjectThatMasqueradesAsUndefined): + (JSC::StringObjectThatMasqueradesAsUndefined::createStructure): + * runtime/StringPrototype.cpp: + (JSC::StringPrototype::StringPrototype): + * runtime/StringPrototype.h: + * runtime/Structure.cpp: Copied from JavaScriptCore/runtime/StructureID.cpp. + (JSC::Structure::dumpStatistics): + (JSC::Structure::Structure): + (JSC::Structure::~Structure): + (JSC::Structure::startIgnoringLeaks): + (JSC::Structure::stopIgnoringLeaks): + (JSC::Structure::materializePropertyMap): + (JSC::Structure::getEnumerablePropertyNames): + (JSC::Structure::clearEnumerationCache): + (JSC::Structure::growPropertyStorageCapacity): + (JSC::Structure::addPropertyTransitionToExistingStructure): + (JSC::Structure::addPropertyTransition): + (JSC::Structure::removePropertyTransition): + (JSC::Structure::changePrototypeTransition): + (JSC::Structure::getterSetterTransition): + (JSC::Structure::toDictionaryTransition): + (JSC::Structure::fromDictionaryTransition): + (JSC::Structure::addPropertyWithoutTransition): + (JSC::Structure::removePropertyWithoutTransition): + (JSC::Structure::createCachedPrototypeChain): + (JSC::Structure::checkConsistency): + (JSC::Structure::copyPropertyTable): + (JSC::Structure::get): + (JSC::Structure::put): + (JSC::Structure::remove): + (JSC::Structure::insertIntoPropertyMapHashTable): + (JSC::Structure::createPropertyMapHashTable): + (JSC::Structure::expandPropertyMapHashTable): + (JSC::Structure::rehashPropertyMapHashTable): + (JSC::Structure::getEnumerablePropertyNamesInternal): + * runtime/Structure.h: Copied from JavaScriptCore/runtime/StructureID.h. + (JSC::Structure::create): + (JSC::Structure::previousID): + (JSC::Structure::setCachedPrototypeChain): + (JSC::Structure::cachedPrototypeChain): + (JSC::Structure::): + (JSC::Structure::get): + * runtime/StructureChain.cpp: Copied from JavaScriptCore/runtime/StructureIDChain.cpp. + (JSC::StructureChain::StructureChain): + (JSC::structureChainsAreEqual): + * runtime/StructureChain.h: Copied from JavaScriptCore/runtime/StructureIDChain.h. + (JSC::StructureChain::create): + (JSC::StructureChain::head): + * runtime/StructureID.cpp: Removed. + * runtime/StructureID.h: Removed. + * runtime/StructureIDChain.cpp: Removed. + * runtime/StructureIDChain.h: Removed. + * runtime/StructureIDTransitionTable.h: Removed. + * runtime/StructureTransitionTable.h: Copied from JavaScriptCore/runtime/StructureIDTransitionTable.h. + +2008-11-15 Darin Adler <darin@apple.com> + + - fix non-WREC build + + * runtime/RegExp.cpp: Put "using namespace WREC" inside #if ENABLE(WREC). + +2008-11-15 Kevin Ollivier <kevino@theolliviers.com> + + Reviewed by Timothy Hatcher. + + As ThreadingNone doesn't implement threads, isMainThread should return true, + not false. + + https://bugs.webkit.org/show_bug.cgi?id=22285 + + * wtf/ThreadingNone.cpp: + (WTF::isMainThread): + +2008-11-15 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Sam Weinig. + + Moved all WREC-related code into WREC.cpp and put it in a WREC namespace. + Removed the WREC prefix from class names. + + * VM/CTI.cpp: + * VM/CTI.h: + * VM/Machine.h: + (JSC::BytecodeInterpreter::assemblerBuffer): + * masm/X86Assembler.h: + * runtime/RegExp.cpp: + (JSC::RegExp::RegExp): + * wrec/CharacterClassConstructor.cpp: + * wrec/CharacterClassConstructor.h: + * wrec/WREC.cpp: + (WREC::GenerateParenthesesNonGreedyFunctor::GenerateParenthesesNonGreedyFunctor): + (WREC::GeneratePatternCharacterFunctor::generateAtom): + (WREC::GeneratePatternCharacterFunctor::backtrack): + (WREC::GenerateCharacterClassFunctor::generateAtom): + (WREC::GenerateCharacterClassFunctor::backtrack): + (WREC::GenerateBackreferenceFunctor::generateAtom): + (WREC::GenerateBackreferenceFunctor::backtrack): + (WREC::GenerateParenthesesNonGreedyFunctor::generateAtom): + (WREC::GenerateParenthesesNonGreedyFunctor::backtrack): + (WREC::Generator::generateBacktrack1): + (WREC::Generator::generateBacktrackBackreference): + (WREC::Generator::generateBackreferenceQuantifier): + (WREC::Generator::generateNonGreedyQuantifier): + (WREC::Generator::generateGreedyQuantifier): + (WREC::Generator::generatePatternCharacter): + (WREC::Generator::generateCharacterClassInvertedRange): + (WREC::Generator::generateCharacterClassInverted): + (WREC::Generator::generateCharacterClass): + (WREC::Generator::generateParentheses): + (WREC::Generator::generateParenthesesNonGreedy): + (WREC::Generator::generateParenthesesResetTrampoline): + (WREC::Generator::generateAssertionBOL): + (WREC::Generator::generateAssertionEOL): + (WREC::Generator::generateAssertionWordBoundary): + (WREC::Generator::generateBackreference): + (WREC::Generator::generateDisjunction): + (WREC::Generator::terminateDisjunction): + (WREC::Parser::parseGreedyQuantifier): + (WREC::Parser::parseQuantifier): + (WREC::Parser::parsePatternCharacterQualifier): + (WREC::Parser::parseCharacterClassQuantifier): + (WREC::Parser::parseBackreferenceQuantifier): + (WREC::Parser::parseParentheses): + (WREC::Parser::parseCharacterClass): + (WREC::Parser::parseOctalEscape): + (WREC::Parser::parseEscape): + (WREC::Parser::parseTerm): + (WREC::Parser::parseDisjunction): + (WREC::compileRegExp): + * wrec/WREC.h: + (WREC::Generator::Generator): + (WREC::Parser::Parser): + (WREC::Parser::parseAlternative): + +2008-11-15 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Sam Weinig. + + Changed another case of "m_jit" to "m_assembler". + + * VM/CTI.cpp: + * wrec/WREC.cpp: + * wrec/WREC.h: + (JSC::WRECGenerator::WRECGenerator): + (JSC::WRECParser::WRECParser): + +2008-11-15 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Sam Weinig. + + Renamed "jit" to "assembler" and, for brevity, replaced *jit.* with __ + using a macro. + + * VM/CTI.cpp: + (JSC::CTI::emitGetVirtualRegister): + (JSC::CTI::emitPutCTIArgFromVirtualRegister): + (JSC::CTI::emitPutCTIArg): + (JSC::CTI::emitGetCTIArg): + (JSC::CTI::emitPutCTIArgConstant): + (JSC::CTI::emitPutCTIParam): + (JSC::CTI::emitGetCTIParam): + (JSC::CTI::emitPutToCallFrameHeader): + (JSC::CTI::emitGetFromCallFrameHeader): + (JSC::CTI::emitPutVirtualRegister): + (JSC::CTI::emitInitRegister): + (JSC::CTI::emitAllocateNumber): + (JSC::CTI::emitNakedCall): + (JSC::CTI::emitNakedFastCall): + (JSC::CTI::emitCTICall): + (JSC::CTI::emitJumpSlowCaseIfNotJSCell): + (JSC::CTI::linkSlowCaseIfNotJSCell): + (JSC::CTI::emitJumpSlowCaseIfNotImmNum): + (JSC::CTI::emitJumpSlowCaseIfNotImmNums): + (JSC::CTI::emitFastArithDeTagImmediate): + (JSC::CTI::emitFastArithDeTagImmediateJumpIfZero): + (JSC::CTI::emitFastArithReTagImmediate): + (JSC::CTI::emitFastArithPotentiallyReTagImmediate): + (JSC::CTI::emitFastArithImmToInt): + (JSC::CTI::emitFastArithIntToImmOrSlowCase): + (JSC::CTI::emitFastArithIntToImmNoCheck): + (JSC::CTI::emitArithIntToImmWithJump): + (JSC::CTI::emitTagAsBoolImmediate): + (JSC::CTI::CTI): + (JSC::CTI::compileOpCallInitializeCallFrame): + (JSC::CTI::compileOpCall): + (JSC::CTI::compileOpStrictEq): + (JSC::CTI::emitSlowScriptCheck): + (JSC::CTI::putDoubleResultToJSNumberCellOrJSImmediate): + (JSC::CTI::compileBinaryArithOp): + (JSC::CTI::compileBinaryArithOpSlowCase): + (JSC::CTI::privateCompileMainPass): + (JSC::CTI::privateCompileLinkPass): + (JSC::CTI::privateCompileSlowCases): + (JSC::CTI::privateCompile): + (JSC::CTI::privateCompileGetByIdSelf): + (JSC::CTI::privateCompileGetByIdProto): + (JSC::CTI::privateCompileGetByIdChain): + (JSC::CTI::privateCompilePutByIdReplace): + (JSC::CTI::privateCompilePutByIdTransition): + (JSC::CTI::privateCompileCTIMachineTrampolines): + (JSC::CTI::privateCompilePatchGetArrayLength): + (JSC::CTI::emitGetVariableObjectRegister): + (JSC::CTI::emitPutVariableObjectRegister): + (JSC::CTI::compileRegExp): + * VM/CTI.h: + * wrec/WREC.cpp: + (JSC::WRECGenerator::generateBacktrack1): + (JSC::WRECGenerator::generateBacktrackBackreference): + (JSC::WRECGenerator::generateBackreferenceQuantifier): + (JSC::WRECGenerator::generateNonGreedyQuantifier): + (JSC::WRECGenerator::generateGreedyQuantifier): + (JSC::WRECGenerator::generatePatternCharacter): + (JSC::WRECGenerator::generateCharacterClassInvertedRange): + (JSC::WRECGenerator::generateCharacterClassInverted): + (JSC::WRECGenerator::generateCharacterClass): + (JSC::WRECGenerator::generateParentheses): + (JSC::WRECGenerator::generateParenthesesNonGreedy): + (JSC::WRECGenerator::generateParenthesesResetTrampoline): + (JSC::WRECGenerator::generateAssertionBOL): + (JSC::WRECGenerator::generateAssertionEOL): + (JSC::WRECGenerator::generateAssertionWordBoundary): + (JSC::WRECGenerator::generateBackreference): + (JSC::WRECGenerator::generateDisjunction): + (JSC::WRECGenerator::terminateDisjunction): + +2008-11-15 Sam Weinig <sam@webkit.org> + + Reviewed by Geoffrey Garen. + + Remove dead method declaration. + + * bytecompiler/CodeGenerator.h: + +2008-11-15 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Sam Weinig. + + Renamed LabelID to Label, Label::isForwardLabel to Label::isForward. + + * VM/LabelID.h: + (JSC::Label::Label): + (JSC::Label::isForward): + * bytecompiler/CodeGenerator.cpp: + (JSC::BytecodeGenerator::newLabel): + (JSC::BytecodeGenerator::emitLabel): + (JSC::BytecodeGenerator::emitJump): + (JSC::BytecodeGenerator::emitJumpIfTrue): + (JSC::BytecodeGenerator::emitJumpIfFalse): + (JSC::BytecodeGenerator::pushFinallyContext): + (JSC::BytecodeGenerator::emitComplexJumpScopes): + (JSC::BytecodeGenerator::emitJumpScopes): + (JSC::BytecodeGenerator::emitNextPropertyName): + (JSC::BytecodeGenerator::emitCatch): + (JSC::BytecodeGenerator::emitJumpSubroutine): + (JSC::prepareJumpTableForImmediateSwitch): + (JSC::prepareJumpTableForCharacterSwitch): + (JSC::prepareJumpTableForStringSwitch): + (JSC::BytecodeGenerator::endSwitch): + * bytecompiler/CodeGenerator.h: + * bytecompiler/LabelScope.h: + (JSC::LabelScope::LabelScope): + (JSC::LabelScope::breakTarget): + (JSC::LabelScope::continueTarget): + * parser/Nodes.cpp: + (JSC::LogicalOpNode::emitBytecode): + (JSC::ConditionalNode::emitBytecode): + (JSC::IfNode::emitBytecode): + (JSC::IfElseNode::emitBytecode): + (JSC::DoWhileNode::emitBytecode): + (JSC::WhileNode::emitBytecode): + (JSC::ForNode::emitBytecode): + (JSC::ForInNode::emitBytecode): + (JSC::ReturnNode::emitBytecode): + (JSC::CaseBlockNode::emitBytecodeForBlock): + (JSC::TryNode::emitBytecode): + +2008-11-15 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Sam Weinig. + + Renamed JITCodeBuffer to AssemblerBuffer and renamed its data members + to be more like the rest of our buffer classes, with a size and a + capacity. + + Added an assert in the unchecked put case to match the test in the checked + put case. + + Changed a C-style cast to a C++-style cast. + + Renamed MAX_INSTRUCTION_SIZE to maxInstructionSize. + + * VM/CTI.cpp: + (JSC::CTI::CTI): + (JSC::CTI::compileRegExp): + * VM/Machine.cpp: + (JSC::BytecodeInterpreter::BytecodeInterpreter): + * VM/Machine.h: + (JSC::BytecodeInterpreter::assemblerBuffer): + * masm/X86Assembler.h: + (JSC::AssemblerBuffer::AssemblerBuffer): + (JSC::AssemblerBuffer::~AssemblerBuffer): + (JSC::AssemblerBuffer::ensureSpace): + (JSC::AssemblerBuffer::isAligned): + (JSC::AssemblerBuffer::putByteUnchecked): + (JSC::AssemblerBuffer::putByte): + (JSC::AssemblerBuffer::putShortUnchecked): + (JSC::AssemblerBuffer::putShort): + (JSC::AssemblerBuffer::putIntUnchecked): + (JSC::AssemblerBuffer::putInt): + (JSC::AssemblerBuffer::data): + (JSC::AssemblerBuffer::size): + (JSC::AssemblerBuffer::reset): + (JSC::AssemblerBuffer::copy): + (JSC::AssemblerBuffer::grow): + (JSC::X86Assembler::): + (JSC::X86Assembler::X86Assembler): + (JSC::X86Assembler::testl_i32r): + (JSC::X86Assembler::movl_mr): + (JSC::X86Assembler::movl_rm): + (JSC::X86Assembler::movl_i32m): + (JSC::X86Assembler::emitCall): + (JSC::X86Assembler::label): + (JSC::X86Assembler::emitUnlinkedJmp): + (JSC::X86Assembler::emitUnlinkedJne): + (JSC::X86Assembler::emitUnlinkedJe): + (JSC::X86Assembler::emitUnlinkedJl): + (JSC::X86Assembler::emitUnlinkedJb): + (JSC::X86Assembler::emitUnlinkedJle): + (JSC::X86Assembler::emitUnlinkedJbe): + (JSC::X86Assembler::emitUnlinkedJge): + (JSC::X86Assembler::emitUnlinkedJg): + (JSC::X86Assembler::emitUnlinkedJa): + (JSC::X86Assembler::emitUnlinkedJae): + (JSC::X86Assembler::emitUnlinkedJo): + (JSC::X86Assembler::emitUnlinkedJp): + (JSC::X86Assembler::emitUnlinkedJs): + (JSC::X86Assembler::link): + (JSC::X86Assembler::emitModRm_rr): + (JSC::X86Assembler::emitModRm_rm): + (JSC::X86Assembler::emitModRm_opr): + +2008-11-15 Geoffrey Garen <ggaren@apple.com> + + Suggested by Maciej Stachowiak. + + Reverted most "opcode" => "bytecode" renames. We use "bytecode" as a + mass noun to refer to a stream of instructions. Each instruction may be + an opcode or an operand. + + * VM/CTI.cpp: + (JSC::CTI::emitCTICall): + (JSC::CTI::compileOpCall): + (JSC::CTI::compileBinaryArithOp): + (JSC::CTI::compileBinaryArithOpSlowCase): + (JSC::CTI::privateCompileMainPass): + (JSC::CTI::privateCompileSlowCases): + (JSC::CTI::privateCompile): + * VM/CTI.h: + * VM/CodeBlock.cpp: + (JSC::CodeBlock::printStructureIDs): + (JSC::CodeBlock::dump): + (JSC::CodeBlock::derefStructureIDs): + (JSC::CodeBlock::refStructureIDs): + * VM/CodeBlock.h: + * VM/ExceptionHelpers.cpp: + (JSC::createNotAnObjectError): + * VM/Instruction.h: + (JSC::Instruction::Instruction): + (JSC::Instruction::): + * VM/Machine.cpp: + (JSC::BytecodeInterpreter::isOpcode): + (JSC::BytecodeInterpreter::throwException): + (JSC::BytecodeInterpreter::tryCachePutByID): + (JSC::BytecodeInterpreter::uncachePutByID): + (JSC::BytecodeInterpreter::tryCacheGetByID): + (JSC::BytecodeInterpreter::uncacheGetByID): + (JSC::BytecodeInterpreter::privateExecute): + (JSC::BytecodeInterpreter::tryCTICachePutByID): + (JSC::BytecodeInterpreter::tryCTICacheGetByID): + * VM/Machine.h: + (JSC::BytecodeInterpreter::getOpcode): + (JSC::BytecodeInterpreter::getOpcodeID): + (JSC::BytecodeInterpreter::isCallBytecode): + * VM/Opcode.cpp: + (JSC::): + (JSC::OpcodeStats::OpcodeStats): + (JSC::compareOpcodeIndices): + (JSC::compareOpcodePairIndices): + (JSC::OpcodeStats::~OpcodeStats): + (JSC::OpcodeStats::recordInstruction): + (JSC::OpcodeStats::resetLastInstruction): + * VM/Opcode.h: + (JSC::): + (JSC::padOpcodeName): + * VM/SamplingTool.cpp: + (JSC::ScopeSampleRecord::sample): + (JSC::SamplingTool::run): + (JSC::compareOpcodeIndicesSampling): + (JSC::SamplingTool::dump): + * VM/SamplingTool.h: + (JSC::ScopeSampleRecord::ScopeSampleRecord): + (JSC::SamplingTool::SamplingTool): + * bytecompiler/CodeGenerator.cpp: + (JSC::BytecodeGenerator::BytecodeGenerator): + (JSC::BytecodeGenerator::emitLabel): + (JSC::BytecodeGenerator::emitOpcode): + (JSC::BytecodeGenerator::emitJump): + (JSC::BytecodeGenerator::emitJumpIfTrue): + (JSC::BytecodeGenerator::emitJumpIfFalse): + (JSC::BytecodeGenerator::emitMove): + (JSC::BytecodeGenerator::emitUnaryOp): + (JSC::BytecodeGenerator::emitPreInc): + (JSC::BytecodeGenerator::emitPreDec): + (JSC::BytecodeGenerator::emitPostInc): + (JSC::BytecodeGenerator::emitPostDec): + (JSC::BytecodeGenerator::emitBinaryOp): + (JSC::BytecodeGenerator::emitEqualityOp): + (JSC::BytecodeGenerator::emitUnexpectedLoad): + (JSC::BytecodeGenerator::emitInstanceOf): + (JSC::BytecodeGenerator::emitResolve): + (JSC::BytecodeGenerator::emitGetScopedVar): + (JSC::BytecodeGenerator::emitPutScopedVar): + (JSC::BytecodeGenerator::emitResolveBase): + (JSC::BytecodeGenerator::emitResolveWithBase): + (JSC::BytecodeGenerator::emitResolveFunction): + (JSC::BytecodeGenerator::emitGetById): + (JSC::BytecodeGenerator::emitPutById): + (JSC::BytecodeGenerator::emitPutGetter): + (JSC::BytecodeGenerator::emitPutSetter): + (JSC::BytecodeGenerator::emitDeleteById): + (JSC::BytecodeGenerator::emitGetByVal): + (JSC::BytecodeGenerator::emitPutByVal): + (JSC::BytecodeGenerator::emitDeleteByVal): + (JSC::BytecodeGenerator::emitPutByIndex): + (JSC::BytecodeGenerator::emitNewObject): + (JSC::BytecodeGenerator::emitNewArray): + (JSC::BytecodeGenerator::emitNewFunction): + (JSC::BytecodeGenerator::emitNewRegExp): + (JSC::BytecodeGenerator::emitNewFunctionExpression): + (JSC::BytecodeGenerator::emitCall): + (JSC::BytecodeGenerator::emitReturn): + (JSC::BytecodeGenerator::emitUnaryNoDstOp): + (JSC::BytecodeGenerator::emitConstruct): + (JSC::BytecodeGenerator::emitPopScope): + (JSC::BytecodeGenerator::emitDebugHook): + (JSC::BytecodeGenerator::emitComplexJumpScopes): + (JSC::BytecodeGenerator::emitJumpScopes): + (JSC::BytecodeGenerator::emitNextPropertyName): + (JSC::BytecodeGenerator::emitCatch): + (JSC::BytecodeGenerator::emitNewError): + (JSC::BytecodeGenerator::emitJumpSubroutine): + (JSC::BytecodeGenerator::emitSubroutineReturn): + (JSC::BytecodeGenerator::emitPushNewScope): + (JSC::BytecodeGenerator::beginSwitch): + * bytecompiler/CodeGenerator.h: + * jsc.cpp: + (runWithScripts): + * masm/X86Assembler.h: + (JSC::X86Assembler::): + (JSC::X86Assembler::emitModRm_opr): + (JSC::X86Assembler::emitModRm_opr_Unchecked): + (JSC::X86Assembler::emitModRm_opm): + (JSC::X86Assembler::emitModRm_opm_Unchecked): + (JSC::X86Assembler::emitModRm_opmsib): + * parser/Nodes.cpp: + (JSC::UnaryOpNode::emitBytecode): + (JSC::BinaryOpNode::emitBytecode): + (JSC::ReverseBinaryOpNode::emitBytecode): + (JSC::ThrowableBinaryOpNode::emitBytecode): + (JSC::emitReadModifyAssignment): + (JSC::ScopeNode::ScopeNode): + * parser/Nodes.h: + (JSC::UnaryPlusNode::): + (JSC::NegateNode::): + (JSC::BitwiseNotNode::): + (JSC::LogicalNotNode::): + (JSC::MultNode::): + (JSC::DivNode::): + (JSC::ModNode::): + (JSC::AddNode::): + (JSC::SubNode::): + (JSC::LeftShiftNode::): + (JSC::RightShiftNode::): + (JSC::UnsignedRightShiftNode::): + (JSC::LessNode::): + (JSC::GreaterNode::): + (JSC::LessEqNode::): + (JSC::GreaterEqNode::): + (JSC::InstanceOfNode::): + (JSC::InNode::): + (JSC::EqualNode::): + (JSC::NotEqualNode::): + (JSC::StrictEqualNode::): + (JSC::NotStrictEqualNode::): + (JSC::BitAndNode::): + (JSC::BitOrNode::): + (JSC::BitXOrNode::): + * runtime/StructureID.cpp: + (JSC::StructureID::fromDictionaryTransition): + * wtf/Platform.h: + +2008-11-15 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Sam Weinig. + + Renames: + + CodeGenerator => BytecodeGenerator + emitCodeForBlock => emitBytecodeForBlock + generatedByteCode => generatedBytecode + generateCode => generateBytecode + + * JavaScriptCore.exp: + * bytecompiler/CodeGenerator.cpp: + (JSC::BytecodeGenerator::setDumpsGeneratedCode): + (JSC::BytecodeGenerator::generate): + (JSC::BytecodeGenerator::addVar): + (JSC::BytecodeGenerator::addGlobalVar): + (JSC::BytecodeGenerator::allocateConstants): + (JSC::BytecodeGenerator::BytecodeGenerator): + (JSC::BytecodeGenerator::addParameter): + (JSC::BytecodeGenerator::registerFor): + (JSC::BytecodeGenerator::constRegisterFor): + (JSC::BytecodeGenerator::isLocal): + (JSC::BytecodeGenerator::isLocalConstant): + (JSC::BytecodeGenerator::newRegister): + (JSC::BytecodeGenerator::newTemporary): + (JSC::BytecodeGenerator::highestUsedRegister): + (JSC::BytecodeGenerator::newLabelScope): + (JSC::BytecodeGenerator::newLabel): + (JSC::BytecodeGenerator::emitLabel): + (JSC::BytecodeGenerator::emitBytecode): + (JSC::BytecodeGenerator::retrieveLastBinaryOp): + (JSC::BytecodeGenerator::retrieveLastUnaryOp): + (JSC::BytecodeGenerator::rewindBinaryOp): + (JSC::BytecodeGenerator::rewindUnaryOp): + (JSC::BytecodeGenerator::emitJump): + (JSC::BytecodeGenerator::emitJumpIfTrue): + (JSC::BytecodeGenerator::emitJumpIfFalse): + (JSC::BytecodeGenerator::addConstant): + (JSC::BytecodeGenerator::addUnexpectedConstant): + (JSC::BytecodeGenerator::addRegExp): + (JSC::BytecodeGenerator::emitMove): + (JSC::BytecodeGenerator::emitUnaryOp): + (JSC::BytecodeGenerator::emitPreInc): + (JSC::BytecodeGenerator::emitPreDec): + (JSC::BytecodeGenerator::emitPostInc): + (JSC::BytecodeGenerator::emitPostDec): + (JSC::BytecodeGenerator::emitBinaryOp): + (JSC::BytecodeGenerator::emitEqualityOp): + (JSC::BytecodeGenerator::emitLoad): + (JSC::BytecodeGenerator::emitUnexpectedLoad): + (JSC::BytecodeGenerator::findScopedProperty): + (JSC::BytecodeGenerator::emitInstanceOf): + (JSC::BytecodeGenerator::emitResolve): + (JSC::BytecodeGenerator::emitGetScopedVar): + (JSC::BytecodeGenerator::emitPutScopedVar): + (JSC::BytecodeGenerator::emitResolveBase): + (JSC::BytecodeGenerator::emitResolveWithBase): + (JSC::BytecodeGenerator::emitResolveFunction): + (JSC::BytecodeGenerator::emitGetById): + (JSC::BytecodeGenerator::emitPutById): + (JSC::BytecodeGenerator::emitPutGetter): + (JSC::BytecodeGenerator::emitPutSetter): + (JSC::BytecodeGenerator::emitDeleteById): + (JSC::BytecodeGenerator::emitGetByVal): + (JSC::BytecodeGenerator::emitPutByVal): + (JSC::BytecodeGenerator::emitDeleteByVal): + (JSC::BytecodeGenerator::emitPutByIndex): + (JSC::BytecodeGenerator::emitNewObject): + (JSC::BytecodeGenerator::emitNewArray): + (JSC::BytecodeGenerator::emitNewFunction): + (JSC::BytecodeGenerator::emitNewRegExp): + (JSC::BytecodeGenerator::emitNewFunctionExpression): + (JSC::BytecodeGenerator::emitCall): + (JSC::BytecodeGenerator::emitCallEval): + (JSC::BytecodeGenerator::emitReturn): + (JSC::BytecodeGenerator::emitUnaryNoDstOp): + (JSC::BytecodeGenerator::emitConstruct): + (JSC::BytecodeGenerator::emitPushScope): + (JSC::BytecodeGenerator::emitPopScope): + (JSC::BytecodeGenerator::emitDebugHook): + (JSC::BytecodeGenerator::pushFinallyContext): + (JSC::BytecodeGenerator::popFinallyContext): + (JSC::BytecodeGenerator::breakTarget): + (JSC::BytecodeGenerator::continueTarget): + (JSC::BytecodeGenerator::emitComplexJumpScopes): + (JSC::BytecodeGenerator::emitJumpScopes): + (JSC::BytecodeGenerator::emitNextPropertyName): + (JSC::BytecodeGenerator::emitCatch): + (JSC::BytecodeGenerator::emitNewError): + (JSC::BytecodeGenerator::emitJumpSubroutine): + (JSC::BytecodeGenerator::emitSubroutineReturn): + (JSC::BytecodeGenerator::emitPushNewScope): + (JSC::BytecodeGenerator::beginSwitch): + (JSC::BytecodeGenerator::endSwitch): + (JSC::BytecodeGenerator::emitThrowExpressionTooDeepException): + * bytecompiler/CodeGenerator.h: + * jsc.cpp: + (runWithScripts): + * parser/Nodes.cpp: + (JSC::ThrowableExpressionData::emitThrowError): + (JSC::NullNode::emitBytecode): + (JSC::BooleanNode::emitBytecode): + (JSC::NumberNode::emitBytecode): + (JSC::StringNode::emitBytecode): + (JSC::RegExpNode::emitBytecode): + (JSC::ThisNode::emitBytecode): + (JSC::ResolveNode::isPure): + (JSC::ResolveNode::emitBytecode): + (JSC::ArrayNode::emitBytecode): + (JSC::ObjectLiteralNode::emitBytecode): + (JSC::PropertyListNode::emitBytecode): + (JSC::BracketAccessorNode::emitBytecode): + (JSC::DotAccessorNode::emitBytecode): + (JSC::ArgumentListNode::emitBytecode): + (JSC::NewExprNode::emitBytecode): + (JSC::EvalFunctionCallNode::emitBytecode): + (JSC::FunctionCallValueNode::emitBytecode): + (JSC::FunctionCallResolveNode::emitBytecode): + (JSC::FunctionCallBracketNode::emitBytecode): + (JSC::FunctionCallDotNode::emitBytecode): + (JSC::emitPreIncOrDec): + (JSC::emitPostIncOrDec): + (JSC::PostfixResolveNode::emitBytecode): + (JSC::PostfixBracketNode::emitBytecode): + (JSC::PostfixDotNode::emitBytecode): + (JSC::PostfixErrorNode::emitBytecode): + (JSC::DeleteResolveNode::emitBytecode): + (JSC::DeleteBracketNode::emitBytecode): + (JSC::DeleteDotNode::emitBytecode): + (JSC::DeleteValueNode::emitBytecode): + (JSC::VoidNode::emitBytecode): + (JSC::TypeOfResolveNode::emitBytecode): + (JSC::TypeOfValueNode::emitBytecode): + (JSC::PrefixResolveNode::emitBytecode): + (JSC::PrefixBracketNode::emitBytecode): + (JSC::PrefixDotNode::emitBytecode): + (JSC::PrefixErrorNode::emitBytecode): + (JSC::UnaryOpNode::emitBytecode): + (JSC::BinaryOpNode::emitBytecode): + (JSC::EqualNode::emitBytecode): + (JSC::StrictEqualNode::emitBytecode): + (JSC::ReverseBinaryOpNode::emitBytecode): + (JSC::ThrowableBinaryOpNode::emitBytecode): + (JSC::InstanceOfNode::emitBytecode): + (JSC::LogicalOpNode::emitBytecode): + (JSC::ConditionalNode::emitBytecode): + (JSC::emitReadModifyAssignment): + (JSC::ReadModifyResolveNode::emitBytecode): + (JSC::AssignResolveNode::emitBytecode): + (JSC::AssignDotNode::emitBytecode): + (JSC::ReadModifyDotNode::emitBytecode): + (JSC::AssignErrorNode::emitBytecode): + (JSC::AssignBracketNode::emitBytecode): + (JSC::ReadModifyBracketNode::emitBytecode): + (JSC::CommaNode::emitBytecode): + (JSC::ConstDeclNode::emitCodeSingle): + (JSC::ConstDeclNode::emitBytecode): + (JSC::ConstStatementNode::emitBytecode): + (JSC::statementListEmitCode): + (JSC::BlockNode::emitBytecode): + (JSC::EmptyStatementNode::emitBytecode): + (JSC::DebuggerStatementNode::emitBytecode): + (JSC::ExprStatementNode::emitBytecode): + (JSC::VarStatementNode::emitBytecode): + (JSC::IfNode::emitBytecode): + (JSC::IfElseNode::emitBytecode): + (JSC::DoWhileNode::emitBytecode): + (JSC::WhileNode::emitBytecode): + (JSC::ForNode::emitBytecode): + (JSC::ForInNode::emitBytecode): + (JSC::ContinueNode::emitBytecode): + (JSC::BreakNode::emitBytecode): + (JSC::ReturnNode::emitBytecode): + (JSC::WithNode::emitBytecode): + (JSC::CaseBlockNode::emitBytecodeForBlock): + (JSC::SwitchNode::emitBytecode): + (JSC::LabelNode::emitBytecode): + (JSC::ThrowNode::emitBytecode): + (JSC::TryNode::emitBytecode): + (JSC::EvalNode::emitBytecode): + (JSC::EvalNode::generateBytecode): + (JSC::FunctionBodyNode::generateBytecode): + (JSC::FunctionBodyNode::emitBytecode): + (JSC::ProgramNode::emitBytecode): + (JSC::ProgramNode::generateBytecode): + (JSC::FuncDeclNode::emitBytecode): + (JSC::FuncExprNode::emitBytecode): + * parser/Nodes.h: + (JSC::ExpressionNode::): + (JSC::BooleanNode::): + (JSC::NumberNode::): + (JSC::StringNode::): + (JSC::ProgramNode::): + (JSC::EvalNode::): + (JSC::FunctionBodyNode::): + * runtime/Arguments.h: + (JSC::Arguments::getArgumentsData): + (JSC::JSActivation::copyRegisters): + * runtime/JSActivation.cpp: + (JSC::JSActivation::mark): + * runtime/JSActivation.h: + (JSC::JSActivation::JSActivationData::JSActivationData): + * runtime/JSFunction.cpp: + (JSC::JSFunction::~JSFunction): + +2008-11-15 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Sam Weinig. + + Renamed all forms of "byte code" "opcode" "op code" "code" "bitcode" + etc. to "bytecode". + + * VM/CTI.cpp: + (JSC::CTI::printBytecodeOperandTypes): + (JSC::CTI::emitAllocateNumber): + (JSC::CTI::emitNakedCall): + (JSC::CTI::emitNakedFastCall): + (JSC::CTI::emitCTICall): + (JSC::CTI::emitJumpSlowCaseIfNotJSCell): + (JSC::CTI::emitJumpSlowCaseIfNotImmNum): + (JSC::CTI::emitJumpSlowCaseIfNotImmNums): + (JSC::CTI::emitFastArithIntToImmOrSlowCase): + (JSC::CTI::compileOpCall): + (JSC::CTI::emitSlowScriptCheck): + (JSC::CTI::compileBinaryArithOp): + (JSC::CTI::compileBinaryArithOpSlowCase): + (JSC::CTI::privateCompileMainPass): + (JSC::CTI::privateCompileSlowCases): + (JSC::CTI::privateCompile): + * VM/CTI.h: + (JSC::CallRecord::CallRecord): + (JSC::SwitchRecord::SwitchRecord): + * VM/CodeBlock.cpp: + (JSC::CodeBlock::printStructureIDs): + (JSC::CodeBlock::dump): + (JSC::CodeBlock::~CodeBlock): + (JSC::CodeBlock::derefStructureIDs): + (JSC::CodeBlock::refStructureIDs): + * VM/CodeBlock.h: + (JSC::StructureStubInfo::StructureStubInfo): + * VM/ExceptionHelpers.cpp: + (JSC::createNotAnObjectError): + * VM/Instruction.h: + (JSC::Instruction::Instruction): + (JSC::Instruction::): + * VM/Machine.cpp: + (JSC::BytecodeInterpreter::isBytecode): + (JSC::BytecodeInterpreter::throwException): + (JSC::BytecodeInterpreter::execute): + (JSC::BytecodeInterpreter::tryCachePutByID): + (JSC::BytecodeInterpreter::uncachePutByID): + (JSC::BytecodeInterpreter::tryCacheGetByID): + (JSC::BytecodeInterpreter::uncacheGetByID): + (JSC::BytecodeInterpreter::privateExecute): + (JSC::BytecodeInterpreter::tryCTICachePutByID): + (JSC::BytecodeInterpreter::tryCTICacheGetByID): + (JSC::BytecodeInterpreter::cti_op_call_JSFunction): + (JSC::BytecodeInterpreter::cti_vm_dontLazyLinkCall): + (JSC::BytecodeInterpreter::cti_vm_lazyLinkCall): + * VM/Machine.h: + (JSC::BytecodeInterpreter::getBytecode): + (JSC::BytecodeInterpreter::getBytecodeID): + (JSC::BytecodeInterpreter::isCallBytecode): + * VM/Opcode.cpp: + (JSC::): + (JSC::BytecodeStats::BytecodeStats): + (JSC::compareBytecodeIndices): + (JSC::compareBytecodePairIndices): + (JSC::BytecodeStats::~BytecodeStats): + (JSC::BytecodeStats::recordInstruction): + (JSC::BytecodeStats::resetLastInstruction): + * VM/Opcode.h: + (JSC::): + (JSC::padBytecodeName): + * VM/SamplingTool.cpp: + (JSC::ScopeSampleRecord::sample): + (JSC::SamplingTool::run): + (JSC::compareBytecodeIndicesSampling): + (JSC::SamplingTool::dump): + * VM/SamplingTool.h: + (JSC::ScopeSampleRecord::ScopeSampleRecord): + (JSC::SamplingTool::SamplingTool): + * bytecompiler/CodeGenerator.cpp: + (JSC::CodeGenerator::generate): + (JSC::CodeGenerator::CodeGenerator): + (JSC::CodeGenerator::emitLabel): + (JSC::CodeGenerator::emitBytecode): + (JSC::CodeGenerator::emitJump): + (JSC::CodeGenerator::emitJumpIfTrue): + (JSC::CodeGenerator::emitJumpIfFalse): + (JSC::CodeGenerator::emitMove): + (JSC::CodeGenerator::emitUnaryOp): + (JSC::CodeGenerator::emitPreInc): + (JSC::CodeGenerator::emitPreDec): + (JSC::CodeGenerator::emitPostInc): + (JSC::CodeGenerator::emitPostDec): + (JSC::CodeGenerator::emitBinaryOp): + (JSC::CodeGenerator::emitEqualityOp): + (JSC::CodeGenerator::emitUnexpectedLoad): + (JSC::CodeGenerator::emitInstanceOf): + (JSC::CodeGenerator::emitResolve): + (JSC::CodeGenerator::emitGetScopedVar): + (JSC::CodeGenerator::emitPutScopedVar): + (JSC::CodeGenerator::emitResolveBase): + (JSC::CodeGenerator::emitResolveWithBase): + (JSC::CodeGenerator::emitResolveFunction): + (JSC::CodeGenerator::emitGetById): + (JSC::CodeGenerator::emitPutById): + (JSC::CodeGenerator::emitPutGetter): + (JSC::CodeGenerator::emitPutSetter): + (JSC::CodeGenerator::emitDeleteById): + (JSC::CodeGenerator::emitGetByVal): + (JSC::CodeGenerator::emitPutByVal): + (JSC::CodeGenerator::emitDeleteByVal): + (JSC::CodeGenerator::emitPutByIndex): + (JSC::CodeGenerator::emitNewObject): + (JSC::CodeGenerator::emitNewArray): + (JSC::CodeGenerator::emitNewFunction): + (JSC::CodeGenerator::emitNewRegExp): + (JSC::CodeGenerator::emitNewFunctionExpression): + (JSC::CodeGenerator::emitCall): + (JSC::CodeGenerator::emitReturn): + (JSC::CodeGenerator::emitUnaryNoDstOp): + (JSC::CodeGenerator::emitConstruct): + (JSC::CodeGenerator::emitPopScope): + (JSC::CodeGenerator::emitDebugHook): + (JSC::CodeGenerator::emitComplexJumpScopes): + (JSC::CodeGenerator::emitJumpScopes): + (JSC::CodeGenerator::emitNextPropertyName): + (JSC::CodeGenerator::emitCatch): + (JSC::CodeGenerator::emitNewError): + (JSC::CodeGenerator::emitJumpSubroutine): + (JSC::CodeGenerator::emitSubroutineReturn): + (JSC::CodeGenerator::emitPushNewScope): + (JSC::CodeGenerator::beginSwitch): + (JSC::CodeGenerator::endSwitch): + * bytecompiler/CodeGenerator.h: + (JSC::CodeGenerator::emitNode): + * jsc.cpp: + (runWithScripts): + * masm/X86Assembler.h: + (JSC::X86Assembler::): + (JSC::X86Assembler::emitModRm_opr): + (JSC::X86Assembler::emitModRm_opr_Unchecked): + (JSC::X86Assembler::emitModRm_opm): + (JSC::X86Assembler::emitModRm_opm_Unchecked): + (JSC::X86Assembler::emitModRm_opmsib): + * parser/Nodes.cpp: + (JSC::NullNode::emitBytecode): + (JSC::BooleanNode::emitBytecode): + (JSC::NumberNode::emitBytecode): + (JSC::StringNode::emitBytecode): + (JSC::RegExpNode::emitBytecode): + (JSC::ThisNode::emitBytecode): + (JSC::ResolveNode::emitBytecode): + (JSC::ArrayNode::emitBytecode): + (JSC::ObjectLiteralNode::emitBytecode): + (JSC::PropertyListNode::emitBytecode): + (JSC::BracketAccessorNode::emitBytecode): + (JSC::DotAccessorNode::emitBytecode): + (JSC::ArgumentListNode::emitBytecode): + (JSC::NewExprNode::emitBytecode): + (JSC::EvalFunctionCallNode::emitBytecode): + (JSC::FunctionCallValueNode::emitBytecode): + (JSC::FunctionCallResolveNode::emitBytecode): + (JSC::FunctionCallBracketNode::emitBytecode): + (JSC::FunctionCallDotNode::emitBytecode): + (JSC::PostfixResolveNode::emitBytecode): + (JSC::PostfixBracketNode::emitBytecode): + (JSC::PostfixDotNode::emitBytecode): + (JSC::PostfixErrorNode::emitBytecode): + (JSC::DeleteResolveNode::emitBytecode): + (JSC::DeleteBracketNode::emitBytecode): + (JSC::DeleteDotNode::emitBytecode): + (JSC::DeleteValueNode::emitBytecode): + (JSC::VoidNode::emitBytecode): + (JSC::TypeOfResolveNode::emitBytecode): + (JSC::TypeOfValueNode::emitBytecode): + (JSC::PrefixResolveNode::emitBytecode): + (JSC::PrefixBracketNode::emitBytecode): + (JSC::PrefixDotNode::emitBytecode): + (JSC::PrefixErrorNode::emitBytecode): + (JSC::UnaryOpNode::emitBytecode): + (JSC::BinaryOpNode::emitBytecode): + (JSC::EqualNode::emitBytecode): + (JSC::StrictEqualNode::emitBytecode): + (JSC::ReverseBinaryOpNode::emitBytecode): + (JSC::ThrowableBinaryOpNode::emitBytecode): + (JSC::InstanceOfNode::emitBytecode): + (JSC::LogicalOpNode::emitBytecode): + (JSC::ConditionalNode::emitBytecode): + (JSC::emitReadModifyAssignment): + (JSC::ReadModifyResolveNode::emitBytecode): + (JSC::AssignResolveNode::emitBytecode): + (JSC::AssignDotNode::emitBytecode): + (JSC::ReadModifyDotNode::emitBytecode): + (JSC::AssignErrorNode::emitBytecode): + (JSC::AssignBracketNode::emitBytecode): + (JSC::ReadModifyBracketNode::emitBytecode): + (JSC::CommaNode::emitBytecode): + (JSC::ConstDeclNode::emitBytecode): + (JSC::ConstStatementNode::emitBytecode): + (JSC::BlockNode::emitBytecode): + (JSC::EmptyStatementNode::emitBytecode): + (JSC::DebuggerStatementNode::emitBytecode): + (JSC::ExprStatementNode::emitBytecode): + (JSC::VarStatementNode::emitBytecode): + (JSC::IfNode::emitBytecode): + (JSC::IfElseNode::emitBytecode): + (JSC::DoWhileNode::emitBytecode): + (JSC::WhileNode::emitBytecode): + (JSC::ForNode::emitBytecode): + (JSC::ForInNode::emitBytecode): + (JSC::ContinueNode::emitBytecode): + (JSC::BreakNode::emitBytecode): + (JSC::ReturnNode::emitBytecode): + (JSC::WithNode::emitBytecode): + (JSC::SwitchNode::emitBytecode): + (JSC::LabelNode::emitBytecode): + (JSC::ThrowNode::emitBytecode): + (JSC::TryNode::emitBytecode): + (JSC::ScopeNode::ScopeNode): + (JSC::EvalNode::emitBytecode): + (JSC::FunctionBodyNode::emitBytecode): + (JSC::ProgramNode::emitBytecode): + (JSC::FuncDeclNode::emitBytecode): + (JSC::FuncExprNode::emitBytecode): + * parser/Nodes.h: + (JSC::UnaryPlusNode::): + (JSC::NegateNode::): + (JSC::BitwiseNotNode::): + (JSC::LogicalNotNode::): + (JSC::MultNode::): + (JSC::DivNode::): + (JSC::ModNode::): + (JSC::AddNode::): + (JSC::SubNode::): + (JSC::LeftShiftNode::): + (JSC::RightShiftNode::): + (JSC::UnsignedRightShiftNode::): + (JSC::LessNode::): + (JSC::GreaterNode::): + (JSC::LessEqNode::): + (JSC::GreaterEqNode::): + (JSC::InstanceOfNode::): + (JSC::InNode::): + (JSC::EqualNode::): + (JSC::NotEqualNode::): + (JSC::StrictEqualNode::): + (JSC::NotStrictEqualNode::): + (JSC::BitAndNode::): + (JSC::BitOrNode::): + (JSC::BitXOrNode::): + (JSC::ProgramNode::): + (JSC::EvalNode::): + (JSC::FunctionBodyNode::): + * runtime/JSNotAnObject.h: + * runtime/StructureID.cpp: + (JSC::StructureID::fromDictionaryTransition): + * wtf/Platform.h: + +2008-11-15 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Sam Weinig. + + Renamed Machine to BytecodeInterpreter. + + Nixed the Interpreter class, and changed its two functions to stand-alone + functions. + + * JavaScriptCore.exp: + * VM/CTI.cpp: + (JSC::): + (JSC::CTI::emitCTICall): + (JSC::CTI::CTI): + (JSC::CTI::compileOpCall): + (JSC::CTI::emitSlowScriptCheck): + (JSC::CTI::compileBinaryArithOpSlowCase): + (JSC::CTI::privateCompileMainPass): + (JSC::CTI::privateCompileSlowCases): + (JSC::CTI::privateCompile): + (JSC::CTI::privateCompileGetByIdSelf): + (JSC::CTI::privateCompileGetByIdProto): + (JSC::CTI::privateCompileGetByIdChain): + (JSC::CTI::privateCompilePutByIdReplace): + (JSC::CTI::privateCompilePutByIdTransition): + (JSC::CTI::privateCompileCTIMachineTrampolines): + (JSC::CTI::freeCTIMachineTrampolines): + (JSC::CTI::patchGetByIdSelf): + (JSC::CTI::patchPutByIdReplace): + (JSC::CTI::privateCompilePatchGetArrayLength): + (JSC::CTI::compileRegExp): + * VM/CTI.h: + * VM/CodeBlock.cpp: + (JSC::CodeBlock::printStructureIDs): + (JSC::CodeBlock::dump): + (JSC::CodeBlock::derefStructureIDs): + (JSC::CodeBlock::refStructureIDs): + * VM/ExceptionHelpers.cpp: + (JSC::createNotAnObjectError): + * VM/Machine.cpp: + (JSC::jsLess): + (JSC::jsLessEq): + (JSC::BytecodeInterpreter::resolve): + (JSC::BytecodeInterpreter::resolveSkip): + (JSC::BytecodeInterpreter::resolveGlobal): + (JSC::BytecodeInterpreter::resolveBase): + (JSC::BytecodeInterpreter::resolveBaseAndProperty): + (JSC::BytecodeInterpreter::resolveBaseAndFunc): + (JSC::BytecodeInterpreter::slideRegisterWindowForCall): + (JSC::BytecodeInterpreter::callEval): + (JSC::BytecodeInterpreter::BytecodeInterpreter): + (JSC::BytecodeInterpreter::initialize): + (JSC::BytecodeInterpreter::~BytecodeInterpreter): + (JSC::BytecodeInterpreter::dumpCallFrame): + (JSC::BytecodeInterpreter::dumpRegisters): + (JSC::BytecodeInterpreter::isOpcode): + (JSC::BytecodeInterpreter::unwindCallFrame): + (JSC::BytecodeInterpreter::throwException): + (JSC::BytecodeInterpreter::execute): + (JSC::BytecodeInterpreter::debug): + (JSC::BytecodeInterpreter::resetTimeoutCheck): + (JSC::BytecodeInterpreter::checkTimeout): + (JSC::BytecodeInterpreter::createExceptionScope): + (JSC::BytecodeInterpreter::tryCachePutByID): + (JSC::BytecodeInterpreter::uncachePutByID): + (JSC::BytecodeInterpreter::tryCacheGetByID): + (JSC::BytecodeInterpreter::uncacheGetByID): + (JSC::BytecodeInterpreter::privateExecute): + (JSC::BytecodeInterpreter::retrieveArguments): + (JSC::BytecodeInterpreter::retrieveCaller): + (JSC::BytecodeInterpreter::retrieveLastCaller): + (JSC::BytecodeInterpreter::findFunctionCallFrame): + (JSC::BytecodeInterpreter::tryCTICachePutByID): + (JSC::BytecodeInterpreter::tryCTICacheGetByID): + (JSC::BytecodeInterpreter::cti_op_convert_this): + (JSC::BytecodeInterpreter::cti_op_end): + (JSC::BytecodeInterpreter::cti_op_add): + (JSC::BytecodeInterpreter::cti_op_pre_inc): + (JSC::BytecodeInterpreter::cti_timeout_check): + (JSC::BytecodeInterpreter::cti_register_file_check): + (JSC::BytecodeInterpreter::cti_op_loop_if_less): + (JSC::BytecodeInterpreter::cti_op_loop_if_lesseq): + (JSC::BytecodeInterpreter::cti_op_new_object): + (JSC::BytecodeInterpreter::cti_op_put_by_id): + (JSC::BytecodeInterpreter::cti_op_put_by_id_second): + (JSC::BytecodeInterpreter::cti_op_put_by_id_generic): + (JSC::BytecodeInterpreter::cti_op_put_by_id_fail): + (JSC::BytecodeInterpreter::cti_op_get_by_id): + (JSC::BytecodeInterpreter::cti_op_get_by_id_second): + (JSC::BytecodeInterpreter::cti_op_get_by_id_generic): + (JSC::BytecodeInterpreter::cti_op_get_by_id_fail): + (JSC::BytecodeInterpreter::cti_op_instanceof): + (JSC::BytecodeInterpreter::cti_op_del_by_id): + (JSC::BytecodeInterpreter::cti_op_mul): + (JSC::BytecodeInterpreter::cti_op_new_func): + (JSC::BytecodeInterpreter::cti_op_call_JSFunction): + (JSC::BytecodeInterpreter::cti_op_call_arityCheck): + (JSC::BytecodeInterpreter::cti_vm_dontLazyLinkCall): + (JSC::BytecodeInterpreter::cti_vm_lazyLinkCall): + (JSC::BytecodeInterpreter::cti_op_push_activation): + (JSC::BytecodeInterpreter::cti_op_call_NotJSFunction): + (JSC::BytecodeInterpreter::cti_op_create_arguments): + (JSC::BytecodeInterpreter::cti_op_create_arguments_no_params): + (JSC::BytecodeInterpreter::cti_op_tear_off_activation): + (JSC::BytecodeInterpreter::cti_op_tear_off_arguments): + (JSC::BytecodeInterpreter::cti_op_profile_will_call): + (JSC::BytecodeInterpreter::cti_op_profile_did_call): + (JSC::BytecodeInterpreter::cti_op_ret_scopeChain): + (JSC::BytecodeInterpreter::cti_op_new_array): + (JSC::BytecodeInterpreter::cti_op_resolve): + (JSC::BytecodeInterpreter::cti_op_construct_JSConstruct): + (JSC::BytecodeInterpreter::cti_op_construct_NotJSConstruct): + (JSC::BytecodeInterpreter::cti_op_get_by_val): + (JSC::BytecodeInterpreter::cti_op_resolve_func): + (JSC::BytecodeInterpreter::cti_op_sub): + (JSC::BytecodeInterpreter::cti_op_put_by_val): + (JSC::BytecodeInterpreter::cti_op_put_by_val_array): + (JSC::BytecodeInterpreter::cti_op_lesseq): + (JSC::BytecodeInterpreter::cti_op_loop_if_true): + (JSC::BytecodeInterpreter::cti_op_negate): + (JSC::BytecodeInterpreter::cti_op_resolve_base): + (JSC::BytecodeInterpreter::cti_op_resolve_skip): + (JSC::BytecodeInterpreter::cti_op_resolve_global): + (JSC::BytecodeInterpreter::cti_op_div): + (JSC::BytecodeInterpreter::cti_op_pre_dec): + (JSC::BytecodeInterpreter::cti_op_jless): + (JSC::BytecodeInterpreter::cti_op_not): + (JSC::BytecodeInterpreter::cti_op_jtrue): + (JSC::BytecodeInterpreter::cti_op_post_inc): + (JSC::BytecodeInterpreter::cti_op_eq): + (JSC::BytecodeInterpreter::cti_op_lshift): + (JSC::BytecodeInterpreter::cti_op_bitand): + (JSC::BytecodeInterpreter::cti_op_rshift): + (JSC::BytecodeInterpreter::cti_op_bitnot): + (JSC::BytecodeInterpreter::cti_op_resolve_with_base): + (JSC::BytecodeInterpreter::cti_op_new_func_exp): + (JSC::BytecodeInterpreter::cti_op_mod): + (JSC::BytecodeInterpreter::cti_op_less): + (JSC::BytecodeInterpreter::cti_op_neq): + (JSC::BytecodeInterpreter::cti_op_post_dec): + (JSC::BytecodeInterpreter::cti_op_urshift): + (JSC::BytecodeInterpreter::cti_op_bitxor): + (JSC::BytecodeInterpreter::cti_op_new_regexp): + (JSC::BytecodeInterpreter::cti_op_bitor): + (JSC::BytecodeInterpreter::cti_op_call_eval): + (JSC::BytecodeInterpreter::cti_op_throw): + (JSC::BytecodeInterpreter::cti_op_get_pnames): + (JSC::BytecodeInterpreter::cti_op_next_pname): + (JSC::BytecodeInterpreter::cti_op_push_scope): + (JSC::BytecodeInterpreter::cti_op_pop_scope): + (JSC::BytecodeInterpreter::cti_op_typeof): + (JSC::BytecodeInterpreter::cti_op_is_undefined): + (JSC::BytecodeInterpreter::cti_op_is_boolean): + (JSC::BytecodeInterpreter::cti_op_is_number): + (JSC::BytecodeInterpreter::cti_op_is_string): + (JSC::BytecodeInterpreter::cti_op_is_object): + (JSC::BytecodeInterpreter::cti_op_is_function): + (JSC::BytecodeInterpreter::cti_op_stricteq): + (JSC::BytecodeInterpreter::cti_op_nstricteq): + (JSC::BytecodeInterpreter::cti_op_to_jsnumber): + (JSC::BytecodeInterpreter::cti_op_in): + (JSC::BytecodeInterpreter::cti_op_push_new_scope): + (JSC::BytecodeInterpreter::cti_op_jmp_scopes): + (JSC::BytecodeInterpreter::cti_op_put_by_index): + (JSC::BytecodeInterpreter::cti_op_switch_imm): + (JSC::BytecodeInterpreter::cti_op_switch_char): + (JSC::BytecodeInterpreter::cti_op_switch_string): + (JSC::BytecodeInterpreter::cti_op_del_by_val): + (JSC::BytecodeInterpreter::cti_op_put_getter): + (JSC::BytecodeInterpreter::cti_op_put_setter): + (JSC::BytecodeInterpreter::cti_op_new_error): + (JSC::BytecodeInterpreter::cti_op_debug): + (JSC::BytecodeInterpreter::cti_vm_throw): + * VM/Machine.h: + * VM/Register.h: + * VM/SamplingTool.cpp: + (JSC::SamplingTool::run): + * VM/SamplingTool.h: + (JSC::SamplingTool::SamplingTool): + * bytecompiler/CodeGenerator.cpp: + (JSC::CodeGenerator::generate): + (JSC::CodeGenerator::CodeGenerator): + (JSC::CodeGenerator::emitOpcode): + * debugger/DebuggerCallFrame.cpp: + (JSC::DebuggerCallFrame::evaluate): + * jsc.cpp: + (runWithScripts): + * parser/Nodes.cpp: + (JSC::ScopeNode::ScopeNode): + * profiler/ProfileGenerator.cpp: + (JSC::ProfileGenerator::addParentForConsoleStart): + * runtime/ArrayPrototype.cpp: + (JSC::arrayProtoFuncPop): + (JSC::arrayProtoFuncPush): + * runtime/Collector.cpp: + (JSC::Heap::collect): + * runtime/ExecState.h: + (JSC::ExecState::interpreter): + * runtime/FunctionPrototype.cpp: + (JSC::functionProtoFuncApply): + * runtime/Interpreter.cpp: + (JSC::Interpreter::evaluate): + * runtime/JSCell.h: + * runtime/JSFunction.cpp: + (JSC::JSFunction::call): + (JSC::JSFunction::argumentsGetter): + (JSC::JSFunction::callerGetter): + (JSC::JSFunction::construct): + * runtime/JSFunction.h: + * runtime/JSGlobalData.cpp: + (JSC::JSGlobalData::JSGlobalData): + (JSC::JSGlobalData::~JSGlobalData): + * runtime/JSGlobalData.h: + * runtime/JSGlobalObject.cpp: + (JSC::JSGlobalObject::~JSGlobalObject): + (JSC::JSGlobalObject::setTimeoutTime): + (JSC::JSGlobalObject::startTimeoutCheck): + (JSC::JSGlobalObject::stopTimeoutCheck): + (JSC::JSGlobalObject::mark): + * runtime/JSGlobalObjectFunctions.cpp: + (JSC::globalFuncEval): + * runtime/JSString.h: + * runtime/RegExp.cpp: + (JSC::RegExp::RegExp): + +2008-11-15 Maciej Stachowiak <mjs@apple.com> + + Reviewed by Sam Weinig. + + - Remove SymbolTable from FunctionBodyNode and move it to CodeBlock + + It's not needed for functions that have never been executed, so no + need to waste the memory. Saves ~4M on membuster after 30 pages. + + * VM/CodeBlock.h: + * VM/Machine.cpp: + (JSC::Machine::retrieveArguments): + * parser/Nodes.cpp: + (JSC::EvalNode::generateCode): + (JSC::FunctionBodyNode::generateCode): + * parser/Nodes.h: + * runtime/JSActivation.h: + (JSC::JSActivation::JSActivationData::JSActivationData): + +2008-11-14 Cameron Zwarich <zwarich@apple.com> + + Reviewed by Darin Adler. + + Bug 22259: Make all opcodes use eax as their final result register + <https://bugs.webkit.org/show_bug.cgi?id=22259> + + Change one case of op_add (and the corresponding slow case) to use eax + rather than edx. Also, change the order in which the two results of + resolve_func and resolve_base are emitted so that the retrieved value is + put last into eax. + + This gives no performance change on SunSpider or the V8 benchmark suite + when run in either harness. + + * VM/CTI.cpp: + (JSC::CTI::privateCompileMainPass): + (JSC::CTI::privateCompileSlowCases): + +2008-11-14 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Geoff Garen. + + Geoff has this wacky notion that emitGetArg and emitPutArg should be related to + doing the same thing. Crazy. + + Rename the methods for accessing virtual registers to say 'VirtualRegister' in the + name, and those for setting up the arguments for CTI methods to contain 'CTIArg'. + + * VM/CTI.cpp: + (JSC::CTI::emitGetVirtualRegister): + (JSC::CTI::emitGetVirtualRegisters): + (JSC::CTI::emitPutCTIArgFromVirtualRegister): + (JSC::CTI::emitPutCTIArg): + (JSC::CTI::emitGetCTIArg): + (JSC::CTI::emitPutCTIArgConstant): + (JSC::CTI::emitPutVirtualRegister): + (JSC::CTI::compileOpCallSetupArgs): + (JSC::CTI::compileOpCallEvalSetupArgs): + (JSC::CTI::compileOpConstructSetupArgs): + (JSC::CTI::compileOpCall): + (JSC::CTI::compileOpStrictEq): + (JSC::CTI::putDoubleResultToJSNumberCellOrJSImmediate): + (JSC::CTI::compileBinaryArithOp): + (JSC::CTI::compileBinaryArithOpSlowCase): + (JSC::CTI::privateCompileMainPass): + (JSC::CTI::privateCompileSlowCases): + (JSC::CTI::privateCompileCTIMachineTrampolines): + * VM/CTI.h: + +2008-11-14 Greg Bolsinga <bolsinga@apple.com> + + Reviewed by Antti Koivisto + + Fix potential build break by adding StdLibExtras.h + + * GNUmakefile.am: + * JavaScriptCore.vcproj/WTF/WTF.vcproj: + +2008-11-14 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Geoff Garen. + + Generate less code for the slow cases of op_call and op_construct. + https://bugs.webkit.org/show_bug.cgi?id=22272 + + 1% progression on v8 tests. + + * VM/CTI.cpp: + (JSC::CTI::emitRetrieveArg): + (JSC::CTI::emitNakedCall): + (JSC::CTI::compileOpCallInitializeCallFrame): + (JSC::CTI::compileOpCall): + (JSC::CTI::privateCompileSlowCases): + (JSC::CTI::privateCompileCTIMachineTrampolines): + * VM/CTI.h: + * VM/CodeBlock.h: + (JSC::getCallLinkInfoReturnLocation): + (JSC::CodeBlock::getCallLinkInfo): + * VM/Machine.cpp: + (JSC::Machine::Machine): + (JSC::Machine::cti_vm_dontLazyLinkCall): + (JSC::Machine::cti_vm_lazyLinkCall): + * VM/Machine.h: + +2008-11-14 Greg Bolsinga <bolsinga@apple.com> + + Reviewed by Darin Alder. + + https://bugs.webkit.org/show_bug.cgi?id=21810 + Remove use of static C++ objects that are destroyed at exit time (destructors) + + Create DEFINE_STATIC_LOCAL macro. Change static local objects to leak to avoid + exit-time destructor. Update code that was changed to fix this issue that ran + into a gcc bug (<rdar://problem/6354696> Codegen issue with C++ static reference + in gcc build 5465). Also typdefs for template types needed to be added in some + cases so the type could make it through the macro successfully. + + Basically code of the form: + static T m; + becomes: + DEFINE_STATIC_LOCAL(T, m, ()); + + Also any code of the form: + static T& m = *new T; + also becomes: + DEFINE_STATIC_LOCAL(T, m, ()); + + * JavaScriptCore.xcodeproj/project.pbxproj: + * wtf/MainThread.cpp: + (WTF::mainThreadFunctionQueueMutex): + (WTF::functionQueue): + * wtf/StdLibExtras.h: Added. Add DEFINE_STATIC_LOCAL macro + * wtf/ThreadingPthreads.cpp: + (WTF::threadMapMutex): + (WTF::threadMap): + (WTF::identifierByPthreadHandle): + +2008-11-13 Sam Weinig <sam@webkit.org> + + Reviewed by Darin Adler + + Fix for https://bugs.webkit.org/show_bug.cgi?id=22269 + Reduce PropertyMap usage + + From observation of StructureID statistics, it became clear that many + StructureID's were not being used as StructureIDs themselves, but rather + only being necessary as links in the transition chain. Acknowledging this + and that PropertyMaps stored in StructureIDs can be treated as caches, that + is that they can be reconstructed on demand, it became clear that we could + reduce the memory consumption of StructureIDs by only keeping PropertyMaps + for the StructureIDs that need them the most. + + The specific strategy used to reduce the number of StructureIDs with + PropertyMaps is to take the previous StructureIDs PropertyMap when initially + transitioning (addPropertyTransition) from it and clearing out the pointer + in the process. The next time we need to do the same transition, for instance + repeated calls to the same constructor, we use the new addPropertyTransitionToExistingStructure + first, which allows us not to need the PropertyMap to determine if the property + exists already, since a transition to that property would require it not already + be present in the StructureID. Should there be no transition, the PropertyMap + can be constructed on demand (via materializePropertyMap) to determine if the put is a + replace or a transition to a new StructureID. + + Reduces memory use on Membuster head test (30 pages open) by ~15MB. + + * JavaScriptCore.exp: + * runtime/JSObject.h: + (JSC::JSObject::putDirect): First use addPropertyTransitionToExistingStructure + so that we can avoid building the PropertyMap on subsequent similar object + creations. + * runtime/PropertyMapHashTable.h: + (JSC::PropertyMapEntry::PropertyMapEntry): Add version of constructor which takes + all values to be used when lazily building the PropertyMap. + * runtime/StructureID.cpp: + (JSC::StructureID::dumpStatistics): Add statistics on the number of StructureIDs + with PropertyMaps. + (JSC::StructureID::StructureID): Rename m_cachedTransistionOffset to m_offset + (JSC::isPowerOf2): + (JSC::nextPowerOf2): + (JSC::sizeForKeyCount): Returns the expected size of a PropertyMap for a key count. + (JSC::StructureID::materializePropertyMap): Builds the PropertyMap out of its previous pointer chain. + (JSC::StructureID::addPropertyTransitionToExistingStructure): Only transitions if there is a + an existing transition. + (JSC::StructureID::addPropertyTransition): Instead of always copying the ProperyMap, try and take + it from it previous pointer. + (JSC::StructureID::removePropertyTransition): Simplify by calling toDictionaryTransition() to do + transition work. + (JSC::StructureID::changePrototypeTransition): Build the PropertyMap if necessary before transitioning + because once you have transitioned, you will not be able to reconstruct it afterwards as there is no + previous pointer, pinning the ProperyMap as well. + (JSC::StructureID::getterSetterTransition): Ditto. + (JSC::StructureID::toDictionaryTransition): Pin the PropertyMap so that it is not destroyed on further transitions. + (JSC::StructureID::fromDictionaryTransition): We can only transition back from a dictionary transition if there + are no deleted offsets. + (JSC::StructureID::addPropertyWithoutTransition): Build PropertyMap on demands and pin. + (JSC::StructureID::removePropertyWithoutTransition): Ditto. + (JSC::StructureID::get): Build on demand. + (JSC::StructureID::createPropertyMapHashTable): Add version of create that takes a size + for on demand building. + (JSC::StructureID::expandPropertyMapHashTable): + (JSC::StructureID::rehashPropertyMapHashTable): + (JSC::StructureID::getEnumerablePropertyNamesInternal): Build PropertyMap on demand. + * runtime/StructureID.h: + (JSC::StructureID::propertyStorageSize): Account for StructureIDs without PropertyMaps. + (JSC::StructureID::isEmpty): Ditto. + (JSC::StructureID::materializePropertyMapIfNecessary): + (JSC::StructureID::get): Build PropertyMap on demand + +2008-11-14 Csaba Osztrogonac <oszi@inf.u-szeged.hu> + + Reviewed by Simon Hausmann. + + <https://bugs.webkit.org/show_bug.cgi?id=21500> + + JavaScriptCore build with -O3 flag instead of -O2 (gcc). + 2.02% speedup on SunSpider (Qt-port on Linux) + 1.10% speedup on V8 (Qt-port on Linux) + 3.45% speedup on WindScorpion (Qt-port on Linux) + + * JavaScriptCore.pri: + +2008-11-14 Kristian Amlie <kristian.amlie@trolltech.com> + + Reviewed by Darin Adler. + + Compile fix for RVCT. + + In reality, it is two fixes: + + 1. Remove typename. I believe typename can only be used when the named + type depends on the template parameters, which it doesn't in this + case, so I think this is more correct. + 2. Replace ::iterator scope with specialized typedef. This is to work + around a bug in RVCT. + + https://bugs.webkit.org/show_bug.cgi?id=22260 + + * wtf/ListHashSet.h: + (WTF::::find): + +2008-11-14 Kristian Amlie <kristian.amlie@trolltech.com> + + Reviewed by Darin Adler. + + Compile fix for WINSCW. + + This fix doesn't protect against implicit conversions from bool to + integers, but most likely that will be caught on another platform. + + https://bugs.webkit.org/show_bug.cgi?id=22260 + + * wtf/PassRefPtr.h: + (WTF::PassRefPtr::operator bool): + * wtf/RefPtr.h: + (WTF::RefPtr::operator bool): + +2008-11-14 Cameron Zwarich <zwarich@apple.com> + + Reviewed by Darin Adler. + + Bug 22245: Move wtf/dtoa.h into the WTF namespace + <https://bugs.webkit.org/show_bug.cgi?id=22245> + + Move wtf/dtoa.h into the WTF namespace from the JSC namespace. This + introduces some ambiguities in name lookups, so I changed all uses of + the functions in wtf/dtoa.h to explicitly state the namespace. + + * JavaScriptCore.exp: + * parser/Lexer.cpp: + (JSC::Lexer::lex): + * runtime/InitializeThreading.cpp: + * runtime/JSGlobalObjectFunctions.cpp: + (JSC::parseInt): + * runtime/NumberPrototype.cpp: + (JSC::integerPartNoExp): + (JSC::numberProtoFuncToExponential): + * runtime/UString.cpp: + (JSC::concatenate): + (JSC::UString::from): + (JSC::UString::toDouble): + * wtf/dtoa.cpp: + * wtf/dtoa.h: + +2008-11-14 Cameron Zwarich <zwarich@apple.com> + + Reviewed by Maciej Stachowiak. + + Bug 22257: Enable redundant read optimizations for results generated by compileBinaryArithOp() + <https://bugs.webkit.org/show_bug.cgi?id=22257> + + This shows no change in performance on either SunSpider or the V8 + benchmark suite, but it removes an ugly special case and allows for + future optimizations to be implemented in a cleaner fashion. + + This patch was essentially given to me by Gavin Barraclough upon my + request, but I did regression and performance testing so that he could + work on something else. + + * VM/CTI.cpp: + (JSC::CTI::putDoubleResultToJSNumberCellOrJSImmediate): Move the final + result to eax if it is not already there. + (JSC::CTI::compileBinaryArithOp): Remove the killing of the final result + register that disables the optimization. + +2008-11-13 Eric Seidel <eric@webkit.org> + + Reviewed by Adam Roben. + + Add a Scons-based build system for building + the Chromium-Mac build of JavaScriptCore. + https://bugs.webkit.org/show_bug.cgi?id=21991 + + * JavaScriptCore.scons: Added. + * SConstruct: Added. + +2008-11-13 Eric Seidel <eric@webkit.org> + + Reviewed by Adam Roben. + + Add PLATFORM(CHROMIUM) to the "we don't use cairo" blacklist + until https://bugs.webkit.org/show_bug.cgi?id=22250 is fixed. + + * wtf/Platform.h: + +2008-11-13 Cameron Zwarich <zwarich@apple.com> + + Reviewed by Sam Weinig. + + In r38375 the 'jsc' shell was changed to improve teardown on quit. The + main() function in jsc.cpp uses Structured Exception Handling, so Visual + C++ emits a warning when destructors are used. + + In order to speculatively fix the Windows build, this patch changes that + code to use explicit pointer manipulation and locking rather than smart + pointers and RAII. + + * jsc.cpp: + (main): + +2008-11-13 Cameron Zwarich <zwarich@apple.com> + + Reviewed by Darin Adler. + + Bug 22246: Get arguments for opcodes together to eliminate more redundant memory reads + <https://bugs.webkit.org/show_bug.cgi?id=22246> + + It is common for opcodes to read their first operand into eax and their + second operand into edx. If the value intended for the second operand is + in eax, we should first move eax to the register for the second operand + and then read the first operand into eax. + + This is a 0.5% speedup on SunSpider and a 2.0% speedup on the V8 + benchmark suite when measured using the V8 harness. + + * VM/CTI.cpp: + (JSC::CTI::emitGetArgs): + (JSC::CTI::compileOpStrictEq): + (JSC::CTI::compileBinaryArithOp): + (JSC::CTI::privateCompileMainPass): + (JSC::CTI::privateCompileSlowCases): + * VM/CTI.h: + +2008-11-13 Cameron Zwarich <zwarich@apple.com> + + Reviewed by Darin Adler. + + Bug 22238: Avoid unnecessary reads of temporaries when the target machine register is not eax + <https://bugs.webkit.org/show_bug.cgi?id=22238> + + Enable the optimization of not reading a value back from memory that we + just wrote when the target machine register is not eax. In order to do + this, the code generation for op_put_global_var must be changed to + read its argument into a register before overwriting eax. + + This is a 0.5% speedup on SunSpider and shows no change on the V8 + benchmark suite when run in either harness. + + * VM/CTI.cpp: + (JSC::CTI::emitGetArg): + (JSC::CTI::privateCompileMainPass): + +2008-11-13 Cameron Zwarich <zwarich@apple.com> + + Reviewed by Alexey Proskuryakov. + + Perform teardown in the 'jsc' shell in order to suppress annoying and + misleading leak messages. There is still a lone JSC::Node leaking when + quit() is called, but hopefully that can be fixed as well. + + * jsc.cpp: + (functionQuit): + (main): + +2008-11-13 Mike Pinkerton <pinkerton@chromium.org> + + Reviewed by Sam Weinig. + + Fix for https://bugs.webkit.org/show_bug.cgi?id=22087 + Need correct platform defines for Mac Chromium + + Set the appropriate platform defines for Mac Chromium, which is + similar to PLATFORM(MAC), but isn't. + + * wtf/Platform.h: + +2008-11-13 Maciej Stachowiak <mjs@apple.com> + + Reviewed by Cameron Zwarich. + + - remove immediate checks from native codegen for known non-immediate cases like "this" + + ~.5% speedup on v8 benchmarks + + In the future we can extend this model to remove all sorts of + typechecks based on local type info or type inference. + + I also added an assertion to verify that all slow cases linked as + many slow case jumps as the corresponding fast case generated, and + fixed the pre-existing cases where this was not true. + + * VM/CTI.cpp: + (JSC::CTI::emitJumpSlowCaseIfNotJSCell): + (JSC::CTI::linkSlowCaseIfNotJSCell): + (JSC::CTI::compileBinaryArithOp): + (JSC::CTI::compileBinaryArithOpSlowCase): + (JSC::CTI::privateCompileMainPass): + (JSC::CTI::privateCompileSlowCases): + * VM/CTI.h: + * VM/CodeBlock.h: + (JSC::CodeBlock::isKnownNotImmediate): + +2008-11-13 Cameron Zwarich <zwarich@apple.com> + + Reviewed by Maciej Stachowiak. + + Bug 21943: Avoid needless reads of temporary values in CTI code + <https://bugs.webkit.org/show_bug.cgi?id=21943> + + If an opcode needs to load a virtual register and a previous opcode left + the contents of that virtual register in a machine register, use the + value in the machine register rather than getting it from memory. + + In order to perform this optimization, it is necessary to know the + jump tagets in the CodeBlock. For temporaries, the only problematic + jump targets are binary logical operators and the ternary conditional + operator. However, if this optimization were to be extended to local + variable registers as well, other jump targets would need to be + included, like switch statement cases and the beginnings of catch + blocks. + + This optimization also requires that the fast case and the slow case + of an opcode use emitPutResult() on the same register, which was chosen + to be eax, as that is the register into which we read the first operand + of opcodes. In order to make this the case, we needed to add some mov + instructions to the slow cases of some instructions. + + This optimizaton is not applied whenever compileBinaryArithOp() is used + to compile an opcode, because different machine registers may be used to + store the final result. It seems possible to rewrite the code generation + in compileBinaryArithOp() to allow for this optimization. + + This optimization is also not applied when generating slow cases, + because some fast cases overwrite the value of eax before jumping to the + slow case. In the future, it may be possible to apply this optimization + to slow cases as well, but it did not seem to be a speedup when testing + an early version of this patch. + + This is a 1.0% speedup on SunSpider and a 6.3% speedup on the V8 + benchmark suite. + + * VM/CTI.cpp: + (JSC::CTI::killLastResultRegister): + (JSC::CTI::emitGetArg): + (JSC::CTI::emitGetPutArg): + (JSC::CTI::emitGetCTIParam): + (JSC::CTI::emitGetFromCallFrameHeader): + (JSC::CTI::emitPutResult): + (JSC::CTI::emitCTICall): + (JSC::CTI::CTI): + (JSC::CTI::compileOpCall): + (JSC::CTI::compileOpStrictEq): + (JSC::CTI::emitSlowScriptCheck): + (JSC::CTI::compileBinaryArithOp): + (JSC::CTI::privateCompileMainPass): + (JSC::CTI::privateCompileSlowCases): + (JSC::CTI::privateCompileGetByIdProto): + (JSC::CTI::privateCompilePatchGetArrayLength): + * VM/CTI.h: + * VM/CodeBlock.h: + (JSC::CodeBlock::isTemporaryRegisterIndex): + * bytecompiler/CodeGenerator.cpp: + (JSC::CodeGenerator::emitLabel): + +2008-11-12 Alp Toker <alp@nuanti.com> + + autotools build system fix-up only. Add FloatQuad.h to the source + lists and sort them. + + * GNUmakefile.am: + +2008-11-12 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Sam Weinig. + + Fixed https://bugs.webkit.org/show_bug.cgi?id=22192 + +37 failures in fast/profiler + + along with Darin's review comments in + https://bugs.webkit.org/show_bug.cgi?id=22174 + Simplified op_call by nixing its responsibility for moving the value of + "this" into the first argument slot + + * VM/Machine.cpp: + (JSC::returnToThrowTrampoline): + (JSC::throwStackOverflowError): + (JSC::Machine::cti_register_file_check): + (JSC::Machine::cti_op_call_arityCheck): + (JSC::Machine::cti_vm_throw): Moved the throw logic into a function, since + functions are better than macros. + + * bytecompiler/CodeGenerator.cpp: + (JSC::CodeGenerator::emitCall): + (JSC::CodeGenerator::emitConstruct): Ensure that the function register + is preserved if profiling is enabled, since the profiler uses that + register. + + * runtime/JSGlobalData.h: Renamed throwReturnAddress to exceptionLocation, + because I had a hard time understanding what "throwReturnAddress" meant. + +2008-11-12 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Sam Weinig. + + Roll in r38322, now that test failures have been fixed. + + * VM/CTI.cpp: + (JSC::CTI::compileOpCallSetupArgs): + (JSC::CTI::compileOpCallEvalSetupArgs): + (JSC::CTI::compileOpConstructSetupArgs): + (JSC::CTI::compileOpCall): + (JSC::CTI::privateCompileMainPass): + (JSC::CTI::privateCompileSlowCases): + * VM/CTI.h: + * VM/CodeBlock.cpp: + (JSC::CodeBlock::dump): + * VM/Machine.cpp: + (JSC::Machine::callEval): + (JSC::Machine::dumpCallFrame): + (JSC::Machine::dumpRegisters): + (JSC::Machine::execute): + (JSC::Machine::privateExecute): + (JSC::Machine::cti_register_file_check): + (JSC::Machine::cti_op_call_arityCheck): + (JSC::Machine::cti_op_call_NotJSFunction): + (JSC::Machine::cti_op_construct_JSConstruct): + (JSC::Machine::cti_op_construct_NotJSConstruct): + (JSC::Machine::cti_op_call_eval): + (JSC::Machine::cti_vm_throw): + * VM/Machine.h: + * bytecompiler/CodeGenerator.cpp: + (JSC::CodeGenerator::emitCall): + (JSC::CodeGenerator::emitCallEval): + (JSC::CodeGenerator::emitConstruct): + * bytecompiler/CodeGenerator.h: + * parser/Nodes.cpp: + (JSC::EvalFunctionCallNode::emitCode): + (JSC::FunctionCallValueNode::emitCode): + (JSC::FunctionCallResolveNode::emitCode): + (JSC::FunctionCallBracketNode::emitCode): + (JSC::FunctionCallDotNode::emitCode): + * parser/Nodes.h: + (JSC::ScopeNode::neededConstants): + +2008-11-12 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Cameron Zwarich. + + Fix for https://bugs.webkit.org/show_bug.cgi?id=22201 + Integer conversion in array.length was safe signed values, + but the length is unsigned. + + * VM/CTI.cpp: + (JSC::CTI::privateCompilePatchGetArrayLength): + +2008-11-12 Cameron Zwarich <zwarich@apple.com> + + Rubber-stamped by Mark Rowe. + + Roll out r38322 due to test failures on the bots. + + * VM/CTI.cpp: + (JSC::CTI::compileOpCallSetupArgs): + (JSC::CTI::compileOpCall): + (JSC::CTI::privateCompileMainPass): + (JSC::CTI::privateCompileSlowCases): + * VM/CTI.h: + * VM/CodeBlock.cpp: + (JSC::CodeBlock::dump): + * VM/Machine.cpp: + (JSC::Machine::callEval): + (JSC::Machine::dumpCallFrame): + (JSC::Machine::dumpRegisters): + (JSC::Machine::execute): + (JSC::Machine::privateExecute): + (JSC::Machine::throwStackOverflowPreviousFrame): + (JSC::Machine::cti_register_file_check): + (JSC::Machine::cti_op_call_arityCheck): + (JSC::Machine::cti_op_call_NotJSFunction): + (JSC::Machine::cti_op_construct_JSConstruct): + (JSC::Machine::cti_op_construct_NotJSConstruct): + (JSC::Machine::cti_op_call_eval): + (JSC::Machine::cti_vm_throw): + * VM/Machine.h: + * bytecompiler/CodeGenerator.cpp: + (JSC::CodeGenerator::emitCall): + (JSC::CodeGenerator::emitCallEval): + (JSC::CodeGenerator::emitConstruct): + * bytecompiler/CodeGenerator.h: + * parser/Nodes.cpp: + (JSC::EvalFunctionCallNode::emitCode): + (JSC::FunctionCallValueNode::emitCode): + (JSC::FunctionCallResolveNode::emitCode): + (JSC::FunctionCallBracketNode::emitCode): + (JSC::FunctionCallDotNode::emitCode): + * parser/Nodes.h: + (JSC::ScopeNode::neededConstants): + +2008-11-11 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Darin Adler. + + Fixed https://bugs.webkit.org/show_bug.cgi?id=22174 + Simplified op_call by nixing its responsibility for moving the value of + "this" into the first argument slot. + + Instead, the caller emits an explicit load or mov instruction, or relies + on implicit knowledge that "this" is already in the first argument slot. + As a result, two operands to op_call are gone: firstArg and thisVal. + + SunSpider and v8 tests show no change in bytecode or CTI. + + * VM/CTI.cpp: + (JSC::CTI::compileOpCallSetupArgs): + (JSC::CTI::compileOpCallEvalSetupArgs): + (JSC::CTI::compileOpConstructSetupArgs): Split apart these three versions + of setting up arguments to op_call, because they're more different than + they are the same -- even more so with this patch. + + (JSC::CTI::compileOpCall): Updated for the fact that op_construct doesn't + match op_call anymore. + + (JSC::CTI::privateCompileMainPass): + (JSC::CTI::privateCompileSlowCases): Merged a few call cases. Updated + for changes mentioned above. + + * VM/CTI.h: + + * VM/CodeBlock.cpp: + (JSC::CodeBlock::dump): Updated for new bytecode format of call / construct. + + * VM/Machine.cpp: + (JSC::Machine::callEval): Updated for new bytecode format of call / construct. + + (JSC::Machine::dumpCallFrame): + (JSC::Machine::dumpRegisters): Simplified these debugging functions, + taking advantage of the new call frame layout. + + (JSC::Machine::execute): Fixed up the eval version of execute to be + friendlier to calls in the new format. + + (JSC::Machine::privateExecute): Implemented the new call format in + bytecode. + + (JSC::Machine::cti_op_call_NotJSFunction): + (JSC::Machine::cti_op_construct_JSConstruct): + (JSC::Machine::cti_op_construct_NotJSConstruct): + (JSC::Machine::cti_op_call_eval): Updated CTI helpers to match the new + call format. + + Fixed a latent bug in stack overflow checking that is now hit because + the register layout has changed a bit -- namely: when throwing a stack + overflow exception inside an op_call helper, we need to account for the + fact that the current call frame is only half-constructed, and use the + parent call frame instead. + + * VM/Machine.h: + + * bytecompiler/CodeGenerator.cpp: + (JSC::CodeGenerator::emitCall): + (JSC::CodeGenerator::emitCallEval): + (JSC::CodeGenerator::emitConstruct): + * bytecompiler/CodeGenerator.h: Updated codegen to match the new call + format. + + * parser/Nodes.cpp: + (JSC::EvalFunctionCallNode::emitCode): + (JSC::FunctionCallValueNode::emitCode): + (JSC::FunctionCallResolveNode::emitCode): + (JSC::FunctionCallBracketNode::emitCode): + (JSC::FunctionCallDotNode::emitCode): + * parser/Nodes.h: + (JSC::ScopeNode::neededConstants): ditto + +2008-11-11 Cameron Zwarich <zwarich@apple.com> + + Reviewed by Geoff Garen. + + Remove an unused forwarding header for a file that no longer exists. + + * ForwardingHeaders/JavaScriptCore/JSLock.h: Removed. + +2008-11-11 Mark Rowe <mrowe@apple.com> + + Fix broken dependencies building JavaScriptCore on a freezing cold cat, caused + by failure to update all instances of "kjs" to their new locations. + + * JavaScriptCore.xcodeproj/project.pbxproj: + +2008-11-11 Alexey Proskuryakov <ap@webkit.org> + + Rubber-stamped by Adam Roben. + + * wtf/AVLTree.h: (WTF::AVLTree::Iterator::start_iter): + Fix indentation a little more. + +2008-11-11 Cameron Zwarich <zwarich@apple.com> + + Rubber-stamped by Sam Weinig. + + Clean up EvalCodeCache to match our coding style a bit more. + + * VM/EvalCodeCache.h: + (JSC::EvalCodeCache::get): + +2008-11-11 Cameron Zwarich <zwarich@apple.com> + + Rubber-stamped by Sam Weinig. + + Bug 22179: Move EvalCodeCache from CodeBlock.h into its own file + <https://bugs.webkit.org/show_bug.cgi?id=22179> + + * GNUmakefile.am: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: + * JavaScriptCore.xcodeproj/project.pbxproj: + * VM/CodeBlock.h: + * VM/EvalCodeCache.h: Copied from VM/CodeBlock.h. + * VM/Machine.cpp: + +2008-11-11 Cameron Zwarich <zwarich@apple.com> + + Reviewed by Sam Weinig. + + Remove the 'm_' prefix from the fields of the SwitchRecord struct. + + * VM/CTI.cpp: + (JSC::CTI::privateCompile): + * VM/CTI.h: + (JSC::SwitchRecord): + (JSC::SwitchRecord::SwitchRecord): + +2008-11-11 Cameron Zwarich <zwarich@apple.com> + + Rubber-stamped by Sam Weinig. + + Make asInteger() a static function so that it has internal linkage. + + * VM/CTI.cpp: + (JSC::asInteger): + +2008-11-11 Maciej Stachowiak <mjs@apple.com> + + Reviewed by Mark Rowe. + + - shrink CodeBlock and AST related Vectors to exact fit (5-10M savings on membuster test) + + No perf regression combined with the last patch (each seems like a small regression individually) + + * bytecompiler/CodeGenerator.cpp: + (JSC::CodeGenerator::generate): + * parser/Nodes.h: + (JSC::SourceElements::releaseContentsIntoVector): + * wtf/Vector.h: + (WTF::Vector::shrinkToFit): + +2008-11-11 Maciej Stachowiak <mjs@apple.com> + + Reviewed by Mark Rowe. + + - remove inline capacity from declaration stacks (15M savings on membuster test) + + No perf regression on SunSpider or V8 test combined with other upcoming memory improvement patch. + + * JavaScriptCore.exp: + * parser/Nodes.h: + +2008-11-11 Cameron Zwarich <zwarich@apple.com> + + Reviewed by Oliver Hunt. + + While r38286 removed the need for the m_callFrame member variable of + CTI, it should be also be removed. + + * VM/CTI.h: + +2008-11-10 Cameron Zwarich <zwarich@apple.com> + + Reviewed by Oliver Hunt. + + Make CTI::asInteger() a non-member function, since it needs no access to + any of CTI's member variables. + + * VM/CTI.cpp: + (JSC::asInteger): + * VM/CTI.h: + +2008-11-10 Cameron Zwarich <zwarich@apple.com> + + Reviewed by Maciej Stachowiak. + + Use 'value' instead of 'js' in CTI as a name for JSValue* to match our + usual convention elsewhere. + + * VM/CTI.cpp: + (JSC::CTI::emitGetArg): + (JSC::CTI::emitGetPutArg): + (JSC::CTI::getConstantImmediateNumericArg): + (JSC::CTI::printOpcodeOperandTypes): + +2008-11-10 Cameron Zwarich <zwarich@apple.com> + + Reviewed by Maciej Stachowiak. + + Make CTI::getConstant() a member function of CodeBlock instead. + + * VM/CTI.cpp: + (JSC::CTI::emitGetArg): + (JSC::CTI::emitGetPutArg): + (JSC::CTI::getConstantImmediateNumericArg): + (JSC::CTI::printOpcodeOperandTypes): + (JSC::CTI::privateCompileMainPass): + * VM/CTI.h: + * VM/CodeBlock.h: + (JSC::CodeBlock::getConstant): + +2008-11-10 Cameron Zwarich <zwarich@apple.com> + + Reviewed by Sam Weinig. + + Rename CodeBlock::isConstant() to isConstantRegisterIndex(). + + * VM/CTI.cpp: + (JSC::CTI::emitGetArg): + (JSC::CTI::emitGetPutArg): + (JSC::CTI::getConstantImmediateNumericArg): + (JSC::CTI::printOpcodeOperandTypes): + (JSC::CTI::privateCompileMainPass): + * VM/CodeBlock.h: + (JSC::CodeBlock::isConstantRegisterIndex): + * bytecompiler/CodeGenerator.cpp: + (JSC::CodeGenerator::emitEqualityOp): + +2008-11-10 Gavin Barraclough <barraclough@apple.com> + + Build fix for non-CTI builds. + + * VM/Machine.cpp: + (JSC::Machine::initialize): + +2008-11-10 Cameron Zwarich <zwarich@apple.com> + + Reviewed by Sam Weinig. + + Remove the unused labels member variable of CodeBlock. + + * VM/CodeBlock.h: + * VM/LabelID.h: + (JSC::LabelID::setLocation): + +2008-11-10 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Cameron Zwarich. + + Batch compile the set of static trampolines at the point Machine is constructed, using a single allocation. + Refactor out m_callFrame from CTI, since this is only needed to access the global data (instead store a + pointer to the global data directly, since this is available at the point the Machine is constructed). + Add a method to align the code buffer, to allow JIT generation for multiple trampolines in one block. + + * VM/CTI.cpp: + (JSC::CTI::getConstant): + (JSC::CTI::emitGetArg): + (JSC::CTI::emitGetPutArg): + (JSC::CTI::getConstantImmediateNumericArg): + (JSC::CTI::printOpcodeOperandTypes): + (JSC::CTI::CTI): + (JSC::CTI::compileBinaryArithOp): + (JSC::CTI::privateCompileMainPass): + (JSC::CTI::privateCompileGetByIdProto): + (JSC::CTI::privateCompileGetByIdChain): + (JSC::CTI::privateCompileCTIMachineTrampolines): + (JSC::CTI::freeCTIMachineTrampolines): + * VM/CTI.h: + (JSC::CTI::compile): + (JSC::CTI::compileGetByIdSelf): + (JSC::CTI::compileGetByIdProto): + (JSC::CTI::compileGetByIdChain): + (JSC::CTI::compilePutByIdReplace): + (JSC::CTI::compilePutByIdTransition): + (JSC::CTI::compileCTIMachineTrampolines): + (JSC::CTI::compilePatchGetArrayLength): + * VM/Machine.cpp: + (JSC::Machine::initialize): + (JSC::Machine::~Machine): + (JSC::Machine::execute): + (JSC::Machine::tryCTICachePutByID): + (JSC::Machine::tryCTICacheGetByID): + (JSC::Machine::cti_op_call_JSFunction): + (JSC::Machine::cti_vm_lazyLinkCall): + * VM/Machine.h: + * masm/X86Assembler.h: + (JSC::JITCodeBuffer::isAligned): + (JSC::X86Assembler::): + (JSC::X86Assembler::align): + * runtime/JSGlobalData.cpp: + (JSC::JSGlobalData::JSGlobalData): + +2008-11-10 Maciej Stachowiak <mjs@apple.com> + + Reviewed by Antti Koivisto. + + - Make Vector::clear() release the Vector's memory (1MB savings on membuster) + https://bugs.webkit.org/show_bug.cgi?id=22170 + + * wtf/Vector.h: + (WTF::VectorBufferBase::deallocateBuffer): Set capacity to 0 as + well as size, otherwise shrinking capacity to 0 can fail to reset + the capacity and thus cause a future crash. + (WTF::Vector::~Vector): Shrink size not capacity; we only need + to call destructors, the buffer will be freed anyway. + (WTF::Vector::clear): Change this to shrinkCapacity(0), not just shrink(0). + (WTF::::shrinkCapacity): Use shrink() instead of resize() for case where + the size is greater than the new capacity, to work with types that have no + default constructor. + +2008-11-10 Cameron Zwarich <zwarich@apple.com> + + Reviewed by Maciej Stachowiak. + + Split multiple definitions into separate lines. + + * VM/CTI.cpp: + (JSC::CTI::compileBinaryArithOp): + +2008-11-10 Cameron Zwarich <zwarich@apple.com> + + Reviewed by Geoff Garen. + + Bug 22162: Remove cachedValueGetter from the JavaScriptCore API implementation + <https://bugs.webkit.org/show_bug.cgi?id=22162> + + There is no more need for the cachedValueGetter hack now that we have + PropertySlot::setValue(), so we should remove it. + + * API/JSCallbackObject.h: + * API/JSCallbackObjectFunctions.h: + (JSC::::getOwnPropertySlot): + +2008-11-10 Cameron Zwarich <zwarich@apple.com> + + Reviewed by Darin Adler. + + Bug 22152: Remove asObject() call from JSCallbackObject::getOwnPropertySlot() + <https://bugs.webkit.org/show_bug.cgi?id=22152> + + With the recent change to adopt asType() style cast functions with + assertions instead of static_casts in many places, the assertion for + the asObject() call in JSCallbackObject::getOwnPropertySlot() has been + failing when using any nontrivial client of the JavaScriptCore API. + The cast isn't even necessary to call slot.setCustom(), so it should + be removed. + + * API/JSCallbackObjectFunctions.h: + (JSC::JSCallbackObject::getOwnPropertySlot): + +2008-11-10 Alexey Proskuryakov <ap@webkit.org> + + Reviewed by Adam Roben. + + A few coding style fixes for AVLTree. + + * wtf/AVLTree.h: Moved to WTF namespace, Removed "KJS_" from include guards. + (WTF::AVLTree::Iterator::start_iter): Fixed indentation + + * runtime/JSArray.cpp: Added "using namepace WTF". + +2008-11-09 Cameron Zwarich <zwarich@apple.com> + + Not reviewed. + + Speculatively fix the non-AllInOne build. + + * runtime/NativeErrorConstructor.cpp: + +2008-11-09 Darin Adler <darin@apple.com> + + Reviewed by Tim Hatcher. + + - https://bugs.webkit.org/show_bug.cgi?id=22149 + remove unused code from the parser + + * AllInOneFile.cpp: Removed nodes2string.cpp. + * GNUmakefile.am: Ditto. + * JavaScriptCore.exp: Ditto. + * JavaScriptCore.pri: Ditto. + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: Ditto. + * JavaScriptCore.xcodeproj/project.pbxproj: Ditto. + * JavaScriptCoreSources.bkl: Ditto. + + * VM/CodeBlock.h: Added include. + + * VM/Machine.cpp: (JSC::Machine::execute): Use the types from + DeclarationStacks as DeclarationStacks:: rather than Node:: since + "Node" really has little to do with it. + * bytecompiler/CodeGenerator.cpp: + (JSC::CodeGenerator::CodeGenerator): Ditto. + + * jsc.cpp: + (Options::Options): Removed prettyPrint option. + (runWithScripts): Ditto. + (printUsageStatement): Ditto. + (parseArguments): Ditto. + (jscmain): Ditto. + + * parser/Grammar.y: Removed use of obsolete ImmediateNumberNode. + + * parser/Nodes.cpp: + (JSC::ThrowableExpressionData::emitThrowError): Use inline functions + instead of direct member access for ThrowableExpressionData values. + (JSC::BracketAccessorNode::emitCode): Ditto. + (JSC::DotAccessorNode::emitCode): Ditto. + (JSC::NewExprNode::emitCode): Ditto. + (JSC::EvalFunctionCallNode::emitCode): Ditto. + (JSC::FunctionCallValueNode::emitCode): Ditto. + (JSC::FunctionCallResolveNode::emitCode): Ditto. + (JSC::FunctionCallBracketNode::emitCode): Ditto. + (JSC::FunctionCallDotNode::emitCode): Ditto. + (JSC::PostfixResolveNode::emitCode): Ditto. + (JSC::PostfixBracketNode::emitCode): Ditto. + (JSC::PostfixDotNode::emitCode): Ditto. + (JSC::DeleteResolveNode::emitCode): Ditto. + (JSC::DeleteBracketNode::emitCode): Ditto. + (JSC::DeleteDotNode::emitCode): Ditto. + (JSC::PrefixResolveNode::emitCode): Ditto. + (JSC::PrefixBracketNode::emitCode): Ditto. + (JSC::PrefixDotNode::emitCode): Ditto. + (JSC::ThrowableBinaryOpNode::emitCode): Ditto. + (JSC::InstanceOfNode::emitCode): Ditto. + (JSC::ReadModifyResolveNode::emitCode): Ditto. + (JSC::AssignResolveNode::emitCode): Ditto. + (JSC::AssignDotNode::emitCode): Ditto. + (JSC::ReadModifyDotNode::emitCode): Ditto. + (JSC::AssignBracketNode::emitCode): Ditto. + (JSC::ReadModifyBracketNode::emitCode): Ditto. + (JSC::statementListEmitCode): Take a const StatementVector instead + of a non-const one. Also removed unused statementListPushFIFO. + (JSC::ForInNode::emitCode): Inline functions instead of member access. + (JSC::ThrowNode::emitCode): Ditto. + (JSC::EvalNode::emitCode): Ditto. + (JSC::FunctionBodyNode::emitCode): Ditto. + (JSC::ProgramNode::emitCode): Ditto. + + * parser/Nodes.h: Removed unused includes and forward declarations. + Removed Precedence enum. Made many more members private instead of + protected or public. Removed unused NodeStack typedef. Moved the + VarStack and FunctionStack typedefs from Node to ScopeNode. Made + Node::emitCode pure virtual and changed classes that don't emit + any code to inherit from ParserRefCounted rather than Node. + Moved isReturnNode from Node to StatementNode. Removed the + streamTo, precedence, and needsParensIfLeftmost functions from + all classes. Removed the ImmediateNumberNode class and make + NumberNode::setValue nonvirtual. + + * parser/nodes2string.cpp: Removed. + +2008-11-09 Darin Adler <darin@apple.com> + + Reviewed by Sam Weinig and Maciej Stachowiak. + Includes some work done by Chris Brichford. + + - fix https://bugs.webkit.org/show_bug.cgi?id=14886 + Stack overflow due to deeply nested parse tree doing repeated string concatentation + + Test: fast/js/large-expressions.html + + 1) Code generation is recursive, so takes stack proportional to the complexity + of the source code expression. Fixed by setting an arbitrary recursion limit + of 10,000 nodes. + + 2) Destruction of the syntax tree was recursive. Fixed by introducing a + non-recursive mechanism for destroying the tree. + + * bytecompiler/CodeGenerator.cpp: + (JSC::CodeGenerator::CodeGenerator): Initialize depth to 0. + (JSC::CodeGenerator::emitThrowExpressionTooDeepException): Added. Emits the code + to throw a "too deep" exception. + * bytecompiler/CodeGenerator.h: + (JSC::CodeGenerator::emitNode): Check depth and emit an exception if we exceed + the maximum depth. + + * parser/Nodes.cpp: + (JSC::NodeReleaser::releaseAllNodes): Added. To be called inside node destructors + to avoid recursive calls to destructors for nodes inside this one. + (JSC::NodeReleaser::release): Added. To be called inside releaseNodes functions. + Also added releaseNodes functions and calls to releaseAllNodes inside destructors + for each class derived from Node that has RefPtr to other nodes. + (JSC::NodeReleaser::adopt): Added. Used by the release function. + (JSC::NodeReleaser::adoptFunctionBodyNode): Added. + + * parser/Nodes.h: Added declarations of releaseNodes and destructors in all classes + that needed it. Eliminated use of ListRefPtr and releaseNext, which are the two parts + of an older solution to the non-recursive destruction problem that works only for + lists, whereas the new solution works for other graphs. Changed ReverseBinaryOpNode + to use BinaryOpNode as a base class to avoid some duplicated code. + +2008-11-08 Kevin Ollivier <kevino@theolliviers.com> + + wx build fixes after addition of JSCore parser and bycompiler dirs. Also cleanup + the JSCore Bakefile's group names to be consistent. + + * JavaScriptCoreSources.bkl: + * jscore.bkl: + +2008-11-07 Cameron Zwarich <zwarich@apple.com> + + Reviewed by Geoff Garen. + + Bug 21801: REGRESSION (r37821): YUI date formatting JavaScript puts the letter 'd' in place of the day + <https://bugs.webkit.org/show_bug.cgi?id=21801> + + Fix the constant register check in the 'typeof' optimization in + CodeGenerator, which was completely broken after r37821. + + * bytecompiler/CodeGenerator.cpp: + (JSC::CodeGenerator::emitEqualityOp): + +2008-11-07 Cameron Zwarich <zwarich@apple.com> + + Reviewed by Geoff Garen. + + Bug 22129: Move CTI::isConstant() to CodeBlock + <https://bugs.webkit.org/show_bug.cgi?id=22129> + + * VM/CTI.cpp: + (JSC::CTI::emitGetArg): + (JSC::CTI::emitGetPutArg): + (JSC::CTI::getConstantImmediateNumericArg): + (JSC::CTI::printOpcodeOperandTypes): + (JSC::CTI::privateCompileMainPass): + * VM/CTI.h: + * VM/CodeBlock.h: + (JSC::CodeBlock::isConstant): + +2008-11-07 Alp Toker <alp@nuanti.com> + + autotools fix. Always use the configured perl binary (which may be + different to the one in $PATH) when generating sources. + + * GNUmakefile.am: + +2008-11-07 Cameron Zwarich <zwarich@apple.com> + + Not reviewed. + + Change grammar.cpp to Grammar.cpp and grammar.h to Grammar.h in several + build scripts. + + * DerivedSources.make: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: + * JavaScriptCoreSources.bkl: + +2008-11-07 Alp Toker <alp@nuanti.com> + + More grammar.cpp -> Grammar.cpp build fixes. + + * AllInOneFile.cpp: + * GNUmakefile.am: + +2008-11-07 Simon Hausmann <hausmann@webkit.org> + + Fix the build on case-sensitive file systems. grammar.y was renamed to + Grammar.y but Lexer.cpp includes grammar.h. The build bots didn't + notice this change because of stale files. + + * parser/Lexer.cpp: + +2008-11-07 Cameron Zwarich <zwarich@apple.com> + + Reviewed by Alexey Proskuryakov. + + Rename the m_nextGlobal, m_nextParameter, and m_nextConstant member + variables of CodeGenerator to m_nextGlobalIndex, m_nextParameterIndex, + and m_nextConstantIndex respectively. This is to distinguish these from + member variables like m_lastConstant, which are actually RefPtrs to + Registers. + + * bytecompiler/CodeGenerator.cpp: + (JSC::CodeGenerator::addGlobalVar): + (JSC::CodeGenerator::allocateConstants): + (JSC::CodeGenerator::CodeGenerator): + (JSC::CodeGenerator::addParameter): + (JSC::CodeGenerator::addConstant): + * bytecompiler/CodeGenerator.h: + +2008-11-06 Gavin Barraclough barraclough@apple.com + + Reviewed by Oliver Hunt. + + Do not make a cti_* call to perform an op_call unless either: + (1) The codeblock for the function body has not been generated. + (2) The number of arguments passed does not match the callee arity. + + ~1% progression on sunspider --v8 + + * VM/CTI.cpp: + (JSC::CTI::compileOpCallInitializeCallFrame): + (JSC::CTI::compileOpCall): + (JSC::CTI::privateCompileSlowCases): + * VM/CTI.h: + * VM/Machine.cpp: + (JSC::Machine::cti_op_call_JSFunction): + (JSC::Machine::cti_op_call_arityCheck): + (JSC::Machine::cti_op_construct_JSConstruct): + * VM/Machine.h: + * kjs/nodes.h: + +2008-11-06 Cameron Zwarich <zwarich@apple.com> + + Reviewed by Geoff Garen. + + Move the remaining files in the kjs subdirectory of JavaScriptCore to + a new parser subdirectory, and remove the kjs subdirectory entirely. + + * AllInOneFile.cpp: + * DerivedSources.make: + * GNUmakefile.am: + * JavaScriptCore.pri: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: + * JavaScriptCore.vcproj/WTF/WTF.vcproj: + * JavaScriptCore.vcproj/jsc/jsc.vcproj: + * JavaScriptCore.xcodeproj/project.pbxproj: + * JavaScriptCoreSources.bkl: + * VM/CodeBlock.h: + * VM/ExceptionHelpers.cpp: + * VM/SamplingTool.h: + * bytecompiler/CodeGenerator.h: + * jsc.pro: + * jscore.bkl: + * kjs: Removed. + * kjs/NodeInfo.h: Removed. + * kjs/Parser.cpp: Removed. + * kjs/Parser.h: Removed. + * kjs/ResultType.h: Removed. + * kjs/SourceCode.h: Removed. + * kjs/SourceProvider.h: Removed. + * kjs/grammar.y: Removed. + * kjs/keywords.table: Removed. + * kjs/lexer.cpp: Removed. + * kjs/lexer.h: Removed. + * kjs/nodes.cpp: Removed. + * kjs/nodes.h: Removed. + * kjs/nodes2string.cpp: Removed. + * parser: Added. + * parser/Grammar.y: Copied from kjs/grammar.y. + * parser/Keywords.table: Copied from kjs/keywords.table. + * parser/Lexer.cpp: Copied from kjs/lexer.cpp. + * parser/Lexer.h: Copied from kjs/lexer.h. + * parser/NodeInfo.h: Copied from kjs/NodeInfo.h. + * parser/Nodes.cpp: Copied from kjs/nodes.cpp. + * parser/Nodes.h: Copied from kjs/nodes.h. + * parser/Parser.cpp: Copied from kjs/Parser.cpp. + * parser/Parser.h: Copied from kjs/Parser.h. + * parser/ResultType.h: Copied from kjs/ResultType.h. + * parser/SourceCode.h: Copied from kjs/SourceCode.h. + * parser/SourceProvider.h: Copied from kjs/SourceProvider.h. + * parser/nodes2string.cpp: Copied from kjs/nodes2string.cpp. + * pcre/pcre.pri: + * pcre/pcre_exec.cpp: + * runtime/FunctionConstructor.cpp: + * runtime/JSActivation.h: + * runtime/JSFunction.h: + * runtime/JSGlobalData.cpp: + * runtime/JSGlobalObjectFunctions.cpp: + * runtime/JSObject.cpp: + (JSC::JSObject::toNumber): + * runtime/RegExp.cpp: + +2008-11-06 Adam Roben <aroben@apple.com> + + Windows build fix after r38196 + + * JavaScriptCore.vcproj/jsc/jsc.vcproj: Added bytecompiler/ to the + include path. + +2008-11-06 Cameron Zwarich <zwarich@apple.com> + + Rubber-stamped by Sam Weinig. + + Create a new bytecompiler subdirectory of JavaScriptCore and move some + relevant files to it. + + * AllInOneFile.cpp: + * GNUmakefile.am: + * JavaScriptCore.pri: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: + * JavaScriptCore.xcodeproj/project.pbxproj: + * JavaScriptCoreSources.bkl: + * VM/CodeGenerator.cpp: Removed. + * VM/CodeGenerator.h: Removed. + * bytecompiler: Added. + * bytecompiler/CodeGenerator.cpp: Copied from VM/CodeGenerator.cpp. + * bytecompiler/CodeGenerator.h: Copied from VM/CodeGenerator.h. + * bytecompiler/LabelScope.h: Copied from kjs/LabelScope.h. + * jscore.bkl: + * kjs/LabelScope.h: Removed. + +2008-11-06 Adam Roben <aroben@apple.com> + + Windows clean build fix after r38155 + + Rubberstamped by Cameron Zwarich. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: Update + the post-build event for the move of create_hash_table out of kjs/. + +2008-11-06 Laszlo Gombos <laszlo.1.gombos@nokia.com> + + Reviewed by Darin Adler. + + https://bugs.webkit.org/show_bug.cgi?id=22107 + + Bug uncovered during RVCT port in functions not used. get_lt() and + get_gt() takes only one argument - remove second argument where + applicable. + + * wtf/AVLTree.h: + (JSC::AVLTree::remove): Remove second argument of get_lt/get_gt(). + (JSC::AVLTree::subst): Ditto. + +2008-11-06 Alp Toker <alp@nuanti.com> + + Reviewed by Cameron Zwarich. + + https://bugs.webkit.org/show_bug.cgi?id=22033 + [GTK] CTI/Linux r38064 crashes; JIT requires executable memory + + Mark pages allocated by the FastMalloc mmap code path executable with + PROT_EXEC. This fixes crashes seen on CPUs and kernels that enforce + non-executable memory (like ExecShield on Fedora Linux) when the JIT + is enabled. + + This patch does not resolve the issue on debug builds so affected + developers may still need to pass --disable-jit to configure. + + * wtf/TCSystemAlloc.cpp: + (TryMmap): + (TryDevMem): + (TCMalloc_SystemRelease): + +2008-11-06 Peter Gal <galpeter@inf.u-szeged.hu> + + Reviewed by Cameron Zwarich. + + Bug 22099: Make the Qt port build the JSC shell in the correct place + <https://bugs.webkit.org/show_bug.cgi?id=22099> + + Adjust include paths and build destination dir for the 'jsc' executable + in the Qt build. + + * jsc.pro: + +2008-11-06 Kristian Amlie <kristian.amlie@nokia.com> + + Reviewed by Simon Hausmann. + + Implemented the block allocation on Symbian through heap allocation. + + Unfortunately there is no way to allocate virtual memory. The Posix + layer provides mmap() but no anonymous mapping. So this is a very slow + solution but it should work as a start. + + * runtime/Collector.cpp: + (JSC::allocateBlock): + (JSC::freeBlock): + +2008-11-06 Laszlo Gombos <laszlo.1.gombos@nokia.com> + + Reviewed by Simon Hausmann. + + Borrow some math functions from the MSVC port to the build with the + RVCT compiler. + + * wtf/MathExtras.h: + (isinf): + (isnan): + (signbit): + +2008-11-06 Laszlo Gombos <laszlo.1.gombos@nokia.com> + + Reviewed by Simon Hausmann. + + Include strings.h for strncasecmp(). + This is needed for compilation inside Symbian and it is also + confirmed by the man-page on Linux. + + * runtime/DateMath.cpp: + +2008-11-06 Norbert Leser <norbert.leser@nokia.com> + + Reviewed by Simon Hausmann. + + Implemented currentThreadStackBase for Symbian. + + * runtime/Collector.cpp: + (JSC::currentThreadStackBase): + +2008-11-06 Laszlo Gombos <laszlo.1.gombos@nokia.com> + + Reviewed by Simon Hausmann. + + RVCT does not support tm_gmtoff field, so disable that code just like + for MSVC. + + * runtime/DateMath.h: + (JSC::GregorianDateTime::GregorianDateTime): + (JSC::GregorianDateTime::operator tm): + +2008-11-06 Kristian Amlie <kristian.amlie@nokia.com> + + Reviewed by Simon Hausmann. + + Define PLATFORM(UNIX) for S60. Effectively WebKit on S60 is compiled + on top of the Posix layer. + + * wtf/Platform.h: + +2008-11-06 Norbert Leser <norbert.leser@nokia.com> + + Reviewed by Simon Hausmann. + + Added __SYMBIAN32__ condition for defining PLATFORM(SYMBIAN). + + * wtf/Platform.h: + +2008-11-06 Ariya Hidayat <ariya.hidayat@trolltech.com> + + Reviewed by Simon Hausmann. + + Added WINSCW compiler define for Symbian S60. + + * wtf/Platform.h: + +2008-11-06 Kristian Amlie <kristian.amlie@nokia.com> + + Reviewed by Simon Hausmann. + + Use the GCC defines of the WTF_ALIGN* macros for the RVCT and the + MINSCW compiler. + + * wtf/Vector.h: + +2008-11-06 Kristian Amlie <kristian.amlie@nokia.com> + + Reviewed by Simon Hausmann. + + Define capabilities of the SYMBIAN platform. Some of the system + headers are actually dependent on RVCT. + + * wtf/Platform.h: + +2008-11-06 Kristian Amlie <kristian.amlie@nokia.com> + + Reviewed by Simon Hausmann. + + Add missing stddef.h header needed for compilation in Symbian. + + * runtime/Collector.h: + +2008-11-06 Kristian Amlie <kristian.amlie@nokia.com> + + Reviewed by Simon Hausmann. + + Added COMPILER(RVCT) to detect the ARM RVCT compiler used in the Symbian environment. + + * wtf/Platform.h: + +2008-11-06 Simon Hausmann <hausmann@webkit.org> + + Fix the Qt build, adjust include paths after move of jsc.pro. + + * jsc.pro: + +2008-11-06 Cameron Zwarich <zwarich@apple.com> + + Rubber-stamped by Sam Weinig. + + Move kjs/Shell.cpp to the top level of the JavaScriptCore directory and + rename it to jsc.cpp to reflect the name of the binary compiled from it. + + * GNUmakefile.am: + * JavaScriptCore.vcproj/jsc/jsc.vcproj: + * JavaScriptCore.xcodeproj/project.pbxproj: + * jsc.cpp: Copied from kjs/Shell.cpp. + * jsc.pro: + * jscore.bkl: + * kjs/Shell.cpp: Removed. + +2008-11-06 Cameron Zwarich <zwarich@apple.com> + + Rubber-stamped by Sam Weinig. + + Move create_hash_table and jsc.pro out of the kjs directory and into the + root directory of JavaScriptCore. + + * DerivedSources.make: + * JavaScriptCore.pri: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: + * JavaScriptCore.xcodeproj/project.pbxproj: + * create_hash_table: Copied from kjs/create_hash_table. + * jsc.pro: Copied from kjs/jsc.pro. + * kjs/create_hash_table: Removed. + * kjs/jsc.pro: Removed. + * make-generated-sources.sh: + +2008-11-05 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Maciej Stachowiak. + + https://bugs.webkit.org/show_bug.cgi?id=22094 + + Fix for bug where the callee incorrectly recieves the caller's lexical + global object as this, rather than its own. Implementation closely + follows the spec, passing jsNull, checking in the callee and replacing + with the global object where necessary. + + * VM/CTI.cpp: + (JSC::CTI::compileOpCall): + * VM/Machine.cpp: + (JSC::Machine::cti_op_call_NotJSFunction): + (JSC::Machine::cti_op_call_eval): + * runtime/JSCell.h: + (JSC::JSValue::toThisObject): + * runtime/JSImmediate.cpp: + (JSC::JSImmediate::toThisObject): + * runtime/JSImmediate.h: + +2008-11-05 Kevin Ollivier <kevino@theolliviers.com> + + wx build fix after Operations.cpp move. + + * JavaScriptCoreSources.bkl: + +2008-11-05 Cameron Zwarich <zwarich@apple.com> + + Not reviewed. + + Fix the build for case-sensitive build systems and wxWindows. + + * JavaScriptCoreSources.bkl: + * kjs/create_hash_table: + +2008-11-05 Cameron Zwarich <zwarich@apple.com> + + Not reviewed. + + Fix the build for case-sensitive build systems. + + * JavaScriptCoreSources.bkl: + * kjs/Shell.cpp: + * runtime/Interpreter.cpp: + * runtime/JSArray.cpp: + +2008-11-05 Cameron Zwarich <zwarich@apple.com> + + Not reviewed. + + Fix the build for case-sensitive build systems. + + * API/JSBase.cpp: + * API/JSObjectRef.cpp: + * runtime/CommonIdentifiers.h: + * runtime/Identifier.cpp: + * runtime/InitializeThreading.cpp: + * runtime/InternalFunction.h: + * runtime/JSString.h: + * runtime/Lookup.h: + * runtime/PropertyNameArray.h: + * runtime/PropertySlot.h: + * runtime/StructureID.cpp: + * runtime/StructureID.h: + * runtime/UString.cpp: + +2008-11-05 Cameron Zwarich <zwarich@apple.com> + + Rubber-stamped by Sam Weinig. + + Move more files to the runtime subdirectory of JavaScriptCore. + + * API/APICast.h: + * API/JSBase.cpp: + * API/JSCallbackObject.cpp: + * API/JSClassRef.cpp: + * API/JSClassRef.h: + * API/JSStringRefCF.cpp: + * API/JSValueRef.cpp: + * API/OpaqueJSString.cpp: + * API/OpaqueJSString.h: + * AllInOneFile.cpp: + * GNUmakefile.am: + * JavaScriptCore.pri: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: + * JavaScriptCore.xcodeproj/project.pbxproj: + * JavaScriptCoreSources.bkl: + * VM/CodeBlock.h: + * VM/CodeGenerator.cpp: + * VM/Machine.cpp: + * VM/RegisterFile.h: + * debugger/Debugger.h: + * kjs/SourceProvider.h: + * kjs/TypeInfo.h: Removed. + * kjs/collector.cpp: Removed. + * kjs/collector.h: Removed. + * kjs/completion.h: Removed. + * kjs/create_hash_table: + * kjs/identifier.cpp: Removed. + * kjs/identifier.h: Removed. + * kjs/interpreter.cpp: Removed. + * kjs/interpreter.h: Removed. + * kjs/lexer.cpp: + * kjs/lexer.h: + * kjs/lookup.cpp: Removed. + * kjs/lookup.h: Removed. + * kjs/nodes.cpp: + * kjs/nodes.h: + * kjs/operations.cpp: Removed. + * kjs/operations.h: Removed. + * kjs/protect.h: Removed. + * kjs/regexp.cpp: Removed. + * kjs/regexp.h: Removed. + * kjs/ustring.cpp: Removed. + * kjs/ustring.h: Removed. + * pcre/pcre_exec.cpp: + * profiler/CallIdentifier.h: + * profiler/Profile.h: + * runtime/ArrayConstructor.cpp: + * runtime/ArrayPrototype.cpp: + * runtime/ArrayPrototype.h: + * runtime/Collector.cpp: Copied from kjs/collector.cpp. + * runtime/Collector.h: Copied from kjs/collector.h. + * runtime/CollectorHeapIterator.h: + * runtime/Completion.h: Copied from kjs/completion.h. + * runtime/ErrorPrototype.cpp: + * runtime/Identifier.cpp: Copied from kjs/identifier.cpp. + * runtime/Identifier.h: Copied from kjs/identifier.h. + * runtime/InitializeThreading.cpp: + * runtime/Interpreter.cpp: Copied from kjs/interpreter.cpp. + * runtime/Interpreter.h: Copied from kjs/interpreter.h. + * runtime/JSCell.h: + * runtime/JSGlobalData.cpp: + * runtime/JSGlobalData.h: + * runtime/JSLock.cpp: + * runtime/JSNumberCell.cpp: + * runtime/JSNumberCell.h: + * runtime/JSObject.cpp: + * runtime/JSValue.h: + * runtime/Lookup.cpp: Copied from kjs/lookup.cpp. + * runtime/Lookup.h: Copied from kjs/lookup.h. + * runtime/MathObject.cpp: + * runtime/NativeErrorPrototype.cpp: + * runtime/NumberPrototype.cpp: + * runtime/Operations.cpp: Copied from kjs/operations.cpp. + * runtime/Operations.h: Copied from kjs/operations.h. + * runtime/PropertyMapHashTable.h: + * runtime/Protect.h: Copied from kjs/protect.h. + * runtime/RegExp.cpp: Copied from kjs/regexp.cpp. + * runtime/RegExp.h: Copied from kjs/regexp.h. + * runtime/RegExpConstructor.cpp: + * runtime/RegExpObject.h: + * runtime/RegExpPrototype.cpp: + * runtime/SmallStrings.h: + * runtime/StringObjectThatMasqueradesAsUndefined.h: + * runtime/StructureID.cpp: + * runtime/StructureID.h: + * runtime/StructureIDTransitionTable.h: + * runtime/SymbolTable.h: + * runtime/TypeInfo.h: Copied from kjs/TypeInfo.h. + * runtime/UString.cpp: Copied from kjs/ustring.cpp. + * runtime/UString.h: Copied from kjs/ustring.h. + * wrec/CharacterClassConstructor.h: + * wrec/WREC.h: + +2008-11-05 Geoffrey Garen <ggaren@apple.com> + + Suggested by Darin Adler. + + Removed two copy constructors that the compiler can generate for us + automatically. + + * VM/LabelID.h: + (JSC::LabelID::setLocation): + (JSC::LabelID::offsetFrom): + (JSC::LabelID::ref): + (JSC::LabelID::refCount): + * kjs/LabelScope.h: + +2008-11-05 Anders Carlsson <andersca@apple.com> + + Fix Snow Leopard build. + + * JavaScriptCore.xcodeproj/project.pbxproj: + +2008-11-04 Cameron Zwarich <zwarich@apple.com> + + Rubber-stamped by Steve Falkenburg. + + Move dtoa.cpp and dtoa.h to the WTF Visual Studio project to reflect + their movement in the filesystem. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: + * JavaScriptCore.vcproj/WTF/WTF.vcproj: + +2008-11-04 Cameron Zwarich <zwarich@apple.com> + + Rubber-stamped by Sam Weinig. + + Move kjs/dtoa.h to the wtf subdirectory of JavaScriptCore. + + * AllInOneFile.cpp: + * GNUmakefile.am: + * JavaScriptCore.pri: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: + * JavaScriptCore.xcodeproj/project.pbxproj: + * JavaScriptCoreSources.bkl: + * kjs/dtoa.cpp: Removed. + * kjs/dtoa.h: Removed. + * wtf/dtoa.cpp: Copied from kjs/dtoa.cpp. + * wtf/dtoa.h: Copied from kjs/dtoa.h. + +2008-11-04 Cameron Zwarich <zwarich@apple.com> + + Rubber-stamped by Sam Weinig. + + Move kjs/config.h to the top level of JavaScriptCore. + + * GNUmakefile.am: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: + * JavaScriptCore.xcodeproj/project.pbxproj: + * config.h: Copied from kjs/config.h. + * kjs/config.h: Removed. + +2008-11-04 Darin Adler <darin@apple.com> + + Reviewed by Tim Hatcher. + + * wtf/ThreadingNone.cpp: Tweak formatting. + +2008-11-03 Darin Adler <darin@apple.com> + + Reviewed by Tim Hatcher. + + - https://bugs.webkit.org/show_bug.cgi?id=22061 + create script to check for exit-time destructors + + * JavaScriptCore.exp: Changed to export functions rather than + a global for the atomically initialized static mutex. + + * JavaScriptCore.xcodeproj/project.pbxproj: Added a script + phase that runs the check-for-exit-time-destructors script. + + * wtf/MainThread.cpp: + (WTF::mainThreadFunctionQueueMutex): Changed to leak an object + rather than using an exit time destructor. + (WTF::functionQueue): Ditto. + * wtf/unicode/icu/CollatorICU.cpp: + (WTF::cachedCollatorMutex): Ditto. + + * wtf/Threading.h: Changed other platforms to share the Windows + approach where the mutex is internal and the functions are exported. + * wtf/ThreadingGtk.cpp: + (WTF::lockAtomicallyInitializedStaticMutex): Ditto. + (WTF::unlockAtomicallyInitializedStaticMutex): Ditto. + * wtf/ThreadingNone.cpp: + (WTF::lockAtomicallyInitializedStaticMutex): Ditto. + (WTF::unlockAtomicallyInitializedStaticMutex): Ditto. + * wtf/ThreadingPthreads.cpp: + (WTF::threadMapMutex): Changed to leak an object rather than using + an exit time destructor. + (WTF::lockAtomicallyInitializedStaticMutex): Mutex change. + (WTF::unlockAtomicallyInitializedStaticMutex): Ditto. + (WTF::threadMap): Changed to leak an object rather than using + an exit time destructor. + * wtf/ThreadingQt.cpp: + (WTF::lockAtomicallyInitializedStaticMutex): Mutex change. + (WTF::unlockAtomicallyInitializedStaticMutex): Ditto. + * wtf/ThreadingWin.cpp: + (WTF::lockAtomicallyInitializedStaticMutex): Added an assertion. + 2008-11-04 Adam Roben <aroben@apple.com> Windows build fix @@ -7667,7 +21201,7 @@ 2008-09-23 Maciej Stachowiak <mjs@apple.com> - Reviewed by Camron Zwarich. + Reviewed by Cameron Zwarich. - inline the fast case of instanceof https://bugs.webkit.org/show_bug.cgi?id=20818 diff --git a/JavaScriptCore/Configurations/Base.xcconfig b/JavaScriptCore/Configurations/Base.xcconfig index 0abb45d..4154cb8 100644 --- a/JavaScriptCore/Configurations/Base.xcconfig +++ b/JavaScriptCore/Configurations/Base.xcconfig @@ -10,6 +10,7 @@ GCC_ENABLE_SYMBOL_SEPARATION = NO; GCC_FAST_OBJC_DISPATCH = YES; GCC_INLINES_ARE_PRIVATE_EXTERN = YES; GCC_MODEL_TUNING = G5; +GCC_OBJC_CALL_CXX_CDTORS = YES; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREPROCESSOR_DEFINITIONS = $(DEBUG_DEFINES) WEBKIT_VERSION_MIN_REQUIRED=WEBKIT_VERSION_LATEST $(GCC_PREPROCESSOR_DEFINITIONS); GCC_STRICT_ALIASING = YES; @@ -23,7 +24,7 @@ LINKER_DISPLAYS_MANGLED_NAMES = YES; PREBINDING = NO; VALID_ARCHS = i386 ppc x86_64 ppc64; WARNING_CFLAGS = $(WARNING_CFLAGS_$(CURRENT_ARCH)); -WARNING_CFLAGS_BASE = -Wall -W -Wcast-align -Wchar-subscripts -Wformat-security -Wmissing-format-attribute -Wpointer-arith -Wwrite-strings -Wno-format-y2k -Wundef; +WARNING_CFLAGS_BASE = -Wall -Wextra -Wcast-align -Wcast-qual -Wchar-subscripts -Wextra-tokens -Wformat=2 -Winit-self -Wmissing-format-attribute -Wmissing-noreturn -Wpacked -Wpointer-arith -Wredundant-decls -Wundef -Wwrite-strings; WARNING_CFLAGS_ = $(WARNING_CFLAGS_BASE) -Wshorten-64-to-32; WARNING_CFLAGS_i386 = $(WARNING_CFLAGS_BASE) -Wshorten-64-to-32; WARNING_CFLAGS_ppc = $(WARNING_CFLAGS_BASE) -Wshorten-64-to-32; @@ -52,6 +53,10 @@ DEAD_CODE_STRIPPING_normal = YES; DEAD_CODE_STRIPPING = $(DEAD_CODE_STRIPPING_$(CURRENT_VARIANT)); +GCC_VERSION = $(GCC_VERSION_$(XCODE_VERSION_ACTUAL)); +GCC_VERSION_0310 = 4.2; + + // <rdar://problem/5488678>: Production builds on 10.4 PowerPC need to have debugging symbols disabled to prevent a huge STABS section being generated. // Xcode on 10.4 does not define MAC_OS_X_VERSION_MAJOR, so the default Mac OS X version is treated as 10.4. GCC_GENERATE_DEBUGGING_SYMBOLS = $(GCC_GENERATE_DEBUGGING_SYMBOLS_$(CURRENT_ARCH)); diff --git a/JavaScriptCore/Configurations/DebugRelease.xcconfig b/JavaScriptCore/Configurations/DebugRelease.xcconfig index 0515da4..cbb2933 100644 --- a/JavaScriptCore/Configurations/DebugRelease.xcconfig +++ b/JavaScriptCore/Configurations/DebugRelease.xcconfig @@ -8,7 +8,3 @@ MACOSX_DEPLOYMENT_TARGET_1050 = 10.5; MACOSX_DEPLOYMENT_TARGET_1060 = 10.6; GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = YES; - -GCC_VERSION = $(GCC_VERSION_$(XCODE_VERSION_ACTUAL)); -GCC_VERSION_0310 = 4.2; -GCC_VERSION_0311 = 4.2; diff --git a/JavaScriptCore/Configurations/JavaScriptCore.xcconfig b/JavaScriptCore/Configurations/JavaScriptCore.xcconfig index 8e3d3c0..ef199d2 100644 --- a/JavaScriptCore/Configurations/JavaScriptCore.xcconfig +++ b/JavaScriptCore/Configurations/JavaScriptCore.xcconfig @@ -13,8 +13,11 @@ INSTALL_PATH = $(SYSTEM_LIBRARY_DIR)/Frameworks; PRODUCT_NAME = JavaScriptCore; // This needs to be kept sorted, and in sync with FEATURE_DEFINES in WebCore.xcconfig, WebKit.xcconfig and the default settings of build-webkit. -FEATURE_DEFINES = ENABLE_DATABASE ENABLE_DOM_STORAGE ENABLE_ICONDATABASE ENABLE_OFFLINE_WEB_APPLICATIONS ENABLE_SVG ENABLE_SVG_ANIMATION ENABLE_SVG_AS_IMAGE ENABLE_SVG_FONTS ENABLE_SVG_FOREIGN_OBJECT ENABLE_SVG_USE ENABLE_VIDEO ENABLE_XPATH ENABLE_XSLT; +FEATURE_DEFINES = ENABLE_DATABASE ENABLE_DOM_STORAGE ENABLE_ICONDATABASE ENABLE_OFFLINE_WEB_APPLICATIONS ENABLE_SVG ENABLE_SVG_ANIMATION ENABLE_SVG_AS_IMAGE ENABLE_SVG_FONTS ENABLE_SVG_FOREIGN_OBJECT ENABLE_SVG_USE ENABLE_VIDEO ENABLE_WORKERS ENABLE_XPATH ENABLE_XSLT; OTHER_CFLAGS = $(OTHER_CFLAGS_$(CONFIGURATION)_$(CURRENT_VARIANT)); -OTHER_CFLAGS_Release_normal = -fomit-frame-pointer; -OTHER_CFLAGS_Production_normal = -fomit-frame-pointer; +OTHER_CFLAGS_Release_normal = $(OTHER_CFLAGS_normal_$(XCODE_VERSION_ACTUAL)); +OTHER_CFLAGS_Production_normal = $(OTHER_CFLAGS_normal_$(XCODE_VERSION_ACTUAL)); +OTHER_CFLAGS_normal_0310 = $(OTHER_CFLAGS_normal_GCC_42); +OTHER_CFLAGS_normal_0320 = $(OTHER_CFLAGS_normal_GCC_42); +OTHER_CFLAGS_normal_GCC_42 = -fomit-frame-pointer -funwind-tables; diff --git a/JavaScriptCore/Configurations/Version.xcconfig b/JavaScriptCore/Configurations/Version.xcconfig index 16698b9..16a349c 100644 --- a/JavaScriptCore/Configurations/Version.xcconfig +++ b/JavaScriptCore/Configurations/Version.xcconfig @@ -1,5 +1,5 @@ MAJOR_VERSION = 528; -MINOR_VERSION = 5; +MINOR_VERSION = 15; TINY_VERSION = 0; FULL_VERSION = $(MAJOR_VERSION).$(MINOR_VERSION); diff --git a/JavaScriptCore/DerivedSources.make b/JavaScriptCore/DerivedSources.make index e152979..4b33682 100644 --- a/JavaScriptCore/DerivedSources.make +++ b/JavaScriptCore/DerivedSources.make @@ -1,4 +1,4 @@ -# Copyright (C) 2006 Apple Computer, Inc. All rights reserved. +# Copyright (C) 2006, 2007, 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 @@ -25,11 +25,13 @@ # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. VPATH = \ - $(JavaScriptCore)/kjs \ - $(JavaScriptCore)/VM \ + $(JavaScriptCore) \ + $(JavaScriptCore)/parser \ $(JavaScriptCore)/pcre \ $(JavaScriptCore)/docs \ $(JavaScriptCore)/runtime \ + $(JavaScriptCore)/interpreter \ + $(JavaScriptCore)/jit \ # .PHONY : all @@ -37,37 +39,37 @@ all : \ ArrayPrototype.lut.h \ chartables.c \ DatePrototype.lut.h \ - grammar.cpp \ - lexer.lut.h \ + Grammar.cpp \ + Lexer.lut.h \ MathObject.lut.h \ NumberConstructor.lut.h \ RegExpConstructor.lut.h \ RegExpObject.lut.h \ StringPrototype.lut.h \ - $(JavaScriptCore)/docs/bytecode.html \ + docs/bytecode.html \ # # lookup tables for classes %.lut.h: create_hash_table %.cpp $^ -i > $@ -lexer.lut.h: create_hash_table keywords.table +Lexer.lut.h: create_hash_table Keywords.table $^ > $@ # JavaScript language grammar -grammar.cpp: grammar.y - bison -d -p kjsyy $< -o $@ > bison_out.txt 2>&1 - perl -p -e 'END { if ($$conflict) { unlink "grammar.cpp"; die; } } $$conflict ||= /conflict/' < bison_out.txt - touch grammar.cpp.h - touch grammar.hpp - cat grammar.cpp.h grammar.hpp > grammar.h - rm -f grammar.cpp.h grammar.hpp bison_out.txt +Grammar.cpp: Grammar.y + bison -d -p jscyy $< -o $@ > bison_out.txt 2>&1 + perl -p -e 'END { if ($$conflict) { unlink "Grammar.cpp"; die; } } $$conflict ||= /conflict/' < bison_out.txt + touch Grammar.cpp.h + touch Grammar.hpp + cat Grammar.cpp.h Grammar.hpp > Grammar.h + rm -f Grammar.cpp.h Grammar.hpp bison_out.txt # character tables for PCRE chartables.c : dftables $^ $@ -$(JavaScriptCore)/docs/bytecode.html: make-bytecode-docs.pl Machine.cpp +docs/bytecode.html: make-bytecode-docs.pl Interpreter.cpp perl $^ $@ diff --git a/JavaScriptCore/ForwardingHeaders/JavaScriptCore/JSLock.h b/JavaScriptCore/ForwardingHeaders/JavaScriptCore/JSLock.h deleted file mode 100644 index 8519612..0000000 --- a/JavaScriptCore/ForwardingHeaders/JavaScriptCore/JSLock.h +++ /dev/null @@ -1 +0,0 @@ -#include <kjs/JSLock.h> diff --git a/JavaScriptCore/GNUmakefile.am b/JavaScriptCore/GNUmakefile.am index 2c52190..3d90470 100644 --- a/JavaScriptCore/GNUmakefile.am +++ b/JavaScriptCore/GNUmakefile.am @@ -1,14 +1,20 @@ javascriptcore_cppflags += \ -I$(srcdir)/JavaScriptCore/API \ -I$(srcdir)/JavaScriptCore/ForwardingHeaders \ - -I$(srcdir)/JavaScriptCore/VM \ + -I$(srcdir)/JavaScriptCore/interpreter \ + -I$(srcdir)/JavaScriptCore/bytecode \ + -I$(srcdir)/JavaScriptCore/bytecompiler \ -I$(srcdir)/JavaScriptCore/debugger \ + -I$(srcdir)/JavaScriptCore/jit \ -I$(srcdir)/JavaScriptCore/pcre \ -I$(srcdir)/JavaScriptCore/profiler \ -I$(srcdir)/JavaScriptCore/runtime \ + -I$(srcdir)/JavaScriptCore/wrec \ + -I$(srcdir)/JavaScriptCore/jit \ + -I$(srcdir)/JavaScriptCore/assembler \ -I$(srcdir)/JavaScriptCore/wtf/unicode \ -I$(top_builddir)/JavaScriptCore/pcre \ - -I$(top_builddir)/JavaScriptCore/kjs \ + -I$(top_builddir)/JavaScriptCore/parser \ -I$(top_builddir)/JavaScriptCore/runtime javascriptcore_h_api += \ @@ -24,7 +30,7 @@ javascriptcore_h_api += \ JavaScriptCore/API/WebKitAvailability.h javascriptcore_built_nosources += \ - DerivedSources/lexer.lut.h \ + DerivedSources/Lexer.lut.h \ JavaScriptCore/runtime/ArrayPrototype.lut.h \ JavaScriptCore/runtime/DatePrototype.lut.h \ JavaScriptCore/runtime/MathObject.lut.h \ @@ -67,27 +73,40 @@ javascriptcore_sources += \ JavaScriptCore/ForwardingHeaders/JavaScriptCore/OpaqueJSString.h \ JavaScriptCore/ForwardingHeaders/JavaScriptCore/WebKitAvailability.h \ JavaScriptCore/JavaScriptCorePrefix.h \ - JavaScriptCore/VM/CTI.cpp \ - JavaScriptCore/VM/CTI.h \ - JavaScriptCore/VM/CodeBlock.cpp \ - JavaScriptCore/VM/CodeBlock.h \ - JavaScriptCore/VM/CodeGenerator.h \ - JavaScriptCore/VM/ExceptionHelpers.cpp \ - JavaScriptCore/VM/ExceptionHelpers.h \ - JavaScriptCore/VM/Instruction.h \ - JavaScriptCore/runtime/JSPropertyNameIterator.cpp \ - JavaScriptCore/runtime/JSPropertyNameIterator.h \ - JavaScriptCore/VM/LabelID.h \ - JavaScriptCore/VM/Machine.cpp \ - JavaScriptCore/VM/Machine.h \ - JavaScriptCore/VM/Opcode.cpp \ - JavaScriptCore/VM/Opcode.h \ - JavaScriptCore/VM/Register.h \ - JavaScriptCore/VM/RegisterFile.h \ - JavaScriptCore/VM/RegisterID.h \ - JavaScriptCore/VM/SamplingTool.cpp \ - JavaScriptCore/VM/SamplingTool.h \ - JavaScriptCore/VM/SegmentedVector.h \ + JavaScriptCore/jit/ExecutableAllocator.h \ + JavaScriptCore/jit/JIT.cpp \ + JavaScriptCore/jit/JITCall.cpp \ + JavaScriptCore/jit/JITPropertyAccess.cpp \ + JavaScriptCore/jit/JITArithmetic.cpp \ + JavaScriptCore/jit/ExecutableAllocator.cpp \ + JavaScriptCore/jit/ExecutableAllocatorPosix.cpp \ + JavaScriptCore/jit/JIT.h \ + JavaScriptCore/jit/JITInlineMethods.h \ + JavaScriptCore/bytecode/StructureStubInfo.cpp \ + JavaScriptCore/bytecode/StructureStubInfo.h \ + JavaScriptCore/bytecode/CodeBlock.cpp \ + JavaScriptCore/bytecode/CodeBlock.h \ + JavaScriptCore/bytecode/JumpTable.cpp \ + JavaScriptCore/bytecode/JumpTable.h \ + JavaScriptCore/bytecode/EvalCodeCache.h \ + JavaScriptCore/runtime/ExceptionHelpers.cpp \ + JavaScriptCore/runtime/ExceptionHelpers.h \ + JavaScriptCore/bytecode/Instruction.h \ + JavaScriptCore/bytecompiler/Label.h \ + JavaScriptCore/interpreter/Interpreter.cpp \ + JavaScriptCore/interpreter/Interpreter.h \ + JavaScriptCore/bytecode/Opcode.cpp \ + JavaScriptCore/bytecode/Opcode.h \ + JavaScriptCore/interpreter/Register.h \ + JavaScriptCore/bytecompiler/RegisterID.h \ + JavaScriptCore/bytecode/SamplingTool.cpp \ + JavaScriptCore/bytecode/SamplingTool.h \ + JavaScriptCore/bytecompiler/SegmentedVector.h \ + JavaScriptCore/config.h \ + JavaScriptCore/debugger/DebuggerActivation.cpp \ + JavaScriptCore/debugger/DebuggerActivation.h \ + JavaScriptCore/debugger/DebuggerCallFrame.cpp \ + JavaScriptCore/debugger/DebuggerCallFrame.h \ JavaScriptCore/icu/unicode/parseerr.h \ JavaScriptCore/icu/unicode/platform.h \ JavaScriptCore/icu/unicode/putil.h \ @@ -110,52 +129,9 @@ javascriptcore_sources += \ JavaScriptCore/icu/unicode/utf_old.h \ JavaScriptCore/icu/unicode/utypes.h \ JavaScriptCore/icu/unicode/uversion.h \ - JavaScriptCore/runtime/ArgList.h \ - JavaScriptCore/runtime/Arguments.h \ - JavaScriptCore/runtime/BatchedTransitionOptimizer.h \ - JavaScriptCore/runtime/CollectorHeapIterator.h \ - JavaScriptCore/debugger/DebuggerCallFrame.cpp \ - JavaScriptCore/debugger/DebuggerCallFrame.h \ - JavaScriptCore/runtime/ExecState.cpp \ - JavaScriptCore/runtime/ExecState.h \ - JavaScriptCore/runtime/InitializeThreading.cpp \ - JavaScriptCore/runtime/InitializeThreading.h \ - JavaScriptCore/runtime/JSActivation.cpp \ - JavaScriptCore/runtime/JSActivation.h \ - JavaScriptCore/runtime/JSGlobalData.cpp \ - JavaScriptCore/runtime/JSGlobalData.h \ - JavaScriptCore/runtime/JSStaticScopeObject.h \ - JavaScriptCore/runtime/JSType.h \ - JavaScriptCore/kjs/NodeInfo.h \ - JavaScriptCore/kjs/Parser.h \ - JavaScriptCore/runtime/PropertyNameArray.h \ - JavaScriptCore/runtime/RegExpConstructor.h \ - JavaScriptCore/runtime/RegExpMatchesArray.h \ - JavaScriptCore/runtime/RegExpObject.h \ - JavaScriptCore/runtime/RegExpPrototype.h \ - JavaScriptCore/kjs/ResultType.h \ - JavaScriptCore/runtime/ScopeChain.h \ - JavaScriptCore/runtime/ScopeChainMark.h \ - JavaScriptCore/kjs/SourceProvider.h \ - JavaScriptCore/kjs/SourceCode.h \ - JavaScriptCore/runtime/SymbolTable.h \ - JavaScriptCore/runtime/Tracing.h \ - JavaScriptCore/kjs/TypeInfo.h \ - JavaScriptCore/kjs/collector.h \ - JavaScriptCore/kjs/completion.h \ - JavaScriptCore/kjs/config.h \ - JavaScriptCore/debugger/Debugger.h \ - JavaScriptCore/kjs/dtoa.h \ - JavaScriptCore/kjs/identifier.h \ - JavaScriptCore/kjs/interpreter.h \ - JavaScriptCore/kjs/lexer.h \ - JavaScriptCore/kjs/lookup.h \ - JavaScriptCore/kjs/nodes.h \ - JavaScriptCore/kjs/operations.h \ - JavaScriptCore/kjs/protect.h \ - JavaScriptCore/kjs/regexp.h \ - JavaScriptCore/kjs/ustring.h \ - JavaScriptCore/masm/X86Assembler.h \ + JavaScriptCore/assembler/X86Assembler.h \ + JavaScriptCore/assembler/AssemblerBuffer.h \ + JavaScriptCore/assembler/MacroAssembler.h \ JavaScriptCore/os-win32/stdbool.h \ JavaScriptCore/os-win32/stdint.h \ JavaScriptCore/pcre/pcre.h \ @@ -179,73 +155,53 @@ javascriptcore_sources += \ JavaScriptCore/profiler/Profiler.h \ JavaScriptCore/profiler/TreeProfile.cpp \ JavaScriptCore/profiler/TreeProfile.h \ - JavaScriptCore/runtime/ArrayConstructor.h \ - JavaScriptCore/runtime/ArrayPrototype.h \ - JavaScriptCore/runtime/BooleanConstructor.h \ - JavaScriptCore/runtime/BooleanObject.h \ - JavaScriptCore/runtime/BooleanPrototype.h \ - JavaScriptCore/runtime/CallData.h \ - JavaScriptCore/runtime/ClassInfo.h \ - JavaScriptCore/runtime/DateConstructor.h \ - JavaScriptCore/runtime/DateInstance.h \ - JavaScriptCore/runtime/DateMath.h \ - JavaScriptCore/runtime/DatePrototype.h \ - JavaScriptCore/runtime/Error.h \ - JavaScriptCore/runtime/ErrorConstructor.h \ - JavaScriptCore/runtime/ErrorInstance.h \ - JavaScriptCore/runtime/ErrorPrototype.h \ - JavaScriptCore/runtime/FunctionConstructor.h \ - JavaScriptCore/runtime/FunctionPrototype.h \ - JavaScriptCore/runtime/GlobalEvalFunction.h \ - JavaScriptCore/runtime/InternalFunction.h \ - JavaScriptCore/runtime/JSArray.h \ - JavaScriptCore/runtime/JSCell.h \ - JavaScriptCore/runtime/JSFunction.h \ - JavaScriptCore/runtime/JSGlobalObject.h \ - JavaScriptCore/runtime/JSGlobalObjectFunctions.h \ - JavaScriptCore/runtime/JSImmediate.h \ + JavaScriptCore/interpreter/CallFrame.cpp \ + JavaScriptCore/interpreter/CallFrame.h \ + JavaScriptCore/runtime/InitializeThreading.cpp \ + JavaScriptCore/runtime/InitializeThreading.h \ + JavaScriptCore/runtime/JSActivation.cpp \ + JavaScriptCore/runtime/JSActivation.h \ + JavaScriptCore/runtime/JSByteArray.cpp \ + JavaScriptCore/runtime/JSByteArray.h \ + JavaScriptCore/runtime/JSGlobalData.cpp \ + JavaScriptCore/runtime/JSGlobalData.h \ JavaScriptCore/runtime/JSNotAnObject.cpp \ JavaScriptCore/runtime/JSNotAnObject.h \ - JavaScriptCore/runtime/JSNumberCell.h \ - JavaScriptCore/runtime/JSObject.h \ - JavaScriptCore/runtime/JSString.h \ - JavaScriptCore/runtime/JSValue.h \ - JavaScriptCore/runtime/JSVariableObject.h \ - JavaScriptCore/runtime/MathObject.h \ - JavaScriptCore/runtime/NativeErrorConstructor.h \ - JavaScriptCore/runtime/NativeErrorPrototype.h \ - JavaScriptCore/runtime/NumberConstructor.h \ - JavaScriptCore/runtime/NumberObject.h \ - JavaScriptCore/runtime/NumberPrototype.h \ - JavaScriptCore/runtime/ObjectConstructor.h \ - JavaScriptCore/runtime/ObjectPrototype.h \ - JavaScriptCore/runtime/PropertyMapHashTable.h \ - JavaScriptCore/runtime/PropertySlot.h \ - JavaScriptCore/runtime/PrototypeFunction.h \ - JavaScriptCore/runtime/PutPropertySlot.h \ + JavaScriptCore/runtime/JSPropertyNameIterator.cpp \ + JavaScriptCore/runtime/JSPropertyNameIterator.h \ JavaScriptCore/runtime/SmallStrings.cpp \ JavaScriptCore/runtime/SmallStrings.h \ - JavaScriptCore/runtime/StringConstructor.h \ - JavaScriptCore/runtime/StringObject.h \ - JavaScriptCore/runtime/StringObjectThatMasqueradesAsUndefined.h \ - JavaScriptCore/runtime/StringPrototype.h \ - JavaScriptCore/runtime/StructureID.cpp \ - JavaScriptCore/runtime/StructureID.h \ - JavaScriptCore/runtime/StructureIDChain.cpp \ - JavaScriptCore/runtime/StructureIDChain.h \ - JavaScriptCore/runtime/StructureIDTransitionTable.h \ + JavaScriptCore/runtime/Structure.cpp \ + JavaScriptCore/runtime/Structure.h \ + JavaScriptCore/runtime/StructureChain.cpp \ + JavaScriptCore/runtime/StructureChain.h \ + JavaScriptCore/runtime/StructureTransitionTable.h \ + JavaScriptCore/runtime/TypeInfo.h \ + JavaScriptCore/wrec/CharacterClass.cpp \ + JavaScriptCore/wrec/CharacterClass.h \ JavaScriptCore/wrec/CharacterClassConstructor.cpp \ JavaScriptCore/wrec/CharacterClassConstructor.h \ + JavaScriptCore/wrec/Escapes.h \ + JavaScriptCore/wrec/Quantifier.h \ JavaScriptCore/wrec/WREC.cpp \ JavaScriptCore/wrec/WREC.h \ + JavaScriptCore/wrec/WRECFunctors.cpp \ + JavaScriptCore/wrec/WRECFunctors.h \ + JavaScriptCore/wrec/WRECGenerator.cpp \ + JavaScriptCore/wrec/WRECGenerator.h \ + JavaScriptCore/wrec/WRECParser.cpp \ + JavaScriptCore/wrec/WRECParser.h \ JavaScriptCore/wtf/ASCIICType.h \ JavaScriptCore/wtf/AVLTree.h \ JavaScriptCore/wtf/AlwaysInline.h \ JavaScriptCore/wtf/Assertions.cpp \ JavaScriptCore/wtf/Assertions.h \ + JavaScriptCore/wtf/ByteArray.cpp \ + JavaScriptCore/wtf/ByteArray.h \ + JavaScriptCore/wtf/CurrentTime.cpp \ + JavaScriptCore/wtf/CurrentTime.h \ JavaScriptCore/wtf/Deque.h \ JavaScriptCore/wtf/DisallowCType.h \ - JavaScriptCore/wtf/FastMalloc.h \ JavaScriptCore/wtf/Forward.h \ JavaScriptCore/wtf/GOwnPtr.cpp \ JavaScriptCore/wtf/GOwnPtr.h \ @@ -263,7 +219,6 @@ javascriptcore_sources += \ JavaScriptCore/wtf/Locker.h \ JavaScriptCore/wtf/MainThread.cpp \ JavaScriptCore/wtf/MainThread.h \ - JavaScriptCore/wtf/MallocZoneSupport.h \ JavaScriptCore/wtf/MathExtras.h \ JavaScriptCore/wtf/MessageQueue.h \ JavaScriptCore/wtf/Noncopyable.h \ @@ -272,19 +227,24 @@ javascriptcore_sources += \ JavaScriptCore/wtf/OwnPtr.h \ JavaScriptCore/wtf/PassRefPtr.h \ JavaScriptCore/wtf/Platform.h \ + JavaScriptCore/wtf/PtrAndFlags.h \ + JavaScriptCore/wtf/RandomNumber.cpp \ + JavaScriptCore/wtf/RandomNumber.h \ + JavaScriptCore/wtf/RandomNumberSeed.h \ JavaScriptCore/wtf/RefCounted.h \ JavaScriptCore/wtf/RefCountedLeakCounter.cpp \ JavaScriptCore/wtf/RefCountedLeakCounter.h \ JavaScriptCore/wtf/RefPtr.h \ JavaScriptCore/wtf/RefPtrHashMap.h \ JavaScriptCore/wtf/RetainPtr.h \ + JavaScriptCore/wtf/StdLibExtras.h \ JavaScriptCore/wtf/StringExtras.h \ JavaScriptCore/wtf/TCPackedCache.h \ JavaScriptCore/wtf/TCPageMap.h \ JavaScriptCore/wtf/TCSpinLock.h \ - JavaScriptCore/wtf/TCSystemAlloc.h \ JavaScriptCore/wtf/ThreadSpecific.h \ JavaScriptCore/wtf/Threading.h \ + JavaScriptCore/wtf/Threading.cpp \ JavaScriptCore/wtf/ThreadingGtk.cpp \ JavaScriptCore/wtf/ThreadingPthreads.cpp \ JavaScriptCore/wtf/UnusedParam.h \ @@ -302,114 +262,196 @@ javascriptcore_sources += \ # Debug build if ENABLE_DEBUG javascriptcore_built_sources += \ - DerivedSources/grammar.cpp \ - DerivedSources/grammar.h + DerivedSources/Grammar.cpp \ + DerivedSources/Grammar.h javascriptcore_sources += \ - JavaScriptCore/VM/CodeGenerator.cpp \ - JavaScriptCore/VM/RegisterFile.cpp \ + JavaScriptCore/interpreter/RegisterFile.cpp \ + JavaScriptCore/interpreter/RegisterFile.h \ + JavaScriptCore/bytecompiler/BytecodeGenerator.cpp \ + JavaScriptCore/bytecompiler/BytecodeGenerator.h \ + JavaScriptCore/bytecompiler/LabelScope.h \ + JavaScriptCore/debugger/Debugger.cpp \ + JavaScriptCore/debugger/Debugger.h \ + JavaScriptCore/parser/Lexer.cpp \ + JavaScriptCore/parser/Lexer.h \ + JavaScriptCore/parser/NodeInfo.h \ + JavaScriptCore/parser/Nodes.cpp \ + JavaScriptCore/parser/Nodes.h \ + JavaScriptCore/parser/Parser.cpp \ + JavaScriptCore/parser/Parser.h \ + JavaScriptCore/parser/ResultType.h \ + JavaScriptCore/parser/SourceCode.h \ + JavaScriptCore/parser/SourceProvider.h \ JavaScriptCore/runtime/ArgList.cpp \ + JavaScriptCore/runtime/ArgList.h \ JavaScriptCore/runtime/Arguments.cpp \ - JavaScriptCore/runtime/CommonIdentifiers.cpp \ - JavaScriptCore/runtime/CommonIdentifiers.h \ - JavaScriptCore/runtime/GetterSetter.cpp \ - JavaScriptCore/runtime/GetterSetter.h \ - JavaScriptCore/runtime/JSLock.cpp \ - JavaScriptCore/runtime/JSLock.h \ - JavaScriptCore/runtime/JSStaticScopeObject.cpp \ - JavaScriptCore/kjs/LabelScope.h \ - JavaScriptCore/kjs/Parser.cpp \ - JavaScriptCore/runtime/PropertyNameArray.cpp \ - JavaScriptCore/runtime/RegExpConstructor.cpp \ - JavaScriptCore/runtime/RegExpObject.cpp \ - JavaScriptCore/runtime/RegExpPrototype.cpp \ - JavaScriptCore/runtime/ScopeChain.cpp \ - JavaScriptCore/kjs/collector.cpp \ - JavaScriptCore/debugger/Debugger.cpp \ - JavaScriptCore/kjs/dtoa.cpp \ - JavaScriptCore/kjs/identifier.cpp \ - JavaScriptCore/kjs/interpreter.cpp \ - JavaScriptCore/kjs/lexer.cpp \ - JavaScriptCore/kjs/lookup.cpp \ - JavaScriptCore/kjs/nodes.cpp \ - JavaScriptCore/kjs/nodes2string.cpp \ - JavaScriptCore/kjs/operations.cpp \ - JavaScriptCore/kjs/regexp.cpp \ - JavaScriptCore/kjs/ustring.cpp \ + JavaScriptCore/runtime/Arguments.h \ JavaScriptCore/runtime/ArrayConstructor.cpp \ + JavaScriptCore/runtime/ArrayConstructor.h \ JavaScriptCore/runtime/ArrayPrototype.cpp \ + JavaScriptCore/runtime/ArrayPrototype.h \ + JavaScriptCore/runtime/BatchedTransitionOptimizer.h \ JavaScriptCore/runtime/BooleanConstructor.cpp \ + JavaScriptCore/runtime/BooleanConstructor.h \ JavaScriptCore/runtime/BooleanObject.cpp \ + JavaScriptCore/runtime/BooleanObject.h \ JavaScriptCore/runtime/BooleanPrototype.cpp \ + JavaScriptCore/runtime/BooleanPrototype.h \ JavaScriptCore/runtime/CallData.cpp \ + JavaScriptCore/runtime/CallData.h \ + JavaScriptCore/runtime/ClassInfo.h \ + JavaScriptCore/runtime/Collector.cpp \ + JavaScriptCore/runtime/Collector.h \ + JavaScriptCore/runtime/CollectorHeapIterator.h \ + JavaScriptCore/runtime/CommonIdentifiers.cpp \ + JavaScriptCore/runtime/CommonIdentifiers.h \ + JavaScriptCore/runtime/Completion.h \ JavaScriptCore/runtime/ConstructData.cpp \ JavaScriptCore/runtime/ConstructData.h \ JavaScriptCore/runtime/DateConstructor.cpp \ + JavaScriptCore/runtime/DateConstructor.h \ JavaScriptCore/runtime/DateInstance.cpp \ + JavaScriptCore/runtime/DateInstance.h \ JavaScriptCore/runtime/DateMath.cpp \ + JavaScriptCore/runtime/DateMath.h \ JavaScriptCore/runtime/DatePrototype.cpp \ + JavaScriptCore/runtime/DatePrototype.h \ JavaScriptCore/runtime/Error.cpp \ + JavaScriptCore/runtime/Error.h \ JavaScriptCore/runtime/ErrorConstructor.cpp \ + JavaScriptCore/runtime/ErrorConstructor.h \ JavaScriptCore/runtime/ErrorInstance.cpp \ + JavaScriptCore/runtime/ErrorInstance.h \ JavaScriptCore/runtime/ErrorPrototype.cpp \ + JavaScriptCore/runtime/ErrorPrototype.h \ JavaScriptCore/runtime/FunctionConstructor.cpp \ + JavaScriptCore/runtime/FunctionConstructor.h \ JavaScriptCore/runtime/FunctionPrototype.cpp \ + JavaScriptCore/runtime/FunctionPrototype.h \ + JavaScriptCore/runtime/GetterSetter.cpp \ + JavaScriptCore/runtime/GetterSetter.h \ JavaScriptCore/runtime/GlobalEvalFunction.cpp \ + JavaScriptCore/runtime/GlobalEvalFunction.h \ + JavaScriptCore/runtime/Identifier.cpp \ + JavaScriptCore/runtime/Identifier.h \ JavaScriptCore/runtime/InternalFunction.cpp \ + JavaScriptCore/runtime/InternalFunction.h \ + JavaScriptCore/runtime/Completion.cpp \ JavaScriptCore/runtime/JSArray.cpp \ + JavaScriptCore/runtime/JSArray.h \ JavaScriptCore/runtime/JSCell.cpp \ + JavaScriptCore/runtime/JSCell.h \ JavaScriptCore/runtime/JSFunction.cpp \ + JavaScriptCore/runtime/JSFunction.h \ JavaScriptCore/runtime/JSGlobalObject.cpp \ + JavaScriptCore/runtime/JSGlobalObject.h \ JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp \ + JavaScriptCore/runtime/JSGlobalObjectFunctions.h \ JavaScriptCore/runtime/JSImmediate.cpp \ + JavaScriptCore/runtime/JSImmediate.h \ + JavaScriptCore/runtime/JSLock.cpp \ + JavaScriptCore/runtime/JSLock.h \ JavaScriptCore/runtime/JSNumberCell.cpp \ + JavaScriptCore/runtime/JSNumberCell.h \ JavaScriptCore/runtime/JSObject.cpp \ + JavaScriptCore/runtime/JSObject.h \ + JavaScriptCore/runtime/JSStaticScopeObject.cpp \ + JavaScriptCore/runtime/JSStaticScopeObject.h \ JavaScriptCore/runtime/JSString.cpp \ + JavaScriptCore/runtime/JSString.h \ + JavaScriptCore/runtime/JSType.h \ JavaScriptCore/runtime/JSValue.cpp \ + JavaScriptCore/runtime/JSValue.h \ JavaScriptCore/runtime/JSVariableObject.cpp \ + JavaScriptCore/runtime/JSVariableObject.h \ JavaScriptCore/runtime/JSWrapperObject.cpp \ JavaScriptCore/runtime/JSWrapperObject.h \ + JavaScriptCore/runtime/Lookup.cpp \ + JavaScriptCore/runtime/Lookup.h \ JavaScriptCore/runtime/MathObject.cpp \ + JavaScriptCore/runtime/MathObject.h \ JavaScriptCore/runtime/NativeErrorConstructor.cpp \ + JavaScriptCore/runtime/NativeErrorConstructor.h \ JavaScriptCore/runtime/NativeErrorPrototype.cpp \ + JavaScriptCore/runtime/NativeErrorPrototype.h \ JavaScriptCore/runtime/NumberConstructor.cpp \ + JavaScriptCore/runtime/NumberConstructor.h \ JavaScriptCore/runtime/NumberObject.cpp \ + JavaScriptCore/runtime/NumberObject.h \ JavaScriptCore/runtime/NumberPrototype.cpp \ + JavaScriptCore/runtime/NumberPrototype.h \ JavaScriptCore/runtime/ObjectConstructor.cpp \ + JavaScriptCore/runtime/ObjectConstructor.h \ JavaScriptCore/runtime/ObjectPrototype.cpp \ + JavaScriptCore/runtime/ObjectPrototype.h \ + JavaScriptCore/runtime/Operations.cpp \ + JavaScriptCore/runtime/Operations.h \ + JavaScriptCore/runtime/PropertyMapHashTable.h \ + JavaScriptCore/runtime/PropertyNameArray.cpp \ + JavaScriptCore/runtime/PropertyNameArray.h \ JavaScriptCore/runtime/PropertySlot.cpp \ + JavaScriptCore/runtime/PropertySlot.h \ + JavaScriptCore/runtime/Protect.h \ JavaScriptCore/runtime/PrototypeFunction.cpp \ + JavaScriptCore/runtime/PrototypeFunction.h \ + JavaScriptCore/runtime/PutPropertySlot.h \ + JavaScriptCore/runtime/RegExp.cpp \ + JavaScriptCore/runtime/RegExp.h \ + JavaScriptCore/runtime/RegExpConstructor.cpp \ + JavaScriptCore/runtime/RegExpConstructor.h \ + JavaScriptCore/runtime/RegExpMatchesArray.h \ + JavaScriptCore/runtime/RegExpObject.cpp \ + JavaScriptCore/runtime/RegExpObject.h \ + JavaScriptCore/runtime/RegExpPrototype.cpp \ + JavaScriptCore/runtime/RegExpPrototype.h \ + JavaScriptCore/runtime/ScopeChain.cpp \ + JavaScriptCore/runtime/ScopeChain.h \ + JavaScriptCore/runtime/ScopeChainMark.h \ JavaScriptCore/runtime/StringConstructor.cpp \ + JavaScriptCore/runtime/StringConstructor.h \ JavaScriptCore/runtime/StringObject.cpp \ + JavaScriptCore/runtime/StringObject.h \ + JavaScriptCore/runtime/StringObjectThatMasqueradesAsUndefined.h \ JavaScriptCore/runtime/StringPrototype.cpp \ + JavaScriptCore/runtime/StringPrototype.h \ + JavaScriptCore/runtime/SymbolTable.h \ + JavaScriptCore/runtime/Tracing.h \ + JavaScriptCore/runtime/UString.cpp \ + JavaScriptCore/runtime/UString.h \ JavaScriptCore/wtf/FastMalloc.cpp \ - JavaScriptCore/wtf/TCSystemAlloc.cpp + JavaScriptCore/wtf/FastMalloc.h \ + JavaScriptCore/wtf/MallocZoneSupport.h \ + JavaScriptCore/wtf/TCSystemAlloc.cpp \ + JavaScriptCore/wtf/TCSystemAlloc.h \ + JavaScriptCore/wtf/dtoa.cpp \ + JavaScriptCore/wtf/dtoa.h else javascriptcore_built_nosources += \ - DerivedSources/grammar.cpp \ - DerivedSources/grammar.h + DerivedSources/Grammar.cpp \ + DerivedSources/Grammar.h javascriptcore_sources += \ JavaScriptCore/AllInOneFile.cpp endif # END ENABLE_DEBUG -DerivedSources/grammar.h: DerivedSources/grammar.cpp; +DerivedSources/Grammar.h: DerivedSources/Grammar.cpp; -DerivedSources/grammar.cpp: $(srcdir)/JavaScriptCore/kjs/grammar.y - $(BISON) -d -p kjsyy $(srcdir)/JavaScriptCore/kjs/grammar.y -o $@ > bison_out.txt 2>&1 - $(PERL) -p -e 'END { if ($$conflict) { unlink "grammar.cpp"; die; } } $$conflict ||= /conflict/' < bison_out.txt - cat $(GENSOURCES)/grammar.hpp > $(GENSOURCES)/grammar.h - rm -f $(GENSOURCES)/grammar.hpp bison_out.txt +DerivedSources/Grammar.cpp: $(srcdir)/JavaScriptCore/parser/Grammar.y + $(BISON) -d -p jscyy $(srcdir)/JavaScriptCore/parser/Grammar.y -o $@ > bison_out.txt 2>&1 + $(PERL) -p -e 'END { if ($$conflict) { unlink "Grammar.cpp"; die; } } $$conflict ||= /conflict/' < bison_out.txt + cat $(GENSOURCES)/Grammar.hpp > $(GENSOURCES)/Grammar.h + rm -f $(GENSOURCES)/Grammar.hpp bison_out.txt -DerivedSources/lexer.lut.h: $(CREATE_HASH_TABLE) $(srcdir)/JavaScriptCore/kjs/keywords.table +DerivedSources/Lexer.lut.h: $(CREATE_HASH_TABLE) $(srcdir)/JavaScriptCore/parser/Keywords.table $(PERL) $^ > $@ JavaScriptCore/%.lut.h: $(CREATE_HASH_TABLE) $(srcdir)/JavaScriptCore/%.cpp - $^ -i > $@ + $(PERL) $^ -i > $@ JavaScriptCore/pcre/chartables.c: $(srcdir)/JavaScriptCore/pcre/dftables - $^ $@ + $(PERL) $^ $@ bin_PROGRAMS += \ Programs/jsc @@ -434,6 +476,7 @@ Programs_minidom_CPPFLAGS = \ $(javascriptcore_cppflags) Programs_minidom_CFLAGS = \ + -ansi \ -fno-strict-aliasing \ -O2 \ $(global_cflags) \ @@ -446,7 +489,7 @@ Programs_minidom_LDADD = \ # jsc Programs_jsc_SOURCES = \ - JavaScriptCore/kjs/Shell.cpp + JavaScriptCore/jsc.cpp Programs_jsc_CPPFLAGS = \ $(global_cppflags) \ @@ -475,8 +518,8 @@ javascriptcore_dist += \ JavaScriptCore/pcre/AUTHORS \ JavaScriptCore/pcre/dftables \ JavaScriptCore/pcre/ucptable.cpp \ - JavaScriptCore/kjs/grammar.y \ - JavaScriptCore/kjs/keywords.table + JavaScriptCore/parser/Grammar.y \ + JavaScriptCore/parser/Keywords.table # Clean rules for JavaScriptCore CLEANFILES += \ diff --git a/JavaScriptCore/Info.plist b/JavaScriptCore/Info.plist index 55537af..17949b0 100644 --- a/JavaScriptCore/Info.plist +++ b/JavaScriptCore/Info.plist @@ -7,7 +7,7 @@ <key>CFBundleExecutable</key> <string>${PRODUCT_NAME}</string> <key>CFBundleGetInfoString</key> - <string>${BUNDLE_VERSION}, Copyright 2003-2007 Apple Inc.; Copyright 1999-2001 Harri Porten <porten@kde.org>; Copyright 2001 Peter Kelly <pmk@post.com>; Copyright 1997-2005 University of Cambridge; Copyright 1991, 2000, 2001 by Lucent Technologies.</string> + <string>${BUNDLE_VERSION}, Copyright 2003-2009 Apple Inc.; Copyright 1999-2001 Harri Porten <porten@kde.org>; Copyright 2001 Peter Kelly <pmk@post.com>; Copyright 1997-2005 University of Cambridge; Copyright 1991, 2000, 2001 by Lucent Technologies.</string> <key>CFBundleIdentifier</key> <string>com.apple.${PRODUCT_NAME}</string> <key>CFBundleInfoDictionaryVersion</key> diff --git a/JavaScriptCore/JavaScriptCore.exp b/JavaScriptCore/JavaScriptCore.exp index d7e07c6..5e1bb78 100644 --- a/JavaScriptCore/JavaScriptCore.exp +++ b/JavaScriptCore/JavaScriptCore.exp @@ -99,27 +99,18 @@ __ZN3JSC10JSFunction4infoE __ZN3JSC10throwErrorEPNS_9ExecStateENS_9ErrorTypeE __ZN3JSC10throwErrorEPNS_9ExecStateENS_9ErrorTypeEPKc __ZN3JSC10throwErrorEPNS_9ExecStateENS_9ErrorTypeERKNS_7UStringE -__ZN3JSC11Interpreter11checkSyntaxEPNS_9ExecStateERKNS_10SourceCodeE -__ZN3JSC11Interpreter8evaluateEPNS_9ExecStateERNS_10ScopeChainERKNS_10SourceCodeEPNS_7JSValueE +__ZN3JSC11JSByteArray15createStructureENS_10JSValuePtrE +__ZN3JSC11JSByteArrayC1EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEPNS3_9ByteArrayEPKNS_9ClassInfoE __ZN3JSC11JSImmediate12nonInlineNaNEv -__ZN3JSC11JSImmediate8toObjectEPNS_7JSValueEPNS_9ExecStateE -__ZN3JSC11JSImmediate8toStringEPNS_7JSValueE -__ZN3JSC11JSImmediate9prototypeEPNS_7JSValueEPNS_9ExecStateE +__ZN3JSC11JSImmediate8toObjectENS_10JSValuePtrEPNS_9ExecStateE +__ZN3JSC11JSImmediate8toStringENS_10JSValuePtrE +__ZN3JSC11JSImmediate9prototypeENS_10JSValuePtrEPNS_9ExecStateE __ZN3JSC11ProfileNode4sortEPFbRKN3WTF6RefPtrIS0_EES5_E -__ZN3JSC11ProgramNode6createEPNS_12JSGlobalDataEPNS_14SourceElementsEPN3WTF6VectorISt4pairINS_10IdentifierEjELm16EEEPNS6_INS5_6RefPtrINS_12FuncDeclNodeEEELm16EEERKNS_10SourceCodeEji -__ZN3JSC11StructureID17stopIgnoringLeaksEv -__ZN3JSC11StructureID18startIgnoringLeaksEv -__ZN3JSC11StructureID21addPropertyTransitionEPS0_RKNS_10IdentifierEjRm -__ZN3JSC11StructureID21clearEnumerationCacheEv -__ZN3JSC11StructureID24fromDictionaryTransitionEPS0_ -__ZN3JSC11StructureID25changePrototypeTransitionEPS0_PNS_7JSValueE -__ZN3JSC11StructureID27growPropertyStorageCapacityEv -__ZN3JSC11StructureID28addPropertyWithoutTransitionERKNS_10IdentifierEj -__ZN3JSC11StructureIDC1EPNS_7JSValueERKNS_8TypeInfoE -__ZN3JSC11StructureIDD1Ev +__ZN3JSC11checkSyntaxEPNS_9ExecStateERKNS_10SourceCodeE __ZN3JSC12DateInstance4infoE __ZN3JSC12JSGlobalData10ClientDataD2Ev __ZN3JSC12JSGlobalData12createLeakedEv +__ZN3JSC12JSGlobalData14sharedInstanceEv __ZN3JSC12JSGlobalData6createEv __ZN3JSC12JSGlobalDataD1Ev __ZN3JSC12SamplingTool13notifyOfScopeEPNS_9ScopeNodeE @@ -132,11 +123,10 @@ __ZN3JSC12StringObject14toThisJSStringEPNS_9ExecStateE __ZN3JSC12StringObject16getPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayE __ZN3JSC12StringObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE __ZN3JSC12StringObject18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE -__ZN3JSC12StringObject3putEPNS_9ExecStateERKNS_10IdentifierEPNS_7JSValueERNS_15PutPropertySlotE +__ZN3JSC12StringObject3putEPNS_9ExecStateERKNS_10IdentifierENS_10JSValuePtrERNS_15PutPropertySlotE __ZN3JSC12StringObject4infoE -__ZN3JSC12StringObjectC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_11StructureIDEEERKNS_7UStringE +__ZN3JSC12StringObjectC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEERKNS_7UStringE __ZN3JSC12jsNumberCellEPNS_9ExecStateEd -__ZN3JSC13CodeGenerator21setDumpsGeneratedCodeEb __ZN3JSC13StatementNode6setLocEii __ZN3JSC13jsOwnedStringEPNS_12JSGlobalDataERKNS_7UStringE __ZN3JSC14JSGlobalObject10globalExecEv @@ -144,34 +134,40 @@ __ZN3JSC14JSGlobalObject12defineGetterEPNS_9ExecStateERKNS_10IdentifierEPNS_8JSO __ZN3JSC14JSGlobalObject12defineSetterEPNS_9ExecStateERKNS_10IdentifierEPNS_8JSObjectE __ZN3JSC14JSGlobalObject14setTimeoutTimeEj __ZN3JSC14JSGlobalObject16stopTimeoutCheckEv -__ZN3JSC14JSGlobalObject17putWithAttributesEPNS_9ExecStateERKNS_10IdentifierEPNS_7JSValueEj +__ZN3JSC14JSGlobalObject17putWithAttributesEPNS_9ExecStateERKNS_10IdentifierENS_10JSValuePtrEj __ZN3JSC14JSGlobalObject17startTimeoutCheckEv -__ZN3JSC14JSGlobalObject29markCrossHeapDependentObjectsEv -__ZN3JSC14JSGlobalObject3putEPNS_9ExecStateERKNS_10IdentifierEPNS_7JSValueERNS_15PutPropertySlotE +__ZN3JSC14JSGlobalObject3putEPNS_9ExecStateERKNS_10IdentifierENS_10JSValuePtrERNS_15PutPropertySlotE __ZN3JSC14JSGlobalObject4initEPNS_8JSObjectE __ZN3JSC14JSGlobalObject4markEv __ZN3JSC14JSGlobalObjectD2Ev __ZN3JSC14JSGlobalObjectnwEmPNS_12JSGlobalDataE __ZN3JSC14constructArrayEPNS_9ExecStateERKNS_7ArgListE __ZN3JSC15JSWrapperObject4markEv +__ZN3JSC15toInt32SlowCaseEdRb __ZN3JSC16FunctionBodyNode13finishParsingEPNS_10IdentifierEm __ZN3JSC16FunctionBodyNode14copyParametersEv -__ZN3JSC16FunctionBodyNode6createEPNS_12JSGlobalDataEPNS_14SourceElementsEPN3WTF6VectorISt4pairINS_10IdentifierEjELm16EEEPNS6_INS5_6RefPtrINS_12FuncDeclNodeEEELm16EEERKNS_10SourceCodeEji +__ZN3JSC16FunctionBodyNode6createEPNS_12JSGlobalDataEPNS_14SourceElementsEPN3WTF6VectorISt4pairINS_10IdentifierEjELm0EEEPNS6_INS5_6RefPtrINS_12FuncDeclNodeEEELm0EEERKNS_10SourceCodeEji __ZN3JSC16InternalFunction4infoE -__ZN3JSC16InternalFunctionC2EPNS_12JSGlobalDataEN3WTF10PassRefPtrINS_11StructureIDEEERKNS_10IdentifierE +__ZN3JSC16InternalFunction4nameEPNS_12JSGlobalDataE +__ZN3JSC16InternalFunctionC2EPNS_12JSGlobalDataEN3WTF10PassRefPtrINS_9StructureEEERKNS_10IdentifierE __ZN3JSC16JSVariableObject14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE __ZN3JSC16JSVariableObject16getPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayE __ZN3JSC16ParserRefCounted3refEv __ZN3JSC16ParserRefCounted5derefEv +__ZN3JSC16toUInt32SlowCaseEdRb +__ZN3JSC17BytecodeGenerator21setDumpsGeneratedCodeEb __ZN3JSC17PropertyNameArray3addEPNS_7UString3RepE -__ZN3JSC17PrototypeFunctionC1EPNS_9ExecStateEN3WTF10PassRefPtrINS_11StructureIDEEEiRKNS_10IdentifierEPFPNS_7JSValueES2_PNS_8JSObjectESB_RKNS_7ArgListEE -__ZN3JSC17PrototypeFunctionC1EPNS_9ExecStateEiRKNS_10IdentifierEPFPNS_7JSValueES2_PNS_8JSObjectES7_RKNS_7ArgListEE +__ZN3JSC17PrototypeFunctionC1EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEiRKNS_10IdentifierEPFNS_10JSValuePtrES2_PNS_8JSObjectESA_RKNS_7ArgListEE +__ZN3JSC17PrototypeFunctionC1EPNS_9ExecStateEiRKNS_10IdentifierEPFNS_10JSValuePtrES2_PNS_8JSObjectES6_RKNS_7ArgListEE __ZN3JSC17constructFunctionEPNS_9ExecStateERKNS_7ArgListERKNS_10IdentifierERKNS_7UStringEi +__ZN3JSC18DebuggerActivationC1EPNS_8JSObjectE __ZN3JSC19constructEmptyArrayEPNS_9ExecStateE __ZN3JSC19initializeThreadingEv __ZN3JSC20constructEmptyObjectEPNS_9ExecStateE -__ZN3JSC23objectProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectEPNS_7JSValueERKNS_7ArgListE +__ZN3JSC23objectProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE __ZN3JSC23setUpStaticFunctionSlotEPNS_9ExecStateEPKNS_9HashEntryEPNS_8JSObjectERKNS_10IdentifierERNS_12PropertySlotE +__ZN3JSC25evaluateInGlobalCallFrameERKNS_7UStringERNS_10JSValuePtrEPNS_14JSGlobalObjectE +__ZN3JSC4Heap11objectCountEv __ZN3JSC4Heap14allocateNumberEm __ZN3JSC4Heap14primaryHeapEndEv __ZN3JSC4Heap15recordExtraCostEm @@ -181,15 +177,14 @@ __ZN3JSC4Heap20protectedObjectCountEv __ZN3JSC4Heap24setGCProtectNeedsLockingEv __ZN3JSC4Heap25protectedObjectTypeCountsEv __ZN3JSC4Heap26protectedGlobalObjectCountEv -__ZN3JSC4Heap4heapEPNS_7JSValueE -__ZN3JSC4Heap4sizeEv +__ZN3JSC4Heap4heapENS_10JSValuePtrE __ZN3JSC4Heap6isBusyEv __ZN3JSC4Heap7collectEv __ZN3JSC4Heap7destroyEv -__ZN3JSC4Heap7protectEPNS_7JSValueE +__ZN3JSC4Heap7protectENS_10JSValuePtrE __ZN3JSC4Heap8allocateEm -__ZN3JSC4Heap9unprotectEPNS_7JSValueE -__ZN3JSC4callEPNS_9ExecStateEPNS_7JSValueENS_8CallTypeERKNS_8CallDataES3_RKNS_7ArgListE +__ZN3JSC4Heap9unprotectENS_10JSValuePtrE +__ZN3JSC4callEPNS_9ExecStateENS_10JSValuePtrENS_8CallTypeERKNS_8CallDataES2_RKNS_7ArgListE __ZN3JSC5equalEPKNS_7UString3RepES3_ __ZN3JSC6JSCell11getCallDataERNS_8CallDataE __ZN3JSC6JSCell11getJSNumberEv @@ -199,8 +194,8 @@ __ZN3JSC6JSCell14toThisJSStringEPNS_9ExecStateE __ZN3JSC6JSCell16getConstructDataERNS_13ConstructDataE __ZN3JSC6JSCell18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE __ZN3JSC6JSCell18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE -__ZN3JSC6JSCell3putEPNS_9ExecStateERKNS_10IdentifierEPNS_7JSValueERNS_15PutPropertySlotE -__ZN3JSC6JSCell3putEPNS_9ExecStateEjPNS_7JSValueE +__ZN3JSC6JSCell3putEPNS_9ExecStateERKNS_10IdentifierENS_10JSValuePtrERNS_15PutPropertySlotE +__ZN3JSC6JSCell3putEPNS_9ExecStateEjNS_10JSValuePtrE __ZN3JSC6JSCell9getObjectEv __ZN3JSC6JSCellnwEmPNS_9ExecStateE __ZN3JSC6JSLock12DropAllLocksC1EPNS_9ExecStateE @@ -211,8 +206,7 @@ __ZN3JSC6JSLock6unlockEb __ZN3JSC6JSLock9lockCountEv __ZN3JSC6JSLockC1EPNS_9ExecStateE __ZN3JSC6Parser5parseEPNS_12JSGlobalDataEPiPNS_7UStringE -__ZN3JSC6strtodEPKcPPc -__ZN3JSC7ArgList10slowAppendEPNS_7JSValueE +__ZN3JSC7ArgList10slowAppendENS_10JSValuePtrE __ZN3JSC7CStringD1Ev __ZN3JSC7CStringaSERKS0_ __ZN3JSC7JSArray4infoE @@ -221,7 +215,7 @@ __ZN3JSC7Profile5focusEPKNS_11ProfileNodeE __ZN3JSC7Profile7excludeEPKNS_11ProfileNodeE __ZN3JSC7Profile7forEachEMNS_11ProfileNodeEFvvE __ZN3JSC7UString3Rep11computeHashEPKti -__ZN3JSC7UString3Rep4nullE +__ZN3JSC7UString3Rep14nullBaseStringE __ZN3JSC7UString3Rep7destroyEv __ZN3JSC7UString4fromEi __ZN3JSC7UString4fromEj @@ -234,42 +228,57 @@ __ZN3JSC8Debugger6attachEPNS_14JSGlobalObjectE __ZN3JSC8Debugger6detachEPNS_14JSGlobalObjectE __ZN3JSC8DebuggerC2Ev __ZN3JSC8DebuggerD2Ev -__ZN3JSC8JSObject11hasInstanceEPNS_9ExecStateEPNS_7JSValueES4_ +__ZN3JSC8JSObject11hasInstanceEPNS_9ExecStateENS_10JSValuePtrES3_ __ZN3JSC8JSObject12defineGetterEPNS_9ExecStateERKNS_10IdentifierEPS0_ __ZN3JSC8JSObject12defineSetterEPNS_9ExecStateERKNS_10IdentifierEPS0_ __ZN3JSC8JSObject12lookupGetterEPNS_9ExecStateERKNS_10IdentifierE __ZN3JSC8JSObject12lookupSetterEPNS_9ExecStateERKNS_10IdentifierE __ZN3JSC8JSObject14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE __ZN3JSC8JSObject14deletePropertyEPNS_9ExecStateEj +__ZN3JSC8JSObject15unwrappedObjectEv __ZN3JSC8JSObject16getPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayE __ZN3JSC8JSObject17createInheritorIDEv __ZN3JSC8JSObject17putDirectFunctionEPNS_9ExecStateEPNS_16InternalFunctionEj -__ZN3JSC8JSObject17putWithAttributesEPNS_9ExecStateERKNS_10IdentifierEPNS_7JSValueEj -__ZN3JSC8JSObject17putWithAttributesEPNS_9ExecStateEjPNS_7JSValueEj +__ZN3JSC8JSObject17putWithAttributesEPNS_9ExecStateERKNS_10IdentifierENS_10JSValuePtrEj +__ZN3JSC8JSObject17putWithAttributesEPNS_9ExecStateEjNS_10JSValuePtrEj __ZN3JSC8JSObject18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE -__ZN3JSC8JSObject18getPrimitiveNumberEPNS_9ExecStateERdRPNS_7JSValueE -__ZN3JSC8JSObject22fillGetterPropertySlotERNS_12PropertySlotEPPNS_7JSValueE +__ZN3JSC8JSObject18getPrimitiveNumberEPNS_9ExecStateERdRNS_10JSValuePtrE +__ZN3JSC8JSObject22fillGetterPropertySlotERNS_12PropertySlotEPNS_10JSValuePtrE __ZN3JSC8JSObject23allocatePropertyStorageEmm -__ZN3JSC8JSObject3putEPNS_9ExecStateERKNS_10IdentifierEPNS_7JSValueERNS_15PutPropertySlotE -__ZN3JSC8JSObject3putEPNS_9ExecStateEjPNS_7JSValueE +__ZN3JSC8JSObject3putEPNS_9ExecStateERKNS_10IdentifierENS_10JSValuePtrERNS_15PutPropertySlotE +__ZN3JSC8JSObject3putEPNS_9ExecStateEjNS_10JSValuePtrE __ZN3JSC8JSObject4markEv __ZN3JSC8Profiler13stopProfilingEPNS_9ExecStateERKNS_7UStringE __ZN3JSC8Profiler14startProfilingEPNS_9ExecStateERKNS_7UStringE __ZN3JSC8Profiler8profilerEv +__ZN3JSC8evaluateEPNS_9ExecStateERNS_10ScopeChainERKNS_10SourceCodeENS_10JSValuePtrE __ZN3JSC8jsStringEPNS_12JSGlobalDataERKNS_7UStringE __ZN3JSC9CodeBlockD1Ev __ZN3JSC9CodeBlockD2Ev -__ZN3JSC9constructEPNS_9ExecStateEPNS_7JSValueENS_13ConstructTypeERKNS_13ConstructDataERKNS_7ArgListE +__ZN3JSC9Structure17stopIgnoringLeaksEv +__ZN3JSC9Structure18startIgnoringLeaksEv +__ZN3JSC9Structure21addPropertyTransitionEPS0_RKNS_10IdentifierEjRm +__ZN3JSC9Structure22materializePropertyMapEv +__ZN3JSC9Structure25changePrototypeTransitionEPS0_NS_10JSValuePtrE +__ZN3JSC9Structure28addPropertyWithoutTransitionERKNS_10IdentifierEj +__ZN3JSC9Structure3getERKNS_10IdentifierERj +__ZN3JSC9Structure40addPropertyTransitionToExistingStructureEPS0_RKNS_10IdentifierEjRm +__ZN3JSC9StructureC1ENS_10JSValuePtrERKNS_8TypeInfoE +__ZN3JSC9StructureD1Ev +__ZN3JSC9constructEPNS_9ExecStateENS_10JSValuePtrENS_13ConstructTypeERKNS_13ConstructDataERKNS_7ArgListE __ZN3JSCeqERKNS_7UStringEPKc +__ZN3JSCeqERKNS_7UStringES2_ __ZN3JSCgtERKNS_7UStringES2_ __ZN3JSCltERKNS_7UStringES2_ __ZN3WTF10fastCallocEmm __ZN3WTF10fastMallocEm +__ZN3WTF11currentTimeEv __ZN3WTF11fastReallocEPvm __ZN3WTF12createThreadEPFPvS0_ES0_ __ZN3WTF12createThreadEPFPvS0_ES0_PKc __ZN3WTF12detachThreadEj __ZN3WTF12isMainThreadEv +__ZN3WTF12randomNumberEv __ZN3WTF13currentThreadEv __ZN3WTF13tryFastCallocEmm __ZN3WTF15ThreadCondition4waitERNS_5MutexE @@ -280,6 +289,7 @@ __ZN3WTF15ThreadConditionD1Ev __ZN3WTF16callOnMainThreadEPFvPvES0_ __ZN3WTF16fastZeroedMallocEm __ZN3WTF19initializeThreadingEv +__ZN3WTF20fastMallocStatisticsEv __ZN3WTF21RefCountedLeakCounter16suppressMessagesEPKc __ZN3WTF21RefCountedLeakCounter24cancelMessageSuppressionEPKc __ZN3WTF21RefCountedLeakCounter9decrementEv @@ -289,48 +299,45 @@ __ZN3WTF21RefCountedLeakCounterD1Ev __ZN3WTF23waitForThreadCompletionEjPPv __ZN3WTF27releaseFastMallocFreeMemoryEv __ZN3WTF28setMainThreadCallbacksPausedEb -__ZN3WTF32atomicallyInitializedStaticMutexE +__ZN3WTF36lockAtomicallyInitializedStaticMutexEv +__ZN3WTF38unlockAtomicallyInitializedStaticMutexEv __ZN3WTF5Mutex4lockEv __ZN3WTF5Mutex6unlockEv __ZN3WTF5Mutex7tryLockEv __ZN3WTF5MutexC1Ev __ZN3WTF5MutexD1Ev +__ZN3WTF6strtodEPKcPPc __ZN3WTF7Unicode18convertUTF16ToUTF8EPPKtS2_PPcS4_b __ZN3WTF8Collator18setOrderLowerFirstEb __ZN3WTF8CollatorC1EPKc __ZN3WTF8CollatorD1Ev __ZN3WTF8fastFreeEPv -__ZNK3JSC11StructureID3getERKNS_10IdentifierERj +__ZN3WTF9ByteArray6createEm +__ZNK3JSC10JSValuePtr9toIntegerEPNS_9ExecStateE +__ZNK3JSC11Interpreter14retrieveCallerEPNS_9ExecStateEPNS_16InternalFunctionE +__ZNK3JSC11Interpreter18retrieveLastCallerEPNS_9ExecStateERiRlRNS_7UStringERNS_10JSValuePtrE __ZNK3JSC12DateInstance7getTimeERdRi __ZNK3JSC12StringObject12toThisStringEPNS_9ExecStateE __ZNK3JSC12StringObject8toStringEPNS_9ExecStateE __ZNK3JSC14JSGlobalObject14isDynamicScopeEv -__ZNK3JSC14JSGlobalObject14toGlobalObjectEPNS_9ExecStateE __ZNK3JSC16InternalFunction9classInfoEv __ZNK3JSC16JSVariableObject16isVariableObjectEv __ZNK3JSC16JSVariableObject21getPropertyAttributesEPNS_9ExecStateERKNS_10IdentifierERj __ZNK3JSC17DebuggerCallFrame10thisObjectEv __ZNK3JSC17DebuggerCallFrame12functionNameEv __ZNK3JSC17DebuggerCallFrame4typeEv -__ZNK3JSC17DebuggerCallFrame8evaluateERKNS_7UStringERPNS_7JSValueE -__ZNK3JSC4Node8toStringEv +__ZNK3JSC17DebuggerCallFrame8evaluateERKNS_7UStringERNS_10JSValuePtrE +__ZNK3JSC4Heap10statisticsEv __ZNK3JSC6JSCell12toThisObjectEPNS_9ExecStateE __ZNK3JSC6JSCell12toThisStringEPNS_9ExecStateE __ZNK3JSC6JSCell14isGetterSetterEv __ZNK3JSC6JSCell17getTruncatedInt32ERi __ZNK3JSC6JSCell18getTruncatedUInt32ERj __ZNK3JSC6JSCell9classInfoEv -__ZNK3JSC6JSCell9getNumberEv __ZNK3JSC6JSCell9getStringERNS_7UStringE __ZNK3JSC6JSCell9getStringEv __ZNK3JSC6JSCell9getUInt32ERj __ZNK3JSC7ArgList8getSliceEiRS0_ -__ZNK3JSC7JSValue15toInt32SlowCaseEPNS_9ExecStateERb -__ZNK3JSC7JSValue16toUInt32SlowCaseEPNS_9ExecStateERb -__ZNK3JSC7JSValue7toFloatEPNS_9ExecStateE -__ZNK3JSC7JSValue9toIntegerEPNS_9ExecStateE -__ZNK3JSC7Machine14retrieveCallerEPNS_9ExecStateEPNS_16InternalFunctionE -__ZNK3JSC7Machine18retrieveLastCallerEPNS_9ExecStateERiRlRNS_7UStringERPNS_7JSValueE __ZNK3JSC7UString10UTF8StringEb __ZNK3JSC7UString14toStrictUInt32EPb __ZNK3JSC7UString5asciiEv @@ -342,18 +349,15 @@ __ZNK3JSC8JSObject11hasPropertyEPNS_9ExecStateERKNS_10IdentifierE __ZNK3JSC8JSObject11hasPropertyEPNS_9ExecStateEj __ZNK3JSC8JSObject12defaultValueEPNS_9ExecStateENS_22PreferredPrimitiveTypeE __ZNK3JSC8JSObject12toThisObjectEPNS_9ExecStateE -__ZNK3JSC8JSObject14toGlobalObjectEPNS_9ExecStateE __ZNK3JSC8JSObject21getPropertyAttributesEPNS_9ExecStateERKNS_10IdentifierERj __ZNK3JSC8JSObject8toNumberEPNS_9ExecStateE __ZNK3JSC8JSObject8toObjectEPNS_9ExecStateE __ZNK3JSC8JSObject8toStringEPNS_9ExecStateE __ZNK3JSC8JSObject9classNameEv __ZNK3JSC8JSObject9toBooleanEPNS_9ExecStateE -__ZNK3JSC9CodeBlock17derefStructureIDsEPNS_11InstructionE __ZNK3JSC9HashTable11createTableEPNS_12JSGlobalDataE __ZNK3JSC9HashTable11deleteTableEv __ZNK3WTF8Collator7collateEPKtmS2_m -__ZTVN3JSC12JSNumberCellE __ZTVN3JSC12StringObjectE __ZTVN3JSC14JSGlobalObjectE __ZTVN3JSC15JSWrapperObjectE diff --git a/JavaScriptCore/JavaScriptCore.order b/JavaScriptCore/JavaScriptCore.order index 9f7cb30..05c300c 100644 --- a/JavaScriptCore/JavaScriptCore.order +++ b/JavaScriptCore/JavaScriptCore.order @@ -1,1526 +1,1638 @@ +__ZN3WTF19initializeThreadingEv __ZN3WTF10fastMallocEm +__ZN3WTF10fastMallocILb1EEEPvm __ZN3WTF20TCMalloc_ThreadCache10InitModuleEv -__ZN3WTF15InitSizeClassesEv +__ZN3WTFL15InitSizeClassesEv __Z20TCMalloc_SystemAllocmPmm -__ZN3WTF17TCMalloc_PageHeap4initEv __ZN3WTF20TCMalloc_ThreadCache22CreateCacheIfNecessaryEv __ZN3WTF25TCMalloc_Central_FreeList11RemoveRangeEPPvS2_Pi __ZN3WTF25TCMalloc_Central_FreeList18FetchFromSpansSafeEv __ZN3WTF17TCMalloc_PageHeap10AllocLargeEm __ZN3WTF17TCMalloc_PageHeap8GrowHeapEm -__ZN3WTF13MetaDataAllocEm -__ZN3WTF17TCMalloc_PageHeap19IncrementalScavengeEm +__ZN3WTFL13MetaDataAllocEm +__ZN3WTF20initializeMainThreadEv +__ZN3WTF5MutexC1Ev +__ZN3WTF36lockAtomicallyInitializedStaticMutexEv +__ZN3WTF38unlockAtomicallyInitializedStaticMutexEv +__ZN3JSC19initializeThreadingEv +__ZN3JSCL23initializeThreadingOnceEv +__ZN3JSC17initializeUStringEv +__ZN3JSC12initDateMathEv +__ZN3WTF11currentTimeEv +__ZN3WTF15ThreadConditionC1Ev +__ZN3WTF5Mutex4lockEv +__ZN3WTF5Mutex6unlockEv __ZN3WTF8fastFreeEPv +__ZN3WTF12createThreadEPFPvS0_ES0_PKc +__ZN3WTF20createThreadInternalEPFPvS0_ES0_PKc +__ZN3WTFL35establishIdentifierForPthreadHandleERP17_opaque_pthread_t +__ZN3WTFL16threadEntryPointEPv +__ZN3WTF7HashMapIjP17_opaque_pthread_tNS_7IntHashIjEENS_10HashTraitsIjEENS5_IS2_EEE3addERKjRKS2_ +__ZN3WTF9HashTableIjSt4pairIjP17_opaque_pthread_tENS_18PairFirstExtractorIS4_EENS_7IntHashIjEENS_14PairHashTraitsINS_10HashTraitsIjEENSA_IS3_EEEESB_E6rehashEi __ZN3WTF16fastZeroedMallocEm +__ZN3WTF5MutexD1Ev +__ZN3WTF25TCMalloc_Central_FreeList11InsertRangeEPvS1_i +__ZN3WTF25TCMalloc_Central_FreeList18ReleaseListToSpansEPv __ZN3WTF14FastMallocZone4sizeEP14_malloc_zone_tPKv -__ZN3KJS8Bindings10RootObject19setCreateRootObjectEPFN3WTF10PassRefPtrIS1_EEPvE -__ZN3KJS8Bindings8Instance21setDidExecuteFunctionEPFvPNS_9ExecStateEPNS_8JSObjectEE -_kjs_strtod -__Z15jsRegExpCompilePKti24JSRegExpIgnoreCaseOption23JSRegExpMultilineOptionPjPPKc -__Z30calculateCompiledPatternLengthPKti24JSRegExpIgnoreCaseOptionR11CompileDataR9ErrorCode -__Z11checkEscapePPKtS0_P9ErrorCodeib -__Z13compileBranchiPiPPhPPKtS3_P9ErrorCodeS_S_R11CompileData -__Z15jsRegExpExecutePK8JSRegExpPKtiiPii +__ZN3WTF13currentThreadEv +__ZN3WTF16callOnMainThreadEPFvPvES0_ +__ZN3WTF6VectorINS_19FunctionWithContextELm0EE14expandCapacityEm +__ZN3WTF37scheduleDispatchFunctionsOnMainThreadEv +__ZN3WTF15ThreadCondition4waitERNS_5MutexE +__ZN3JSC8DebuggerC2Ev +__ZN3WTF6strtodEPKcPPc +__ZN3WTF15ThreadCondition6signalEv +__ZN3WTF15ThreadCondition9broadcastEv +__ZN3JSC12JSGlobalData12createLeakedEv +__ZN3JSC12JSGlobalDataC2Eb +__ZN3JSC11InterpreterC1Ev +__ZN3JSC11Interpreter14privateExecuteENS0_13ExecutionFlagEPNS_12RegisterFileEPNS_9ExecStateEPNS_10JSValuePtrE +__ZN3WTF7HashMapIPvN3JSC8OpcodeIDENS_7PtrHashIS1_EENS_10HashTraitsIS1_EENS6_IS3_EEE3addERKS1_RKS3_ +__ZN3WTF9HashTableIPvSt4pairIS1_N3JSC8OpcodeIDEENS_18PairFirstExtractorIS5_EENS_7PtrHashIS1_EENS_14PairHashTraitsINS_10HashTraitsIS1_EENSB_IS4_EEEESC_E6expandEv +__ZN3JSC9StructureC1ENS_10JSValuePtrERKNS_8TypeInfoE +__ZN3JSC7JSArrayC1EN3WTF10PassRefPtrINS_9StructureEEE +__ZN3JSC7JSArrayD0Ev +__ZN3WTF10RefCountedIN3JSC9StructureEE5derefEv +__ZN3JSC9StructureD1Ev +__ZN3JSC11JSByteArray15createStructureENS_10JSValuePtrE +__ZN3JSC21createIdentifierTableEv +__ZN3JSC17CommonIdentifiersC1EPNS_12JSGlobalDataE +__ZN3JSC10Identifier3addEPNS_12JSGlobalDataEPKc +__ZN3WTF9HashTableIPKcSt4pairIS2_NS_6RefPtrIN3JSC7UString3RepEEEENS_18PairFirstExtractorIS9_EENS_7PtrHashIS2_EENS_14PairHashTraitsINS_10HashTraitsIS2_EENSF_IS8_EEEESG_E4findIS2_NS_22IdentityHashTranslatorIS2_S9_SD_EEEENS_17HashTableIteratorIS2_S9_SB_SD_SI_SG_EERKT_ +__ZN3WTF9HashTableIPN3JSC7UString3RepES4_NS_17IdentityExtractorIS4_EENS_7StrHashIS4_EENS_10HashTraitsIS4_EESA_E6rehashEi +__ZN3WTF9HashTableIPKcSt4pairIS2_NS_6RefPtrIN3JSC7UString3RepEEEENS_18PairFirstExtractorIS9_EENS_7PtrHashIS2_EENS_14PairHashTraitsINS_10HashTraitsIS2_EENSF_IS8_EEEESG_E6expandEv +__ZN3WTF9HashTableIPN3JSC7UString3RepES4_NS_17IdentityExtractorIS4_EENS_7StrHashIS4_EENS_10HashTraitsIS4_EESA_E4findIS4_NS_22IdentityHashTranslatorIS4_S4_S8_EEEENS_17HashTableIteratorIS4_S4_S6_S8_SA_SA_EERKT_ +__ZN3JSC12SmallStringsC1Ev +__ZN3JSC5LexerC1EPNS_12JSGlobalDataE +__ZN3JSC4HeapC1EPNS_12JSGlobalDataE +__ZN3JSC19ExecutableAllocator17intializePageSizeEv +__ZN3JSC14ExecutablePool11systemAllocEm +__ZN3JSC27startProfilerServerIfNeededEv ++[ProfilerServer sharedProfileServer] +-[ProfilerServer init] +__ZN3JSC11Interpreter10initializeEPNS_12JSGlobalDataE +__ZN3JSC3JITC1EPNS_12JSGlobalDataEPNS_9CodeBlockE +__ZN3JSC3JIT35privateCompileCTIMachineTrampolinesEv +__ZN3JSC15AssemblerBuffer11ensureSpaceEi +__ZN3JSC12X86Assembler23X86InstructionFormatter9oneByteOpENS0_15OneByteOpcodeIDEiNS_3X8610RegisterIDEi +__ZN3JSC12X86Assembler23X86InstructionFormatter9oneByteOpENS0_15OneByteOpcodeIDEiNS_3X8610RegisterIDE +__ZN3JSC14MacroAssembler4pokeENS_3X8610RegisterIDEi +__ZN3JSC3JIT32compileOpCallInitializeCallFrameEv +__ZN3JSC14MacroAssembler5jnz32ENS_3X8610RegisterIDENS0_5Imm32E __ZN3WTF11fastReallocEPvm -__ZN3KJS20createDidLockJSMutexEv -__ZN3KJS9Collector14registerThreadEv -__ZN3KJS29initializeRegisteredThreadKeyEv -__ZN3KJS15SavedPropertiesC1Ev -__ZN3KJS6JSCellnwEm -__ZN3KJS9Collector12heapAllocateILNS0_8HeapTypeE0EEEPvm -__ZN3KJS15GlobalExecStateC1EPNS_14JSGlobalObjectE -__ZN3KJS17CommonIdentifiers6sharedEv -__ZN3KJS17CommonIdentifiersC2Ev -__ZN3KJS10IdentifierC1EPKc -__ZN3KJS10Identifier3addEPKc -__ZN3WTF7HashSetIPN3KJS7UString3RepENS_7StrHashIS4_EENS_10HashTraitsIS4_EEE3addINS1_11UCharBufferENS1_21UCharBufferTranslatorEEESt4pairINS_24HashTableIteratorAdapterINS_9HashTableIS4_S4_NS_17IdentityExtractorIS4_EES6_S8_S8_EES4_EEbERKT_ -__ZN3WTF9HashTableIPN3KJS7UString3RepES4_NS_17IdentityExtractorIS4_EENS_7StrHashIS4_EENS_10HashTraitsIS4_EESA_E6rehashEi -__ZN3KJS14JSGlobalObject4initEv -__ZN3KJS14JSGlobalObject5resetEPNS_7JSValueE -__ZN3KJS11PropertyMap5clearEv -__ZN3KJS17FunctionPrototypeC2EPNS_9ExecStateE -__ZN3KJS11PropertyMap3putERKNS_10IdentifierEPNS_7JSValueEjb -__ZN3KJS17PrototypeFunctionC1EPNS_9ExecStateEPNS_17FunctionPrototypeEiRKNS_10IdentifierEPFPNS_7JSValueES2_PNS_8JSObjectERKNS_4ListEE -__ZN3KJS19InternalFunctionImpC2EPNS_17FunctionPrototypeERKNS_10IdentifierE -__ZN3KJS11PropertyMap11createTableEv -__ZN3KJS15ObjectPrototypeC2EPNS_9ExecStateEPNS_17FunctionPrototypeE -__ZN3KJS11PropertyMap6rehashEj -__ZN3KJS14ArrayPrototypeC1EPNS_9ExecStateEPNS_15ObjectPrototypeE -__ZN3KJS13ArrayInstanceC2EPNS_8JSObjectEj -__ZN3KJS15StringPrototypeC2EPNS_9ExecStateEPNS_15ObjectPrototypeE -__ZN3KJS8jsStringEPKc -__ZN3KJS16BooleanPrototypeC2EPNS_9ExecStateEPNS_15ObjectPrototypeEPNS_17FunctionPrototypeE -__ZN3KJS15NumberPrototypeC2EPNS_9ExecStateEPNS_15ObjectPrototypeEPNS_17FunctionPrototypeE -__ZN3KJS13DatePrototypeC1EPNS_9ExecStateEPNS_15ObjectPrototypeE -__ZN3KJS12jsNumberCellEd -__ZN3KJS9Collector12heapAllocateILNS0_8HeapTypeE1EEEPvm -__ZN3KJS15RegExpPrototypeC2EPNS_9ExecStateEPNS_15ObjectPrototypeEPNS_17FunctionPrototypeE -__ZN3WTF9HashTableIPN3KJS7UString3RepES4_NS_17IdentityExtractorIS4_EENS_7StrHashIS4_EENS_10HashTraitsIS4_EESA_E4findIS4_NS_22IdentityHashTranslatorIS4_S4_S8_EEEENS_17HashTableIteratorIS4_S4_S6_S8_SA_SA_EERKT_ -__ZN3KJS14ErrorPrototypeC2EPNS_9ExecStateEPNS_15ObjectPrototypeEPNS_17FunctionPrototypeE -__ZN3KJS7UStringC1EPKc -__ZN3KJS20NativeErrorPrototypeC1EPNS_9ExecStateEPNS_14ErrorPrototypeERKNS_7UStringES7_ -__ZN3KJS8jsStringERKNS_7UStringE -__ZN3KJS15ObjectObjectImpC2EPNS_9ExecStateEPNS_15ObjectPrototypeEPNS_17FunctionPrototypeE -__ZN3KJS17FunctionObjectImpC2EPNS_9ExecStateEPNS_17FunctionPrototypeE -__ZNK3KJS19InternalFunctionImp9classInfoEv -__ZN3KJS14ArrayObjectImpC2EPNS_9ExecStateEPNS_17FunctionPrototypeEPNS_14ArrayPrototypeE -__ZNK3KJS14ArrayPrototype9classInfoEv -__ZN3KJS15StringObjectImpC2EPNS_9ExecStateEPNS_17FunctionPrototypeEPNS_15StringPrototypeE -__ZNK3KJS15StringPrototype9classInfoEv -__ZN3KJS19StringObjectFuncImpC2EPNS_9ExecStateEPNS_17FunctionPrototypeERKNS_10IdentifierE -__ZN3KJS16BooleanObjectImpC2EPNS_9ExecStateEPNS_17FunctionPrototypeEPNS_16BooleanPrototypeE -__ZNK3KJS15BooleanInstance9classInfoEv -__ZN3KJS15NumberObjectImpC2EPNS_9ExecStateEPNS_17FunctionPrototypeEPNS_15NumberPrototypeE -__ZNK3KJS14NumberInstance9classInfoEv -__ZN3KJS13DateObjectImpC2EPNS_9ExecStateEPNS_17FunctionPrototypeEPNS_13DatePrototypeE -__ZNK3KJS13DatePrototype9classInfoEv -__ZN3KJS15RegExpObjectImpC2EPNS_9ExecStateEPNS_17FunctionPrototypeEPNS_15RegExpPrototypeE -__ZN3KJS14ErrorObjectImpC2EPNS_9ExecStateEPNS_17FunctionPrototypeEPNS_14ErrorPrototypeE -__ZNK3KJS13ErrorInstance9classInfoEv -__ZN3KJS14NativeErrorImpC1EPNS_9ExecStateEPNS_17FunctionPrototypeEPNS_20NativeErrorPrototypeE -__ZNK3KJS11PropertyMap3getERKNS_10IdentifierE -__ZNK3KJS9StringImp4typeEv -__ZN3KJS10Identifier11addSlowCaseEPNS_7UString3RepE -__ZN3WTF9HashTableIPN3KJS7UString3RepES4_NS_17IdentityExtractorIS4_EENS_7StrHashIS4_EENS_10HashTraitsIS4_EESA_E3addIS4_S4_NS_17HashSetTranslatorILb1ES4_SA_SA_S8_EEEESt4pairINS_17HashTableIteratorIS4_S4_S6_S8_SA_SA_EEbERKT_RKT0_ -__ZN3KJS8JSObject9putDirectERKNS_10IdentifierEPNS_7JSValueEi -__ZN3KJS13MathObjectImpC1EPNS_9ExecStateEPNS_15ObjectPrototypeE -__ZN3KJS8JSObject17putDirectFunctionEPNS_19InternalFunctionImpEi -__ZNK3KJS8JSObject4typeEv -__ZN3KJS9Collector23collectOnMainThreadOnlyEPNS_7JSValueE -__ZN3KJS9Collector7protectEPNS_7JSValueE -__ZN3WTF9HashTableIiSt4pairIiiENS_18PairFirstExtractorIS2_EENS_7IntHashIiEENS_14PairHashTraitsINS_10HashTraitsIiEES9_EES9_E3addIPN3KJS8JSObjectEjNS_17HashMapTranslatorILb1ES1_ISF_jENS_18PairBaseHashTraitsINS8_ISF_EENS8_IjEEEESA_NS_7PtrHashISF_EEEEEES1_INS_17HashTableIteratorIiS2_S4_S6_SA_S9_EEbERKT_RKT0_ -__ZN3WTF9HashTableIiSt4pairIiiENS_18PairFirstExtractorIS2_EENS_7IntHashIiEENS_14PairHashTraitsINS_10HashTraitsIiEES9_EES9_E6rehashEi -__ZN3KJS6JSCell9getObjectEv -__ZN3KJS8Bindings10RootObject6createEPKvPNS_14JSGlobalObjectE -__ZN3KJS8Bindings10RootObjectC2EPKvPNS_14JSGlobalObjectE -__ZN3WTF9HashTableIiiNS_17IdentityExtractorIiEENS_7IntHashIiEENS_10HashTraitsIiEES6_E6rehashEi -__ZN3KJS8Bindings10RootObject9gcProtectEPNS_8JSObjectE -__ZNK3KJS14JSGlobalObject12saveBuiltinsERNS_13SavedBuiltinsE -__ZN3KJS21SavedBuiltinsInternalC2Ev -__ZNK3KJS11PropertyMap4saveERNS_15SavedPropertiesE -__ZN3KJS30comparePropertyMapEntryIndicesEPKvS1_ -__ZN3WTF9HashTableIiSt4pairIiiENS_18PairFirstExtractorIS2_EENS_7IntHashIiEENS_14PairHashTraitsINS_10HashTraitsIiEES9_EES9_E4findIiNS_22IdentityHashTranslatorIiS2_S6_EEEENS_17HashTableIteratorIiS2_S4_S6_SA_S9_EERKT_ -__ZNK3KJS16JSVariableObject16saveLocalStorageERNS_15SavedPropertiesE -__ZN3KJS13ActivationImpD0Ev -__ZN3KJS8JSObject12removeDirectERKNS_10IdentifierE -__ZN3KJS11PropertyMap6removeERKNS_10IdentifierE -__ZN3KJS7UString3Rep7destroyEv -__ZN3KJS10Identifier6removeEPNS_7UString3RepE -__ZN3KJS8Bindings10RootObject10invalidateEv -__ZN3KJS9Collector9unprotectEPNS_7JSValueE -__ZN3WTF9HashTableIiiNS_17IdentityExtractorIiEENS_7IntHashIiEENS_10HashTraitsIiEES6_E4findIiNS_22IdentityHashTranslatorIiiS4_EEEENS_17HashTableIteratorIiiS2_S4_S6_S6_EERKT_ -__ZN3KJS8Bindings10RootObjectD1Ev -__ZN3KJS14JSGlobalObject10globalExecEv -__ZN3KJS14JSGlobalObject17startTimeoutCheckEv -__ZN3KJS7UStringC1EPKNS_5UCharEi -__ZN3KJS11Interpreter8evaluateEPNS_9ExecStateERKNS_7UStringEiPKNS_5UCharEiPNS_7JSValueE -__ZN3KJS6ParserC2Ev -__ZN3KJS6Parser5parseINS_11ProgramNodeEEEN3WTF10PassRefPtrIT_EERKNS_7UStringEiPKNS_5UCharEjPiSD_PS7_ -__ZN3KJS6Parser5parseEiPKNS_5UCharEjPiS4_PNS_7UStringE -__ZN3KJS7UStringaSEPKc -__ZN3KJS5LexerC2Ev -__ZN3WTF6VectorIcLm0EE15reserveCapacityEm -__ZN3WTF6VectorIN3KJS5UCharELm0EE15reserveCapacityEm -__ZN3WTF6VectorIPN3KJS7UStringELm0EE15reserveCapacityEm -__ZN3WTF6VectorIPN3KJS10IdentifierELm0EE15reserveCapacityEm -__Z10kjsyyparsev -__Z8kjsyylexv -__ZN3KJS5Lexer3lexEv -__ZN3KJS5Lexer14makeIdentifierERKN3WTF6VectorINS_5UCharELm0EEE -__ZN3KJS10Identifier3addEPKNS_5UCharEi -__ZN3KJS5Lexer15matchPunctuatorEiiii -__ZN3KJS7UStringC2ERKN3WTF6VectorINS_5UCharELm0EEE -__ZN3KJS14ExpressionNodeC2ENS_6JSTypeE -__ZN3KJS16ParserRefCountedC2Ev -__ZN3KJS7UStringC1ERKS0_ -__ZN3KJS4NodeC2Ev -__ZN3KJS10IdentifierC1ERKS0_ -__ZN3WTF6RefPtrIN3KJS14ExpressionNodeEEC1EPS2_ -__ZN3KJS16ParserRefCounted3refEv -__ZN3WTF6RefPtrIN3KJS12PropertyNodeEEC1EPS2_ -__ZN3WTF10ListRefPtrIN3KJS16PropertyListNodeEEC1Ev -__ZN3KJS11ResolveNodeC1ERKNS_10IdentifierE -__ZN3KJS14ExpressionNodeC2Ev -__ZN3WTF10ListRefPtrIN3KJS16ArgumentListNodeEEC1Ev -__Z20makeFunctionCallNodePN3KJS14ExpressionNodeEPNS_13ArgumentsNodeE -__ZNK3KJS15DotAccessorNode10isLocationEv -__ZNK3KJS14ExpressionNode13isResolveNodeEv -__ZNK3KJS14ExpressionNode21isBracketAccessorNodeEv -__Z14makeNumberNoded -__Z14makeNegateNodePN3KJS14ExpressionNodeE -__ZNK3KJS10NumberNode8isNumberEv -__ZN3KJS19ImmediateNumberNode8setValueEd -__ZN3KJS5lexerEv -__ZN3KJS5Lexer10scanRegExpEv -__ZN3KJS6RegExp6createERKNS_7UStringES3_ -__ZNK3KJS7UString4findENS_5UCharEi -__ZN3KJS17ObjectLiteralNodeC1EPNS_16PropertyListNodeE -__Z14compileBracketiPiPPhPPKtS3_P9ErrorCodeiS_S_R11CompileData -__ZN3KJS16FunctionBodyNode6createEPNS_14SourceElementsEPN3WTF6VectorISt4pairINS_10IdentifierEjELm16EEEPNS4_IPNS_12FuncDeclNodeELm16EEE -__ZN3KJS16FunctionBodyNodeC2EPNS_14SourceElementsEPN3WTF6VectorISt4pairINS_10IdentifierEjELm16EEEPNS4_IPNS_12FuncDeclNodeELm16EEE -__ZN3KJS9ScopeNodeC2EPNS_14SourceElementsEPN3WTF6VectorISt4pairINS_10IdentifierEjELm16EEEPNS4_IPNS_12FuncDeclNodeELm16EEE -__ZN3KJS9BlockNodeC1EPNS_14SourceElementsE -__ZN3KJS13StatementNodeC2Ev -__ZN3WTF6RefPtrIN3KJS13ParameterNodeEEC1EPS2_ -__ZN3WTF6RefPtrIN3KJS16FunctionBodyNodeEEC1EPS2_ -__ZN3KJS12FuncExprNode9addParamsEv -__ZN3WTF10ListRefPtrIN3KJS13ParameterNodeEEC1Ev -__ZN3KJS10ReturnNodeC1EPNS_14ExpressionNodeE -__Z23allowAutomaticSemicolonv -__ZN3KJS14SourceElementsC1Ev -__ZN3WTF10PassRefPtrIN3KJS13StatementNodeEEC1EPS2_ -__ZN3KJS14SourceElements6appendEN3WTF10PassRefPtrINS_13StatementNodeEEE -__ZNK3KJS13StatementNode16isEmptyStatementEv -__ZN3WTF6VectorINS_6RefPtrIN3KJS13StatementNodeEEELm0EE14expandCapacityEm -__ZN3WTF6VectorINS_6RefPtrIN3KJS13StatementNodeEEELm0EE15reserveCapacityEm -__ZN3WTF6VectorIN3KJS10IdentifierELm0EE14expandCapacityEmPKS2_ -__ZN3WTF6VectorIN3KJS10IdentifierELm0EE14expandCapacityEm -__ZN3WTF6VectorIN3KJS10IdentifierELm0EE15reserveCapacityEm -__ZN3KJS20ParserRefCountedDataIN3WTF6VectorISt4pairINS_10IdentifierEjELm16EEEEC1Ev -__Z26appendToVarDeclarationListRPN3KJS20ParserRefCountedDataIN3WTF6VectorISt4pairINS_10IdentifierEjELm16EEEEERKS4_j -__Z20makeVarStatementNodePN3KJS14ExpressionNodeE -__Z14makeAssignNodePN3KJS14ExpressionNodeENS_8OperatorES1_ -__ZN3KJS17ExprStatementNodeC1EPNS_14ExpressionNodeE -__ZN3KJS6IfNodeC2EPNS_14ExpressionNodeEPNS_13StatementNodeE -__Z21mergeDeclarationListsIPN3KJS20ParserRefCountedDataIN3WTF6VectorISt4pairINS0_10IdentifierEjELm16EEEEEET_SA_SA_ -__Z21mergeDeclarationListsIPN3KJS20ParserRefCountedDataIN3WTF6VectorIPNS0_12FuncDeclNodeELm16EEEEEET_S9_S9_ -__ZNK3KJS11ResolveNode10isLocationEv -__ZNK3KJS11ResolveNode13isResolveNodeEv -__Z22combineVarInitializersPN3KJS14ExpressionNodeEPNS_17AssignResolveNodeE -__ZN3KJS14ExpressionNode28optimizeForUnnecessaryResultEv -__ZN3WTF6VectorIPN3KJS10IdentifierELm0EE14expandCapacityEmPKS3_ -__ZN3WTF6VectorIPN3KJS10IdentifierELm0EE14expandCapacityEm -__ZN3KJS12FuncDeclNode9addParamsEv -__ZN3WTF6VectorIPN3KJS12FuncDeclNodeELm16EEC1Ev -__ZN3WTF6VectorISt4pairIN3KJS10IdentifierEjELm16EE6appendIS4_EEvPKT_m -__ZN3KJS16ParserRefCounted5derefEv -__ZN3KJS20ParserRefCountedDataIN3WTF6VectorISt4pairINS_10IdentifierEjELm16EEEED1Ev -__Z12makeLessNodePN3KJS14ExpressionNodeES1_ -__Z15makePostfixNodePN3KJS14ExpressionNodeENS_8OperatorE -__ZN3WTF6RefPtrIN3KJS13StatementNodeEEC1EPS2_ -__ZN3KJS18PostIncResolveNode28optimizeForUnnecessaryResultEv -__ZN3WTF6VectorISt4pairIN3KJS10IdentifierEjELm16EEaSERKS5_ -__ZN3WTF6VectorIPN3KJS12FuncDeclNodeELm16EEaSERKS4_ -__ZNK3KJS14ExpressionNode10isLocationEv -__ZNK3KJS19BracketAccessorNode10isLocationEv -__ZNK3KJS19BracketAccessorNode21isBracketAccessorNodeEv -__ZN3KJS9ForInNodeC1ERKNS_10IdentifierEPNS_14ExpressionNodeES5_PNS_13StatementNodeE -__ZN3KJS9ThrowNodeC1EPNS_14ExpressionNodeE -__Z14makeTypeOfNodePN3KJS14ExpressionNodeE -__ZN3WTF6VectorINS_6RefPtrIN3KJS13StatementNodeEEELm0EEC1Ev -__ZN3WTF6RefPtrIN3KJS14CaseClauseNodeEEC1EPS2_ -__ZN3WTF10ListRefPtrIN3KJS14ClauseListNodeEEC1Ev -__ZN3KJS13CaseBlockNodeC2EPNS_14ClauseListNodeEPNS_14CaseClauseNodeES2_ -__Z11makeAddNodePN3KJS14ExpressionNodeES1_ -__ZN3WTF10ListRefPtrIN3KJS11ElementNodeEEC1Ev -__ZN3WTF6RefPtrIN3KJS11ElementNodeEEC1EPS2_ -__ZNK3KJS18EmptyStatementNode16isEmptyStatementEv -__ZN3KJS9BreakNodeC1Ev -__Z32branchFindFirstAssertedCharacterPKhb -__Z20branchNeedsLineStartPKhjj -__ZN3KJS10IdentifierC1ERKNS_7UStringE -__ZN3WTF6RefPtrIN3KJS7UString3RepEED1Ev -__ZN3KJS9CommaNodeC2EPNS_14ExpressionNodeES2_ -__Z14makePrefixNodePN3KJS14ExpressionNodeENS_8OperatorE -__ZN3WTF6RefPtrIN3KJS13ArgumentsNodeEEC1EPS2_ -__ZN3WTF6VectorIPN3KJS7UStringELm0EE14expandCapacityEmPKS3_ -__ZN3WTF6VectorIPN3KJS7UStringELm0EE14expandCapacityEm -__ZN3WTF6VectorIN3KJS5UCharELm0EE14expandCapacityEmPKS2_ -__ZN3WTF6VectorIN3KJS5UCharELm0EE14expandCapacityEm -__ZNK3KJS14ExpressionNode8isNumberEv -__ZN3KJS19PlaceholderTrueNodeC1Ev -__ZN3KJS18EmptyStatementNodeC1Ev -__Z14makeDeleteNodePN3KJS14ExpressionNodeE -__Z15isCountedRepeatPKtS0_ -__ZN3KJS12ContinueNodeC1Ev -__ZN3KJS9ForInNodeC1EPNS_14ExpressionNodeES2_PNS_13StatementNodeE -__ZN3KJS18PostDecResolveNode28optimizeForUnnecessaryResultEv -__Z17bracketIsAnchoredPKh -__ZN3WTF6VectorISt4pairIN3KJS10IdentifierEjELm16EE14expandCapacityEmPKS4_ -__ZN3WTF6VectorISt4pairIN3KJS10IdentifierEjELm16EE14expandCapacityEm -__ZN3WTF6VectorISt4pairIN3KJS10IdentifierEjELm16EE15reserveCapacityEm -__ZN3KJS7UString4fromEd -_kjs_dtoa -_d2b -_Balloc -__ZN3KJS6parserEv -__ZN3KJS6Parser16didFinishParsingEPNS_14SourceElementsEPNS_20ParserRefCountedDataIN3WTF6VectorISt4pairINS_10IdentifierEjELm16EEEEEPNS3_INS5_IPNS_12FuncDeclNodeELm16EEEEEi -__ZN3KJS5Lexer5clearEv -__ZN3WTF25TCMalloc_Central_FreeList11InsertRangeEPvS1_i +__ZN3WTF11fastReallocILb1EEEPvS1_m +__ZN3JSC4Heap8allocateEm +__ZN3JSCL13allocateBlockILNS_8HeapTypeE0EEEPNS_14CollectorBlockEv +__ZN3JSC14JSGlobalObjectnwEmPNS_12JSGlobalDataE +__ZN3JSC14JSGlobalObject4initEPNS_8JSObjectE +__ZN3JSC14JSGlobalObject5resetENS_10JSValuePtrE +__ZN3JSC4Heap12heapAllocateILNS_8HeapTypeE0EEEPvm +__ZN3JSC17FunctionPrototypeC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEE +__ZN3JSC8jsStringEPNS_12JSGlobalDataERKNS_7UStringE +__ZN3JSC12SmallStrings17createEmptyStringEPNS_12JSGlobalDataE +__ZN3JSC7UStringC1EPKc +__ZN3JSCL9createRepEPKc +__ZN3JSC8JSObject9putDirectERKNS_10IdentifierENS_10JSValuePtrEjbRNS_15PutPropertySlotE +__ZN3JSC9Structure40addPropertyTransitionToExistingStructureEPS0_RKNS_10IdentifierEjRm +__ZN3JSC9Structure3getERKNS_10IdentifierERj +__ZN3JSC9Structure21addPropertyTransitionEPS0_RKNS_10IdentifierEjRm +__ZN3JSC9Structure3putERKNS_10IdentifierEj +__ZN3JSC9Structure28addPropertyWithoutTransitionERKNS_10IdentifierEj +__ZN3JSC17FunctionPrototype21addFunctionPropertiesEPNS_9ExecStateEPNS_9StructureE +__ZN3JSC17PrototypeFunctionC1EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEiRKNS_10IdentifierEPFNS_10JSValuePtrES2_PNS_8JSObjectESA_RKNS_7ArgListEE +__ZN3JSC8JSObject34putDirectFunctionWithoutTransitionEPNS_9ExecStateEPNS_16InternalFunctionEj +__ZN3JSC15ObjectPrototypeC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEPS5_ +__ZN3JSC9Structure26rehashPropertyMapHashTableEj +__ZN3JSC15StringPrototypeC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEE +__ZN3JSC16BooleanPrototypeC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEPS5_ +__ZN3JSC15NumberPrototypeC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEPS5_ +__ZN3JSC12jsNumberCellEPNS_9ExecStateEd +__ZN3JSCL13allocateBlockILNS_8HeapTypeE1EEEPNS_14CollectorBlockEv +__ZN3JSC15RegExpPrototypeC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEPS5_ +__ZN3JSC14ErrorPrototypeC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEPS5_ +__ZN3WTF6RefPtrIN3JSC7UString3RepEED1Ev +__ZN3JSC20NativeErrorPrototypeC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEERKNS_7UStringES9_ +__ZN3JSC17ObjectConstructorC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEPNS_15ObjectPrototypeE +__ZN3JSC19FunctionConstructorC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEPNS_17FunctionPrototypeE +__ZNK3JSC16InternalFunction9classInfoEv +__ZN3JSC16ArrayConstructorC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEPNS_14ArrayPrototypeE +__ZNK3JSC14ArrayPrototype9classInfoEv +__ZN3JSC17StringConstructorC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEPS5_PNS_15StringPrototypeE +__ZNK3JSC15StringPrototype9classInfoEv +__ZN3JSC18BooleanConstructorC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEPNS_16BooleanPrototypeE +__ZNK3JSC13BooleanObject9classInfoEv +__ZN3JSC17NumberConstructorC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEPNS_15NumberPrototypeE +__ZN3JSC15DateConstructorC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEPS5_PNS_13DatePrototypeE +__ZNK3JSC13DatePrototype9classInfoEv +__ZN3JSC17RegExpConstructorC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEPNS_15RegExpPrototypeE +__ZN3JSC16ErrorConstructorC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEPNS_14ErrorPrototypeE +__ZNK3JSC13ErrorInstance9classInfoEv +__ZN3JSC22NativeErrorConstructorC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEPNS_20NativeErrorPrototypeE +__ZN3JSC10Identifier11addSlowCaseEPNS_12JSGlobalDataEPNS_7UString3RepE +__ZN3WTF7HashSetIPN3JSC7UString3RepENS_7StrHashIS4_EENS_10HashTraitsIS4_EEE3addERKS4_ +__ZN3JSC10MathObjectC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEE +__ZN3JSC12SmallStrings24singleCharacterStringRepEh +__ZN3WTF7HashMapINS_6RefPtrIN3JSC7UString3RepEEENS2_16SymbolTableEntryENS2_17IdentifierRepHashENS_10HashTraitsIS5_EENS2_26SymbolTableIndexHashTraitsEE3addEPS4_RKS6_ +__ZN3WTF9HashTableINS_6RefPtrIN3JSC7UString3RepEEESt4pairIS5_NS2_16SymbolTableEntryEENS_18PairFirstExtractorIS8_EENS2_17IdentifierRepHashENS_14PairHashTraitsINS_10HashTraitsIS5_EENS2_26SymbolTableIndexHashTraitsEEESE_E6rehashEi +__ZN3JSC9Structure25changePrototypeTransitionEPS0_NS_10JSValuePtrE +__ZN3JSC9Structure17copyPropertyTableEv +__ZN3JSC14JSGlobalObject14setTimeoutTimeEj +__ZN3JSC14JSGlobalObject10globalExecEv +__ZN3JSC10Identifier3addEPNS_9ExecStateEPKc +__ZN3JSC4Heap4heapENS_10JSValuePtrE +__ZN3JSC4Heap7protectENS_10JSValuePtrE +__ZN3WTF7HashMapIPN3JSC6JSCellEjNS_7PtrHashIS3_EENS_10HashTraitsIS3_EENS6_IjEEE3addERKS3_RKj +__ZN3WTF9HashTableIPN3JSC6JSCellESt4pairIS3_jENS_18PairFirstExtractorIS5_EENS_7PtrHashIS3_EENS_14PairHashTraitsINS_10HashTraitsIS3_EENSB_IjEEEESC_E6rehashEi +__ZN3JSC6JSCellnwEmPNS_9ExecStateE +__ZN3JSC14JSGlobalObject17startTimeoutCheckEv +__ZN3JSC11Interpreter17resetTimeoutCheckEv +__ZN3JSC8evaluateEPNS_9ExecStateERNS_10ScopeChainERKNS_10SourceCodeENS_10JSValuePtrE +__ZN3JSC6JSLock4lockEb +__ZN3JSC6Parser5parseINS_11ProgramNodeEEEN3WTF10PassRefPtrIT_EEPNS_9ExecStateEPNS_8DebuggerERKNS_10SourceCodeEPiPNS_7UStringE +__ZN3JSC6Parser5parseEPNS_12JSGlobalDataEPiPNS_7UStringE +__ZN3JSC7UStringaSEPKc +__Z10jscyyparsePv +__ZN3JSC5Lexer3lexEPvS1_ +__ZN3WTF6VectorItLm0EE15reserveCapacityEm +__ZN3WTF6VectorItLm0EE6appendItEEvRKT_ +__ZN3JSC10Identifier3addEPNS_12JSGlobalDataEPKti +__ZN3WTF7HashSetIPN3JSC7UString3RepENS_7StrHashIS4_EENS_10HashTraitsIS4_EEE3addIPKcNS1_17CStringTranslatorEEESt4pairINS_24HashTableIteratorAdapterINS_9HashTableIS4_S4_NS_17IdentityExtractorIS4_EES6_S8_S8_EES4_EEbERKT_ +__ZNK3JSC9HashTable11createTableEPNS_12JSGlobalDataE +__ZN3WTF7HashSetIPN3JSC16ParserRefCountedENS_7PtrHashIS3_EENS_10HashTraitsIS3_EEE3addERKS3_ +__ZN3WTF9HashTableIPN3JSC16ParserRefCountedES3_NS_17IdentityExtractorIS3_EENS_7PtrHashIS3_EENS_10HashTraitsIS3_EES9_E6rehashEi +__ZN3JSC16ParserRefCountedC2EPNS_12JSGlobalDataE +__ZN3JSC16ParserRefCounted3refEv +__ZL20makeFunctionCallNodePvN3JSC8NodeInfoIPNS0_14ExpressionNodeEEENS1_IPNS0_13ArgumentsNodeEEEiii +__ZNK3JSC15DotAccessorNode10isLocationEv +__ZNK3JSC14ExpressionNode13isResolveNodeEv +__ZNK3JSC14ExpressionNode21isBracketAccessorNodeEv +__ZN3WTF7HashMapIPN3JSC16ParserRefCountedEjNS_7PtrHashIS3_EENS_10HashTraitsIS3_EENS6_IjEEE3addERKS3_RKj +__ZN3WTF9HashTableIPN3JSC16ParserRefCountedESt4pairIS3_jENS_18PairFirstExtractorIS5_EENS_7PtrHashIS3_EENS_14PairHashTraitsINS_10HashTraitsIS3_EENSB_IjEEEESC_E6rehashEi +__ZN3JSC14SourceElements6appendEN3WTF10PassRefPtrINS_13StatementNodeEEE +__ZNK3JSC13StatementNode16isEmptyStatementEv +__ZN3JSC6Parser16didFinishParsingEPNS_14SourceElementsEPNS_20ParserRefCountedDataIN3WTF6VectorISt4pairINS_10IdentifierEjELm0EEEEEPNS3_INS5_INS4_6RefPtrINS_12FuncDeclNodeEEELm0EEEEEjii +__ZN3JSC5Lexer5clearEv +__ZN3WTF6VectorIN3JSC10IdentifierELm64EE14shrinkCapacityEm +__ZN3WTF15deleteAllValuesIPN3JSC16ParserRefCountedEKNS_9HashTableIS3_S3_NS_17IdentityExtractorIS3_EENS_7PtrHashIS3_EENS_10HashTraitsIS3_EESA_EEEEvRT0_ +__ZN3JSC15DotAccessorNodeD1Ev +__ZN3JSC12NodeReleaser15releaseAllNodesEPNS_16ParserRefCountedE +__ZN3JSC15DotAccessorNode12releaseNodesERNS_12NodeReleaserE +__ZN3JSC12NodeReleaser5adoptEN3WTF10PassRefPtrINS_16ParserRefCountedEEE +__ZN3JSC16ParserRefCounted9hasOneRefEv +__ZN3JSC16ParserRefCounted5derefEv +__ZN3JSC9ScopeNodeC2EPNS_12JSGlobalDataERKNS_10SourceCodeEPNS_14SourceElementsEPN3WTF6VectorISt4pairINS_10IdentifierEjELm0EEEPNS9_INS8_6RefPtrINS_12FuncDeclNodeEEELm0EEEji +__ZN3WTF6VectorINS_6RefPtrIN3JSC13StatementNodeEEELm0EE14shrinkCapacityEm +__ZN3JSC14SourceElementsD1Ev +__ZNK3JSC8JSObject8toObjectEPNS_9ExecStateE +__ZN3JSC11Interpreter7executeEPNS_11ProgramNodeEPNS_9ExecStateEPNS_14ScopeChainNodeEPNS_8JSObjectEPNS_10JSValuePtrE +__ZN3JSC11ProgramNode16generateBytecodeEPNS_14ScopeChainNodeE +__ZN3JSC9CodeBlockC1EPNS_9ScopeNodeENS_8CodeTypeEN3WTF10PassRefPtrINS_14SourceProviderEEEj +__ZN3WTF7HashSetIPN3JSC16ProgramCodeBlockENS_7PtrHashIS3_EENS_10HashTraitsIS3_EEE3addERKS3_ +__ZN3WTF9HashTableIPN3JSC16ProgramCodeBlockES3_NS_17IdentityExtractorIS3_EENS_7PtrHashIS3_EENS_10HashTraitsIS3_EES9_E6rehashEi +__ZN3JSC17BytecodeGeneratorC2EPNS_11ProgramNodeEPKNS_8DebuggerERKNS_10ScopeChainEPN3WTF7HashMapINS9_6RefPtrINS_7UString3RepEEENS_16SymbolTableEntryENS_17IdentifierRepHashENS9_10HashTraitsISE_EENS_26SymbolTableIndexHashTraitsEEEPNS_16ProgramCodeBlockE +__ZN3WTF6VectorIN3JSC11InstructionELm0EE14expandCapacityEm +__ZN3JSC9Structure22toDictionaryTransitionEPS0_ +__ZN3JSC17BytecodeGenerator11newRegisterEv +__ZN3JSC9Structure24fromDictionaryTransitionEPS0_ +__ZN3JSC17BytecodeGenerator8generateEv +__ZN3JSC11ProgramNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZN3JSC17BytecodeGenerator13emitDebugHookENS_11DebugHookIDEii +__ZN3JSC17BytecodeGenerator11addConstantENS_10JSValuePtrE +__ZN3WTF9HashTableIPN3JSC23JSValueEncodedAsPointerESt4pairIS3_jENS_18PairFirstExtractorIS5_EENS_7PtrHashIS3_EENS_14PairHashTraitsINS1_17BytecodeGenerator17JSValueHashTraitsENS_10HashTraitsIjEEEESC_E6expandEv +__ZN3WTF6VectorIN3JSC8RegisterELm0EE14expandCapacityEm +__ZNK3JSC13StatementNode6isLoopEv +__ZN3JSC17BytecodeGenerator8emitNodeEPNS_10RegisterIDEPNS_4NodeE +__ZN3WTF6VectorIN3JSC8LineInfoELm0EE14expandCapacityEm +__ZN3JSC17ExprStatementNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZN3JSC19FunctionCallDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZN3JSC11ResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZN3JSC17BytecodeGenerator11registerForERKNS_10IdentifierE +__ZN3WTF6VectorIN3JSC19ExpressionRangeInfoELm0EE14expandCapacityEm +__ZN3JSC17BytecodeGenerator11emitGetByIdEPNS_10RegisterIDES2_RKNS_10IdentifierE +__ZN3WTF6VectorIN3JSC17StructureStubInfoELm0EE14expandCapacityEm +__ZN3JSC17BytecodeGenerator11addConstantERKNS_10IdentifierE +__ZN3WTF9HashTableINS_6RefPtrIN3JSC7UString3RepEEESt4pairIS5_iENS_18PairFirstExtractorIS7_EENS2_17IdentifierRepHashENS_14PairHashTraitsINS_10HashTraitsIS5_EENS2_17BytecodeGenerator28IdentifierMapIndexHashTraitsEEESD_E6expandEv +__ZN3WTF6VectorIN3JSC10IdentifierELm0EE14expandCapacityEm +__ZN3JSC17BytecodeGenerator8emitCallENS_8OpcodeIDEPNS_10RegisterIDES3_S3_PNS_13ArgumentsNodeEjjj +__ZN3WTF6VectorIN3JSC12CallLinkInfoELm0EE14expandCapacityEm +__ZN3JSC9CodeBlock11shrinkToFitEv +__ZN3WTF6VectorIN3JSC11InstructionELm0EE14shrinkCapacityEm +__ZN3WTF6VectorIN3JSC17StructureStubInfoELm0EE14shrinkCapacityEm +__ZN3WTF6VectorIN3JSC17GlobalResolveInfoELm0EE14shrinkCapacityEm +__ZN3WTF6VectorIPN3JSC12CallLinkInfoELm0EE14shrinkCapacityEm +__ZN3WTF6VectorIN3JSC10IdentifierELm0EE14shrinkCapacityEm +__ZN3JSC17ExprStatementNodeD1Ev +__ZN3JSC19FunctionCallDotNodeD1Ev +__ZN3JSC19FunctionCallDotNode12releaseNodesERNS_12NodeReleaserE +__ZN3WTF6VectorINS_6RefPtrIN3JSC16ParserRefCountedEEELm0EE14expandCapacityEm +__ZN3JSC16ParserRefCounted12releaseNodesERNS_12NodeReleaserE +__ZN3JSC13ArgumentsNode12releaseNodesERNS_12NodeReleaserE +__ZN3JSC11ResolveNodeD1Ev +__ZN3JSC13ArgumentsNodeD1Ev +__ZN3JSC14JSGlobalObject13copyGlobalsToERNS_12RegisterFileE +__ZN3JSC3JIT14privateCompileEv +__ZN3JSC3JIT22privateCompileMainPassEv +__ZN3JSC3JIT21compileGetByIdHotPathEiiPNS_10IdentifierEj +__ZN3WTF6VectorIN3JSC13SlowCaseEntryELm0EE14expandCapacityEm +__ZN3JSC3JIT13compileOpCallENS_8OpcodeIDEPNS_11InstructionEj +__ZN3WTF6VectorIN3JSC10CallRecordELm0EE14expandCapacityEm +__ZN3JSC3JIT22privateCompileLinkPassEv +__ZN3JSC3JIT23privateCompileSlowCasesEv +__ZN3JSC3JIT22compileGetByIdSlowCaseEiiPNS_10IdentifierERPNS_13SlowCaseEntryEj +__ZN3JSC3JIT21compileOpCallSlowCaseEPNS_11InstructionERPNS_13SlowCaseEntryEjNS_8OpcodeIDE +__ZN3JSC3JIT22compileOpCallSetupArgsEPNS_11InstructionE +__ZN3JSC12X86Assembler3jneEv +__ZN3WTF6VectorIN3JSC10CallRecordELm0EE6appendIS2_EEvRKT_ +__ZN3JSC9CodeBlock10setJITCodeERNS_10JITCodeRefE +__ZN3JSC17BytecodeGenerator18dumpsGeneratedCodeEv +__ZN3WTF10RefCountedIN3JSC14ExecutablePoolEE5derefEv +ctiTrampoline +__ZN3JSC11Interpreter16cti_op_get_by_idEPvz +__ZNK3JSC10JSValuePtr3getEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE +__ZN3JSC10MathObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE +__ZN3JSC23setUpStaticFunctionSlotEPNS_9ExecStateEPKNS_9HashEntryEPNS_8JSObjectERKNS_10IdentifierERNS_12PropertySlotE +__ZN3JSC17PrototypeFunctionC1EPNS_9ExecStateEiRKNS_10IdentifierEPFNS_10JSValuePtrES2_PNS_8JSObjectES6_RKNS_7ArgListEE +__ZN3JSC27ctiPatchCallByReturnAddressEPvS0_ +__ZN3JSC11Interpreter25cti_op_call_NotJSFunctionEPvz +__ZN3JSC17PrototypeFunction11getCallDataERNS_8CallDataE +__ZN3JSCL19mathProtoFuncRandomEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3WTF12randomNumberEv +__ZN3JSC11ProgramNodeD1Ev +__ZN3WTF9HashTableIPN3JSC16ProgramCodeBlockES3_NS_17IdentityExtractorIS3_EENS_7PtrHashIS3_EENS_10HashTraitsIS3_EES9_E4findIS3_NS_22IdentityHashTranslatorIS3_S3_S7_EEEENS_17HashTableIteratorIS3_S3_S5_S7_S9_S9_EERKT_ +__ZN3JSC9CodeBlockD2Ev +__ZN3JSC17StructureStubInfo5derefEv +__ZN3JSC9ScopeNode12releaseNodesERNS_12NodeReleaserE +__ZN3JSC14JSGlobalObject16stopTimeoutCheckEv +__ZN3JSC4Heap9unprotectENS_10JSValuePtrE +__ZNK3JSC12JSNumberCell8toStringEPNS_9ExecStateE +__ZN3JSC7UString4fromEd +__ZN3WTF4dtoaEdiPiS0_PPc +__ZN3WTFL3d2bEdPiS0_ +__ZN3WTFL8pow5multEPNS_6BigintEi +__ZN3WTFL4multEPNS_6BigintES1_ +__ZN3WTFL6lshiftEPNS_6BigintEi +__ZN3WTFL6quoremEPNS_6BigintES1_ +__ZN3WTFL4diffEPNS_6BigintES1_ +__ZN3JSC7UString3Rep7destroyEv +-[WTFMainThreadCaller call] +__ZN3WTF31dispatchFunctionsFromMainThreadEv +__ZN3JSC4Heap7collectEv +__ZN3JSC4Heap30markStackObjectsConservativelyEv +__ZN3JSC4Heap31markCurrentThreadConservativelyEv +__ZN3JSC4Heap39markCurrentThreadConservativelyInternalEv +__ZN3JSC4Heap18markConservativelyEPvS1_ +__ZN3JSC4Heap20markProtectedObjectsEv +__ZN3JSC12SmallStrings4markEv +__ZN3JSC6JSCell4markEv +__ZN3JSC4Heap5sweepILNS_8HeapTypeE0EEEmv +__ZN3JSC14JSGlobalObjectD2Ev +__ZN3JSC17FunctionPrototypeD0Ev +__ZN3JSC17PrototypeFunctionD0Ev +__ZN3JSC16BooleanPrototypeD0Ev +__ZN3JSC15NumberPrototypeD0Ev +__ZN3JSC14ErrorPrototypeD0Ev +__ZN3JSC17ObjectConstructorD0Ev +__ZN3JSC16ArrayConstructorD0Ev +__ZN3JSC17StringConstructorD0Ev +__ZN3JSC18BooleanConstructorD0Ev +__ZN3JSC17NumberConstructorD0Ev +__ZN3JSC17RegExpConstructorD0Ev +__ZN3JSC16ErrorConstructorD0Ev +__ZN3JSC22NativeErrorConstructorD0Ev +__ZN3JSC18GlobalEvalFunctionD0Ev +__ZN3JSC4Heap5sweepILNS_8HeapTypeE1EEEmv __ZN3WTF25TCMalloc_Central_FreeList11ShrinkCacheEib -__ZN3WTF25TCMalloc_Central_FreeList18ReleaseListToSpansEPv -__ZN3WTF15deleteAllValuesIPN3KJS16ParserRefCountedEKNS_9HashTableIiiNS_17IdentityExtractorIiEENS_7IntHashIiEENS_10HashTraitsIiEESA_EEEEvRT0_ -__ZN3KJS19BracketAccessorNodeD1Ev -__ZN3KJS11ProgramNodeC2EPNS_14SourceElementsEPN3WTF6VectorISt4pairINS_10IdentifierEjELm16EEEPNS4_IPNS_12FuncDeclNodeELm16EEE -__ZNK3KJS8JSObject8toObjectEPNS_9ExecStateE -__ZN3KJS11ProgramNode7executeEPNS_9ExecStateE -__ZN3KJS11ProgramNode21initializeSymbolTableEPNS_9ExecStateE -__ZN3WTF6VectorImLm0EE6resizeEm -__ZN3WTF6VectorImLm0EE14expandCapacityEm -__ZN3WTF6VectorImLm0EE15reserveCapacityEm -__ZN3WTF9HashTableINS_6RefPtrIN3KJS7UString3RepEEESt4pairIS5_mENS_18PairFirstExtractorIS7_EENS2_17IdentifierRepHashENS_14PairHashTraitsINS2_23IdentifierRepHashTraitsENS2_26SymbolTableIndexHashTraitsEEESC_E3addIS5_mNS_17HashMapTranslatorILb1ES7_NS_18PairBaseHashTraitsISC_SD_EESE_SA_EEEES6_INS_17HashTableIteratorIS5_S7_S9_SA_SE_SC_EEbERKT_RKT0_ -__ZN3WTF9HashTableINS_6RefPtrIN3KJS7UString3RepEEESt4pairIS5_mENS_18PairFirstExtractorIS7_EENS2_17IdentifierRepHashENS_14PairHashTraitsINS2_23IdentifierRepHashTraitsENS2_26SymbolTableIndexHashTraitsEEESC_E6rehashEi -__ZN3KJS14JSGlobalObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE -__ZNK3WTF7HashMapINS_6RefPtrIN3KJS7UString3RepEEEmNS2_17IdentifierRepHashENS2_23IdentifierRepHashTraitsENS2_26SymbolTableIndexHashTraitsEE3getEPS4_ -__ZN3KJS11PropertyMap11getLocationERKNS_10IdentifierE -__ZN3KJS6Lookup9findEntryEPKNS_9HashTableERKNS_10IdentifierE -__ZNK3KJS7UString14toStrictUInt32EPb -__ZN3KJS8JSObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE -__ZN3WTF6VectorIN3KJS17LocalStorageEntryELm32EE15reserveCapacityEm -__ZN3KJS11FunctionImpC2EPNS_9ExecStateERKNS_10IdentifierEPNS_16FunctionBodyNodeERKNS_10ScopeChainE -__ZN3KJS15ObjectObjectImp9constructEPNS_9ExecStateERKNS_4ListE -__ZN3KJS9ScopeNode22optimizeVariableAccessEPNS_9ExecStateE -__ZN3WTF6VectorIPN3KJS4NodeELm16EE14expandCapacityEm -__ZN3WTF6VectorIPN3KJS4NodeELm16EE15reserveCapacityEm -__ZN3KJS16VarStatementNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS17AssignResolveNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS17ObjectLiteralNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS16PropertyListNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS12PropertyNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS4Node22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPS0_Lm16EEE -__ZN3KJS14LogicalNotNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS14LogicalAndNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS15DotAccessorNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS11ResolveNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS11GreaterNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS19FunctionCallDotNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS13ArgumentsNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS16ArgumentListNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS9EqualNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS18NotStrictEqualNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS6IfNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS17ExprStatementNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS13AssignDotNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS13LogicalOrNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS8WithNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS9BlockNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS23FunctionCallResolveNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS21FunctionCallValueNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS9ArrayNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS11ElementNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS10IfElseNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS7AddNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS6InNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS11NewExprNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS16VarStatementNode7executeEPNS_9ExecStateE -__ZN3KJS18AssignLocalVarNode8evaluateEPNS_9ExecStateE -__ZN3KJS17ObjectLiteralNode8evaluateEPNS_9ExecStateE -__ZN3KJS16PropertyListNode8evaluateEPNS_9ExecStateE -__ZN3KJS10StringNode8evaluateEPNS_9ExecStateE -__ZN3KJS13jsOwnedStringERKNS_7UStringE -__ZN3KJS8JSObject3putEPNS_9ExecStateERKNS_10IdentifierEPNS_7JSValueEi -__ZN3KJS14LogicalNotNode8evaluateEPNS_9ExecStateE -__ZN3KJS14LogicalNotNode17evaluateToBooleanEPNS_9ExecStateE -__ZN3KJS14LogicalAndNode17evaluateToBooleanEPNS_9ExecStateE -__ZN3KJS15DotAccessorNode17evaluateToBooleanEPNS_9ExecStateE -__ZN3KJS11ResolveNode8evaluateEPNS_9ExecStateE -__ZN3KJS11GreaterNode8evaluateEPNS_9ExecStateE -__ZN3KJS19FunctionCallDotNode8evaluateEPNS_9ExecStateE -__ZN3KJS15DotAccessorNode8evaluateEPNS_9ExecStateE -__ZNK3KJS9ExecState19lexicalGlobalObjectEv -__ZNK3KJS9StringImp8toObjectEPNS_9ExecStateE -__ZN3KJS14StringInstance18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE -__ZN3KJS15StringPrototype18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE -__ZN3KJS20staticFunctionGetterEPNS_9ExecStateEPNS_8JSObjectERKNS_10IdentifierERKNS_12PropertySlotE -__ZN3KJS17PrototypeFunctionC1EPNS_9ExecStateEiRKNS_10IdentifierEPFPNS_7JSValueES2_PNS_8JSObjectERKNS_4ListEE -__ZNK3KJS19InternalFunctionImp14implementsCallEv -__ZN3KJS16ArgumentListNode12evaluateListEPNS_9ExecStateERNS_4ListE -__ZN3KJS17PrototypeFunction14callAsFunctionEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS22stringProtoFuncIndexOfEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZNK3KJS14StringInstance9classInfoEv -__ZNK3KJS9StringImp8toStringEPNS_9ExecStateE -__ZNK3KJS7JSValue9toIntegerEPNS_9ExecStateE -__ZNK3KJS7UString4findERKS0_i -__ZN3KJS19ImmediateNumberNode8evaluateEPNS_9ExecStateE -__ZN3KJS14LogicalAndNode8evaluateEPNS_9ExecStateE -__ZN3KJS9EqualNode8evaluateEPNS_9ExecStateE -__ZN3KJS5equalEPNS_9ExecStateEPNS_7JSValueES3_ -__ZN3KJS19FunctionCallDotNode17evaluateToBooleanEPNS_9ExecStateE -__ZN3KJS10RegExpNode8evaluateEPNS_9ExecStateE -__ZN3KJS15RegExpObjectImp15createRegExpImpEPNS_9ExecStateEN3WTF10PassRefPtrINS_6RegExpEEE -__ZN3KJS20stringProtoFuncMatchEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZNK3KJS9RegExpImp9classInfoEv -__ZN3KJS15RegExpObjectImp12performMatchEPNS_6RegExpERKNS_7UStringEiRiS6_PPi -__ZN3KJS6RegExp5matchERKNS_7UStringEiPN3WTF11OwnArrayPtrIiEE -__Z5matchPKtPKhiR9MatchData -__ZNK3KJS8JSObject9toBooleanEPNS_9ExecStateE -__ZN3KJS18NotStrictEqualNode8evaluateEPNS_9ExecStateE -__ZNK3KJS7UString8toUInt32EPbb -__ZNK3KJS7UString8toDoubleEbb -__ZN3KJS11strictEqualEPNS_9ExecStateEPNS_7JSValueES3_ -__ZN3KJS12FuncExprNode8evaluateEPNS_9ExecStateE -__ZN3KJS14JSGlobalObject17tearOffActivationEPNS_9ExecStateEb -__ZN3KJS6IfNode7executeEPNS_9ExecStateE -__ZN3KJS18LocalVarAccessNode8evaluateEPNS_9ExecStateE -__ZN3KJS17ExprStatementNode7executeEPNS_9ExecStateE -__ZN3KJS13AssignDotNode8evaluateEPNS_9ExecStateE -__ZN3KJS11FunctionImp14callAsFunctionEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS17FunctionExecStateC1EPNS_14JSGlobalObjectEPNS_8JSObjectEPNS_16FunctionBodyNodeEPNS_9ExecStateEPNS_11FunctionImpERKNS_4ListE -__ZN3KJS14JSGlobalObject14pushActivationEPNS_9ExecStateE -__ZN3KJS13ActivationImp4initEPNS_9ExecStateE -__ZN3KJS16FunctionBodyNode7executeEPNS_9ExecStateE -__ZN3KJS16FunctionBodyNode21initializeSymbolTableEPNS_9ExecStateE -__ZN3KJS9ForInNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS17AssignBracketNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS19BracketAccessorNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS10ReturnNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS9ForInNode7executeEPNS_9ExecStateE -__ZN3KJS8JSObject16getPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayE -__ZNK3KJS11PropertyMap26getEnumerablePropertyNamesERNS_17PropertyNameArrayE -__ZNK3KJS8JSObject9classInfoEv -__ZN3KJS13ActivationImp18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE -__ZN3KJS13ActivationImp3putEPNS_9ExecStateERKNS_10IdentifierEPNS_7JSValueEi -__ZN3KJS17AssignBracketNode8evaluateEPNS_9ExecStateE -__ZNK3KJS6JSCell9getUInt32ERj -__ZN3KJS19BracketAccessorNode8evaluateEPNS_9ExecStateE -__ZN3KJS10ReturnNode7executeEPNS_9ExecStateE -__ZN3KJS14JSGlobalObject13popActivationEv -__ZN3KJS11FunctionImp18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE -__ZN3KJS10NumberNode8evaluateEPNS_9ExecStateE -__ZN3KJS9CommaNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS13ActivationImpC1ERKNS0_14ActivationDataEb -__ZN3WTF6VectorIN3KJS17LocalStorageEntryELm32EEC2ERKS3_ -__ZN3KJS13ActivationImp15argumentsGetterEPNS_9ExecStateEPNS_8JSObjectERKNS_10IdentifierERKNS_12PropertySlotE -__ZN3KJS13ActivationImp21createArgumentsObjectEPNS_9ExecStateE -__ZN3KJS9ArgumentsC2EPNS_9ExecStateEPNS_11FunctionImpERKNS_4ListEPNS_13ActivationImpE -__ZN3KJS14IndexToNameMapC2EPNS_11FunctionImpERKNS_4ListE -__ZN3KJS11FunctionImp16getParameterNameEi -__ZN3KJS7UString4fromEj -__ZN3KJS9Arguments18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE -__ZN3KJS9CommaNode8evaluateEPNS_9ExecStateE -__ZN3KJS8ThisNode8evaluateEPNS_9ExecStateE -__ZN3KJS23FunctionCallResolveNode8evaluateEPNS_9ExecStateE -__ZN3KJS9WhileNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS18PostDecResolveNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS18LocalVarAccessNode17evaluateToBooleanEPNS_9ExecStateE -__ZN3KJS13LogicalOrNode8evaluateEPNS_9ExecStateE -__ZN3KJS11NewExprNode8evaluateEPNS_9ExecStateE -__ZNK3KJS14ArrayObjectImp19implementsConstructEv -__ZN3KJS14ArrayObjectImp9constructEPNS_9ExecStateERKNS_4ListE -__ZN3KJS9WhileNode7executeEPNS_9ExecStateE -__ZN3KJS19PostDecLocalVarNode17evaluateToBooleanEPNS_9ExecStateE -__ZN3KJS8JSObject18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE -__ZN3KJS13ArrayInstance3putEPNS_9ExecStateEjPNS_7JSValueEi -__ZN3KJS15RegExpObjectImp18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE -__ZN3KJS15RegExpObjectImp3putEPNS_9ExecStateERKNS_10IdentifierEPNS_7JSValueEi -__ZN3KJS7ForNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS8LessNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS17PreIncResolveNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS8NullNode8evaluateEPNS_9ExecStateE -__ZN3KJS13ArrayInstance18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE -__ZN3KJS17TypeOfResolveNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS18LocalVarTypeOfNode8evaluateEPNS_9ExecStateE -__ZN3KJS18typeStringForValueEPNS_7JSValueE -__ZNK3KJS8JSObject21masqueradeAsUndefinedEv -__ZNK3KJS8JSObject14implementsCallEv -__ZN3KJS12FuncDeclNode7executeEPNS_9ExecStateE -__ZN3KJS11FunctionImp3putEPNS_9ExecStateERKNS_10IdentifierEPNS_7JSValueEi -__ZN3KJS9ArrayNode8evaluateEPNS_9ExecStateE -__ZN3KJS13ArrayInstanceC2EPNS_8JSObjectERKNS_4ListE -__ZN3KJS13ArrayInstance3putEPNS_9ExecStateERKNS_10IdentifierEPNS_7JSValueEi -__ZN3KJS13ArrayInstance9setLengthEj -__ZN3KJS7ForNode7executeEPNS_9ExecStateE -__ZN3KJS8LessNode17evaluateToBooleanEPNS_9ExecStateE -__ZN3KJS13ArrayInstance18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE -__ZN3KJS13ArrayInstance12lengthGetterEPNS_9ExecStateEPNS_8JSObjectERKNS_10IdentifierERKNS_12PropertySlotE -__ZN3KJS14ArrayPrototype18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE -__ZN3KJS18arrayProtoFuncPushEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS8TrueNode8evaluateEPNS_9ExecStateE -__ZN3KJS9BlockNode7executeEPNS_9ExecStateE -__ZN3KJS18PreIncLocalVarNode8evaluateEPNS_9ExecStateE -__ZN3KJS14StringInstance3putEPNS_9ExecStateERKNS_10IdentifierEPNS_7JSValueEi -__ZN3KJS13LogicalOrNode17evaluateToBooleanEPNS_9ExecStateE -__ZN3KJS8WithNode7executeEPNS_9ExecStateE -__ZN3KJS15NumberObjectImp18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE -__ZN3KJS24LocalVarFunctionCallNode8evaluateEPNS_9ExecStateE -__ZN3KJS15ConditionalNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS22stringProtoFuncReplaceEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS7replaceEPNS_9ExecStateEPNS_9StringImpEPNS_7JSValueES5_ -__ZNK3KJS7UString30spliceSubstringsWithSeparatorsEPKNS0_5RangeEiPKS0_i -__ZN3KJS15ConditionalNode8evaluateEPNS_9ExecStateE -__ZNK3KJS9StringImp9toBooleanEPNS_9ExecStateE -__ZN3KJS20stringProtoFuncSplitEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZNK3KJS7UString6substrEii -__ZN3KJS7UString3Rep6createEN3WTF10PassRefPtrIS1_EEii -__ZN3KJS7TryNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS15LessNumbersNode17evaluateToBooleanEPNS_9ExecStateE -__ZN3KJS15DotAccessorNode16evaluateToNumberEPNS_9ExecStateE -__ZN3KJS10NumberNode16evaluateToNumberEPNS_9ExecStateE -__ZN3KJS7TryNode7executeEPNS_9ExecStateE -__ZN3KJS21arrayProtoFuncForEachEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS18PostIncResolveNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS18PostIncResolveNode8evaluateEPNS_9ExecStateE -__ZN3KJS13ActivationImp18isActivationObjectEv -__ZN3KJS13MathObjectImp18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE -__ZN3KJS21FunctionCallValueNode8evaluateEPNS_9ExecStateE -__ZN3KJS12NotEqualNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS9FalseNode8evaluateEPNS_9ExecStateE -__ZN3KJS19arrayProtoFuncShiftEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS13ArrayInstance14deletePropertyEPNS_9ExecStateEj -__ZNK3KJS11FunctionImp19implementsConstructEv -__ZN3KJS11FunctionImp9constructEPNS_9ExecStateERKNS_4ListE -__ZN3KJS9EqualNode17evaluateToBooleanEPNS_9ExecStateE -__ZN3KJS25functionProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZNK3KJS11FunctionImp9classInfoEv -__ZNK3KJS4Node8toStringEv -__ZNK3KJS9ScopeNode8streamToERNS_12SourceStreamE -__ZN3KJS7UString6appendEt -__ZN3KJS7UString6appendERKS0_ -__ZN3KJS7UString6appendEPKc -__ZN3KJS7UString14expandCapacityEi -__ZN3KJS12SourceStreamlsEPKNS_4NodeE -__ZNK3KJS17ExprStatementNode8streamToERNS_12SourceStreamE -__ZNK3KJS4Node21needsParensIfLeftmostEv -__ZNK3KJS23FunctionCallResolveNode8streamToERNS_12SourceStreamE -__ZNK3KJS13ArgumentsNode8streamToERNS_12SourceStreamE -__ZNK3KJS16ArgumentListNode8streamToERNS_12SourceStreamE -__ZNK3KJS11ResolveNode10precedenceEv -__ZNK3KJS11ResolveNode8streamToERNS_12SourceStreamE -__ZNK3KJS13AssignDotNode8streamToERNS_12SourceStreamE -__ZNK3KJS8ThisNode10precedenceEv -__ZNK3KJS8ThisNode8streamToERNS_12SourceStreamE -__ZNK3KJS19FunctionCallDotNode10precedenceEv -__ZNK3KJS19FunctionCallDotNode8streamToERNS_12SourceStreamE -__ZNK3KJS16FunctionBodyNode11paramStringEv -__ZNK3KJS15RegExpObjectImp14arrayOfMatchesEPNS_9ExecStateE -__ZN3KJS9Arguments17mappedIndexGetterEPNS_9ExecStateEPNS_8JSObjectERKNS_10IdentifierERKNS_12PropertySlotE -__ZN3KJS19arrayProtoFuncSliceEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS22functionProtoFuncApplyEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZNK3KJS13ArrayInstance9classInfoEv -__ZN3KJS24substituteBackreferencesERKNS_7UStringES2_PiPNS_6RegExpE -__ZNK3KJS15DotAccessorNode10precedenceEv -__ZNK3KJS15DotAccessorNode8streamToERNS_12SourceStreamE -__ZNK3KJS16VarStatementNode8streamToERNS_12SourceStreamE -__ZNK3KJS17AssignResolveNode8streamToERNS_12SourceStreamE -__ZNK3KJS6IfNode8streamToERNS_12SourceStreamE -__ZNK3KJS14LogicalNotNode8streamToERNS_12SourceStreamE -__ZNK3KJS9ArrayNode10precedenceEv -__ZNK3KJS9ArrayNode8streamToERNS_12SourceStreamE -__ZNK3KJS11ElementNode8streamToERNS_12SourceStreamE -__ZNK3KJS10StringNode10precedenceEv -__ZNK3KJS10StringNode8streamToERNS_12SourceStreamE -__ZN3KJS29escapeStringForPrettyPrintingERKNS_7UStringE -__ZNK3KJS9BlockNode8streamToERNS_12SourceStreamE -__ZNK3KJS17AssignBracketNode8streamToERNS_12SourceStreamE -__ZNK3KJS10IfElseNode8streamToERNS_12SourceStreamE -__ZNK3KJS9EqualNode8streamToERNS_12SourceStreamE -__ZNK3KJS9EqualNode10precedenceEv -__ZN3KJS35streamLeftAssociativeBinaryOperatorERNS_12SourceStreamENS_10PrecedenceEPKcPKNS_4NodeES7_ -__ZNK3KJS17ReadModifyDotNode8streamToERNS_12SourceStreamE -__ZNK3KJS7AddNode10precedenceEv -__ZNK3KJS7AddNode8streamToERNS_12SourceStreamE -__ZNK3KJS15ConditionalNode10precedenceEv -__ZNK3KJS15ConditionalNode8streamToERNS_12SourceStreamE -__ZNK3KJS10RegExpNode10precedenceEv -__ZNK3KJS10RegExpNode8streamToERNS_12SourceStreamE -__ZNK3KJS21ReadModifyResolveNode8streamToERNS_12SourceStreamE -__ZNK3KJS7TryNode8streamToERNS_12SourceStreamE -__ZNK3KJS11NewExprNode10precedenceEv -__ZNK3KJS11NewExprNode8streamToERNS_12SourceStreamE -__ZNK3KJS10NumberNode10precedenceEv -__ZNK3KJS10NumberNode8streamToERNS_12SourceStreamE -__ZN3KJS12SourceStreamlsEd -__ZNK3KJS13LogicalOrNode10precedenceEv -__ZNK3KJS13LogicalOrNode8streamToERNS_12SourceStreamE -__ZNK3KJS8NullNode10precedenceEv -__ZNK3KJS8NullNode8streamToERNS_12SourceStreamE -__ZNK3KJS14LogicalAndNode8streamToERNS_12SourceStreamE -__ZNK3KJS14LogicalAndNode10precedenceEv -__ZNK3KJS14LogicalNotNode10precedenceEv -__ZN3KJS7UString17expandPreCapacityEi -__ZN3KJS19BracketAccessorNode17evaluateToBooleanEPNS_9ExecStateE -__ZNK3KJS11GreaterNode10precedenceEv -__ZNK3KJS11GreaterNode8streamToERNS_12SourceStreamE -__ZNK3KJS17ObjectLiteralNode10precedenceEv -__ZNK3KJS17ObjectLiteralNode8streamToERNS_12SourceStreamE -__ZNK3KJS16PropertyListNode8streamToERNS_12SourceStreamE -__ZNK3KJS12PropertyNode8streamToERNS_12SourceStreamE -__ZNK3KJS8LessNode10precedenceEv -__ZNK3KJS8LessNode8streamToERNS_12SourceStreamE -__ZNK3KJS19BracketAccessorNode10precedenceEv -__ZNK3KJS19BracketAccessorNode8streamToERNS_12SourceStreamE -__ZNK3KJS15TypeOfValueNode10precedenceEv -__ZNK3KJS15TypeOfValueNode8streamToERNS_12SourceStreamE -__ZNK3KJS7ForNode8streamToERNS_12SourceStreamE -__ZNK3KJS9CommaNode8streamToERNS_12SourceStreamE -__ZNK3KJS17AssignResolveNode10precedenceEv -__ZNK3KJS23FunctionCallResolveNode10precedenceEv -__ZNK3KJS12FuncExprNode10precedenceEv -__ZNK3KJS12FuncExprNode8streamToERNS_12SourceStreamE -__ZNK3KJS13ParameterNode8streamToERNS_12SourceStreamE -__ZNK3KJS9ForInNode8streamToERNS_12SourceStreamE -__ZNK3KJS10ReturnNode8streamToERNS_12SourceStreamE -__ZNK3KJS13GreaterEqNode10precedenceEv -__ZNK3KJS13GreaterEqNode8streamToERNS_12SourceStreamE -__ZNK3KJS8TrueNode10precedenceEv -__ZNK3KJS8TrueNode8streamToERNS_12SourceStreamE -__ZNK3KJS21FunctionCallValueNode8streamToERNS_12SourceStreamE -__ZN3KJS11ElementNode8evaluateEPNS_9ExecStateE -__ZNK3KJS8MultNode10precedenceEv -__ZNK3KJS8MultNode8streamToERNS_12SourceStreamE -__ZN3KJS21functionProtoFuncCallEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZNK3KJS4List8getSliceEiRS0_ -__ZN3KJS10IfElseNode7executeEPNS_9ExecStateE -__ZN3KJS6InNode17evaluateToBooleanEPNS_9ExecStateE -__ZNK3KJS12NotEqualNode10precedenceEv -__ZNK3KJS12NotEqualNode8streamToERNS_12SourceStreamE -__ZN3KJS17AssignResolveNode8evaluateEPNS_9ExecStateE -__ZN3KJS13DeleteDotNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS12ContinueNode7executeEPNS_9ExecStateE -__ZN3KJS13DeleteDotNode8evaluateEPNS_9ExecStateE -__ZN3KJS11FunctionImp14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE -__ZN3KJS8JSObject14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE -__ZNK3KJS11PropertyMap3getERKNS_10IdentifierERj -__ZN3KJS11GreaterNode17evaluateToBooleanEPNS_9ExecStateE -__ZN3KJS13PrefixDotNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS13PreIncDotNode8evaluateEPNS_9ExecStateE -__ZN3KJS14JSGlobalObject3putEPNS_9ExecStateERKNS_10IdentifierEPNS_7JSValueEi -__ZNK3KJS8JSObject8toStringEPNS_9ExecStateE -__ZNK3KJS8JSObject11toPrimitiveEPNS_9ExecStateENS_6JSTypeE -__ZNK3KJS8JSObject12defaultValueEPNS_9ExecStateENS_6JSTypeE -__ZN3KJS22arrayProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3WTF9HashTableIiiNS_17IdentityExtractorIiEENS_7IntHashIiEENS_10HashTraitsIiEES6_E3addIPN3KJS16RuntimeObjectImpESB_NS_17HashSetTranslatorILb1ESB_NS5_ISB_EES6_NS_7PtrHashISB_EEEEEESt4pairINS_17HashTableIteratorIiiS2_S4_S6_S6_EEbERKT_RKT0_ -__ZN3KJS11JSImmediate8toStringEPKNS_7JSValueE -__ZN3KJS12NotEqualNode17evaluateToBooleanEPNS_9ExecStateE -__ZN3KJS21arrayProtoFuncIndexOfEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZNK3KJS14ErrorObjectImp19implementsConstructEv -__ZN3KJS14ErrorObjectImp9constructEPNS_9ExecStateERKNS_4ListE -__ZN3KJS9Collector7collectEv -__ZN3KJS9Collector31markCurrentThreadConservativelyEv -__ZN3KJS9Collector30markStackObjectsConservativelyEPvS1_ -__ZN3KJS6JSCell4markEv -__ZN3KJS8JSObject4markEv -__ZNK3KJS11PropertyMap4markEv -__ZN3KJS11FunctionImp4markEv -__ZN3KJS14JSGlobalObject4markEv -__ZN3KJS16JSVariableObject4markEv -__ZN3KJS13ArrayInstance4markEv -__ZN3KJS15JSWrapperObject4markEv -__ZN3KJS13ActivationImp4markEv -__ZN3KJS13ActivationImp12markChildrenEv -__ZN3KJS14NativeErrorImp4markEv -__ZN3KJS9Arguments4markEv -__ZN3KJS9Collector20markProtectedObjectsEv -__ZN3KJS9Collector5sweepILNS0_8HeapTypeE0EEEmb -__ZN3KJS11PropertyMapD1Ev -__ZN3KJS11FunctionImpD0Ev -__ZN3KJS9StringImpD0Ev -__ZN3KJS9RegExpImpD0Ev -__ZN3KJS13ArrayInstanceD0Ev -__ZN3KJS9ArgumentsD0Ev -__ZN3KJS9Collector5sweepILNS0_8HeapTypeE1EEEmb -__ZN3KJS14AddStringsNode8evaluateEPNS_9ExecStateE -__ZN3KJS17AddStringLeftNode8evaluateEPNS_9ExecStateE -__ZNK3KJS9StringImp11toPrimitiveEPNS_9ExecStateENS_6JSTypeE -__ZN3KJS7AddNode8evaluateEPNS_9ExecStateE -__ZN3KJS21stringProtoFuncCharAtEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS26stringProtoFuncToUpperCaseEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS24stringProtoFuncSubstringEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS26stringProtoFuncToLowerCaseEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZNK3KJS7UString8toUInt32EPb -__ZN3KJS22ReadModifyLocalVarNode8evaluateEPNS_9ExecStateE -__ZN3KJS19PostIncLocalVarNode8evaluateEPNS_9ExecStateE -__ZN3KJS17PreDecResolveNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS18PreDecLocalVarNode8evaluateEPNS_9ExecStateE -__ZN3KJS8MultNode16evaluateToNumberEPNS_9ExecStateE -__ZNK3KJS9NumberImp4typeEv -__ZN3KJS20dateProtoFuncSetTimeEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS7SubNode16evaluateToNumberEPNS_9ExecStateE -__ZNK3KJS9StringImp8toNumberEPNS_9ExecStateE -__ZN3KJS18globalFuncParseIntEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZNK3KJS7JSValue15toInt32SlowCaseEPNS_9ExecStateERb -__ZN3KJS24dateProtoFuncToGMTStringEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS10formatTimeERKNS_17GregorianDateTimeEb -__ZNK3KJS15RegExpObjectImp19implementsConstructEv -__ZN3KJS15RegExpObjectImp9constructEPNS_9ExecStateERKNS_4ListE -__ZN3KJS19regExpProtoFuncExecEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS14StringInstance18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE -__ZN3KJS35stringInstanceNumericPropertyGetterEPNS_9ExecStateEPNS_8JSObjectEjRKNS_12PropertySlotE -__ZN3KJS23FunctionCallResolveNode17evaluateToBooleanEPNS_9ExecStateE -__ZN3KJS15globalFuncIsNaNEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS20dateProtoFuncSetYearEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS21gregorianDateTimeToMSERKNS_17GregorianDateTimeEdb -__ZN3KJS15dateToDayInYearEiii -__ZN3KJS21ReadModifyBracketNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZNK3KJS15ObjectObjectImp19implementsConstructEv -__ZN3KJS21ReadModifyBracketNode8evaluateEPNS_9ExecStateE -__ZNK3KJS9ExecState12hadExceptionEv -__ZNK3KJS7JSValue8toObjectEPNS_9ExecStateE -__ZNK3KJS7JSValue8toStringEPNS_9ExecStateE -__ZN3KJS7UStringD1Ev -__ZN3KJS8JSObject15getPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE -__ZNK3KJS12PropertySlot8getValueEPNS_9ExecStateEPNS_8JSObjectERKNS_10IdentifierE -__ZNK3WTF6RefPtrIN3KJS14ExpressionNodeEE3getEv -__ZN3KJS3addEPNS_9ExecStateEPNS_7JSValueES3_ -__ZN3KJS10IdentifierD1Ev -__ZNK3KJS8JSObject3getEPNS_9ExecStateERKNS_10IdentifierE -__ZN3KJS20arrayProtoFuncConcatEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS14ExpressionNode17evaluateToBooleanEPNS_9ExecStateE -__ZN3KJS9BreakNode7executeEPNS_9ExecStateE -__ZN3KJS18arrayProtoFuncJoinEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS11JSImmediate8toObjectEPKNS_7JSValueEPNS_9ExecStateE -__ZN3KJS10throwErrorEPNS_9ExecStateENS_9ErrorTypeEPKc -__ZN3KJS5Error6createEPNS_9ExecStateENS_9ErrorTypeERKNS_7UStringEiiS6_ -__ZN3KJS14NativeErrorImp9constructEPNS_9ExecStateERKNS_4ListE -__ZNK3KJS6JSCell17getTruncatedInt32ERi -__ZN3KJS15StringObjectImp14callAsFunctionEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS9Collector15recordExtraCostEm -__ZN3KJS22objectProtoFuncValueOfEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS23objectProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZNK3KJS8JSObject9classNameEv -__ZN3KJS14PostDecDotNode8evaluateEPNS_9ExecStateE -__ZN3KJS9CommaNodeD1Ev -__ZN3KJS28globalFuncDecodeURIComponentEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS6decodeEPNS_9ExecStateERKNS_4ListEPKcb -__ZN3KJS19BracketAccessorNode16evaluateToNumberEPNS_9ExecStateE -__ZN3KJS15TypeOfValueNodeD1Ev -__ZN3KJS17PrototypeFunctionD0Ev -__ZN3KJS13ErrorInstanceD0Ev -__ZN3KJS18mathProtoFuncRoundEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS23FunctionCallResolveNode16evaluateToNumberEPNS_9ExecStateE -__ZN3KJS13GreaterEqNodeD1Ev -__ZN3KJS7ModNodeD1Ev -__ZN3KJS24LocalVarFunctionCallNode17evaluateToBooleanEPNS_9ExecStateE -__ZN3KJS4List15expandAndAppendEPNS_7JSValueE -__ZN3WTF6VectorIPN3KJS7JSValueELm8EE15reserveCapacityEm -__ZN3KJS10SwitchNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS13CaseBlockNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS14ClauseListNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS14CaseClauseNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS10SwitchNode7executeEPNS_9ExecStateE -__ZN3KJS13CaseBlockNode12executeBlockEPNS_9ExecStateEPNS_7JSValueE -__ZN3KJS18NotStrictEqualNode17evaluateToBooleanEPNS_9ExecStateE -__Z23_NPN_CreateScriptObjectP4_NPPPN3KJS8JSObjectEN3WTF10PassRefPtrINS1_8Bindings10RootObjectEEE -__NPN_CreateObject -__Z10jsAllocateP4_NPPP7NPClass -__NPN_RetainObject -__NPN_Evaluate -__ZNK3KJS8Bindings10RootObject12globalObjectEv -__ZN3KJS8Bindings22convertNPStringToUTF16EPK9_NPStringPPtPj -__ZN3KJS8Bindings36convertUTF8ToUTF16WithLatin1FallbackEPKciPPtPj -__ZN3WTF7Unicode18convertUTF8ToUTF16EPPKcS2_PPtS4_b -__ZN3KJS11Interpreter8evaluateEPNS_9ExecStateERKNS_7UStringEiS5_PNS_7JSValueE -__ZN3KJS8Bindings23convertValueToNPVariantEPNS_9ExecStateEPNS_7JSValueEP10_NPVariant -__ZN3KJS11JSImmediate4typeEPKNS_7JSValueE -__NPN_GetStringIdentifier -__ZN3KJS8Bindings26identifierFromNPIdentifierEPKc -__NPN_Invoke -__ZN3KJS8Bindings14findRootObjectEPNS_14JSGlobalObjectE -__NPN_ReleaseVariantValue -__ZNK3KJS7UString10UTF8StringEb +__ZN3WTF14FastMallocZone9forceLockEP14_malloc_zone_t +__ZN3WTF14FastMallocZone11forceUnlockEP14_malloc_zone_t +__ZN3JSC7UStringC1EPKti +__ZN3JSC5Lexer7record8Ei +__ZN3JSC16FunctionBodyNode13finishParsingERKNS_10SourceCodeEPNS_13ParameterNodeE +__ZN3WTF6VectorINS_6RefPtrIN3JSC12FuncDeclNodeEEELm0EE15reserveCapacityEm +__ZN3JSC10Identifier6removeEPNS_7UString3RepE +__ZN3WTF6VectorINS_6RefPtrIN3JSC12FuncDeclNodeEEELm0EEaSERKS5_ +__ZN3JSC8JSObject12removeDirectERKNS_10IdentifierE +__ZN3JSC9Structure31removePropertyWithoutTransitionERKNS_10IdentifierE +__ZN3JSC9Structure6removeERKNS_10IdentifierE +__ZN3JSC17BytecodeGenerator12addGlobalVarERKNS_10IdentifierEbRPNS_10RegisterIDE +__ZN3JSC17BytecodeGenerator15emitNewFunctionEPNS_10RegisterIDEPNS_12FuncDeclNodeE +__ZN3JSC9CodeBlock25createRareDataIfNecessaryEv +__ZN3JSC12FuncDeclNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZN3WTF6VectorIN3JSC15SimpleJumpTableELm0EE14shrinkCapacityEm +__ZN3WTF6VectorIN3JSC15StringJumpTableELm0EE14shrinkCapacityEm +__ZN3JSC3JIT11emitCTICallEPFvPvzE +__ZN3JSC11Interpreter15cti_op_new_funcEPvz +__ZN3JSC12FuncDeclNode12makeFunctionEPNS_9ExecStateEPNS_14ScopeChainNodeE +__ZN3JSC11Interpreter10cti_op_endEPvz +__ZN3JSC12FuncDeclNode12releaseNodesERNS_12NodeReleaserE +__ZN3JSC12NodeReleaser21adoptFunctionBodyNodeERN3WTF6RefPtrINS_16FunctionBodyNodeEEE +__ZN3JSC8JSObject4markEv +__ZN3JSC14JSGlobalObject4markEv +__ZN3JSC7JSArray4markEv +__ZN3JSC15JSWrapperObject4markEv +__ZN3JSC18GlobalEvalFunction4markEv +__ZNK3JSC10NumberNode8isNumberEv +__ZN3JSC5Lexer10scanRegExpEv +__ZN3JSC7UStringC2ERKN3WTF6VectorItLm0EEE +__ZL26appendToVarDeclarationListPvRPN3JSC20ParserRefCountedDataIN3WTF6VectorISt4pairINS0_10IdentifierEjELm0EEEEERKS5_j +__ZN3WTF6VectorISt4pairIN3JSC10IdentifierEjELm0EE14expandCapacityEmPKS4_ +__ZN3WTF6VectorISt4pairIN3JSC10IdentifierEjELm0EE15reserveCapacityEm +__ZL20makeVarStatementNodePvPN3JSC14ExpressionNodeE +__ZL14makeAssignNodePvPN3JSC14ExpressionNodeENS0_8OperatorES2_bbiii +__Z21mergeDeclarationListsIPN3JSC20ParserRefCountedDataIN3WTF6VectorINS2_6RefPtrINS0_12FuncDeclNodeEEELm0EEEEEET_SA_SA_ +__ZN3JSC20ParserRefCountedDataIN3WTF6VectorISt4pairINS_10IdentifierEjELm0EEEED1Ev +__ZN3WTF6VectorIPNS0_IN3JSC10IdentifierELm64EEELm32EE14expandCapacityEm +__ZNK3JSC18EmptyStatementNode16isEmptyStatementEv +__ZNK3JSC14ExpressionNode10isLocationEv +__ZL11makeAddNodePvPN3JSC14ExpressionNodeES2_b +__ZNK3JSC14ExpressionNode8isNumberEv +__ZN3JSC16PropertyListNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZN3JSC17BytecodeGenerator11emitPutByIdEPNS_10RegisterIDERKNS_10IdentifierES2_ +__ZN3JSC11UnaryOpNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZN3JSC13LogicalOpNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZN3JSC17BytecodeGenerator8newLabelEv +__ZN3JSC17BytecodeGenerator15emitJumpIfFalseEPNS_10RegisterIDEPNS_5LabelE +__ZNK3JSC14LogicalNotNode8opcodeIDEv +__ZN3JSC17BytecodeGenerator9emitLabelEPNS_5LabelE +__ZN3WTF6VectorIjLm0EE15reserveCapacityEm +__ZN3JSC19ReverseBinaryOpNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZNK3JSC10NumberNode6isPureERNS_17BytecodeGeneratorE +__ZN3JSC17BytecodeGenerator11emitResolveEPNS_10RegisterIDERKNS_10IdentifierE +__ZN3WTF6VectorIN3JSC17GlobalResolveInfoELm0EE14expandCapacityEm +__ZNK3JSC11GreaterNode8opcodeIDEv +__ZN3JSC17BytecodeGenerator12emitBinaryOpENS_8OpcodeIDEPNS_10RegisterIDES3_S3_NS_12OperandTypesE +__ZN3JSC9EqualNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZNK3JSC14ExpressionNode6isNullEv +__ZN3JSC17BytecodeGenerator14emitEqualityOpENS_8OpcodeIDEPNS_10RegisterIDES3_S3_ +__ZN3JSC10RegExpNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZN3JSC6RegExp6createEPNS_12JSGlobalDataERKNS_7UStringES5_ +__ZN3JSC4WREC9Generator13compileRegExpEPNS_12JSGlobalDataERKNS_7UStringEPjPPKcRN3WTF6RefPtrINS_14ExecutablePoolEEEbb +__ZN3JSC4WREC9Generator13generateEnterEv +__ZN3JSC4WREC9Generator17generateSaveIndexEv +__ZN3JSC4WREC6Parser16parseDisjunctionERNS_14MacroAssembler8JumpListE +__ZN3JSC4WREC6Parser16parseAlternativeERNS_14MacroAssembler8JumpListE +__ZN3JSC4WREC9Generator32generatePatternCharacterSequenceERNS_14MacroAssembler8JumpListEPim +__ZN3JSC4WREC9Generator28generatePatternCharacterPairERNS_14MacroAssembler8JumpListEii +__ZN3WTF6VectorIN3JSC14MacroAssembler4JumpELm16EE6appendIS3_EEvRKT_ +__ZN3JSC12X86Assembler7cmpl_irEiNS_3X8610RegisterIDE +__ZN3JSC4WREC9Generator24generatePatternCharacterERNS_14MacroAssembler8JumpListEi +__ZN3JSC4WREC9Generator21generateLoadCharacterERNS_14MacroAssembler8JumpListE +__ZN3JSC4WREC14CharacterClass7newlineEv +__ZN3JSC4WREC6Parser29parseCharacterClassQuantifierERNS_14MacroAssembler8JumpListERKNS0_14CharacterClassEb +__ZN3JSC4WREC6Parser17consumeQuantifierEv +__ZN3JSC4WREC9Generator24generateGreedyQuantifierERNS_14MacroAssembler8JumpListERNS0_19GenerateAtomFunctorEjj +__ZN3JSC4WREC29GenerateCharacterClassFunctor12generateAtomEPNS0_9GeneratorERNS_14MacroAssembler8JumpListE +__ZN3JSC4WREC9Generator22generateCharacterClassERNS_14MacroAssembler8JumpListERKNS0_14CharacterClassEb +__ZN3JSC4WREC9Generator30generateCharacterClassInvertedERNS_14MacroAssembler8JumpListERKNS0_14CharacterClassE +__ZN3JSC4WREC29GenerateCharacterClassFunctor9backtrackEPNS0_9GeneratorE +__ZN3JSC4WREC9Generator18generateBacktrack1Ev +__ZN3JSC15AssemblerBuffer4growEv +__ZN3JSC12X86Assembler7addl_irEiNS_3X8610RegisterIDE +__ZN3JSC4WREC9Generator21generateReturnSuccessEv +__ZN3JSC4WREC9Generator22generateIncrementIndexEPNS_14MacroAssembler4JumpE +__ZN3JSC4WREC9Generator27generateJumpIfNotEndOfInputENS_14MacroAssembler5LabelE +__ZN3JSC4WREC9Generator21generateReturnFailureEv +__ZN3JSC17BytecodeGenerator13emitNewRegExpEPNS_10RegisterIDEPNS_6RegExpE +__ZN3JSC12BinaryOpNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZNK3JSC18NotStrictEqualNode8opcodeIDEv +__ZNK3JSC14ExpressionNode6isPureERNS_17BytecodeGeneratorE +__ZN3JSC4WREC9Generator20generateAssertionBOLERNS_14MacroAssembler8JumpListE +__ZN3JSC4WREC6Parser13consumeEscapeEb +__ZN3WTF6VectorIiLm8EE14expandCapacityEm +__ZN3JSC4WREC6Parser16parseParenthesesERNS_14MacroAssembler8JumpListE +__Z15jsRegExpCompilePKti24JSRegExpIgnoreCaseOption23JSRegExpMultilineOptionPjPPKc +__ZL30calculateCompiledPatternLengthPKti24JSRegExpIgnoreCaseOptionR11CompileDataR9ErrorCode +__ZL11checkEscapePPKtS0_P9ErrorCodeib +__ZL13compileBranchiPiPPhPPKtS3_P9ErrorCodeS_S_R11CompileData +__ZN3JSC4WREC14CharacterClass6spacesEv +__ZN3JSC4WREC6Parser23parseNonCharacterEscapeERNS_14MacroAssembler8JumpListERKNS0_6EscapeE +__ZN3JSC12X86Assembler23X86InstructionFormatter9twoByteOpENS0_15TwoByteOpcodeIDE +__ZN3JSC4WREC9Generator35generateCharacterClassInvertedRangeERNS_14MacroAssembler8JumpListES4_PKNS0_14CharacterRangeEjPjPKtj +__ZN3JSC4WREC9Generator20terminateAlternativeERNS_14MacroAssembler8JumpListES4_ +__ZN3JSC4WREC6Parser19parseCharacterClassERNS_14MacroAssembler8JumpListE +__ZN3JSC4WREC14CharacterClass8wordcharEv +__ZN3JSC4WREC25CharacterClassConstructor6appendERKNS0_14CharacterClassE +__ZN3JSC4WREC25CharacterClassConstructor5flushEv +__ZN3JSC4WREC25CharacterClassConstructor9addSortedERN3WTF6VectorItLm0EEEt +__ZN3WTF6VectorItLm0EE14expandCapacityEm +__ZN3JSC4WREC25CharacterClassConstructor14addSortedRangeERN3WTF6VectorINS0_14CharacterRangeELm0EEEtt +__ZN3WTF6VectorIN3JSC4WREC14CharacterRangeELm0EE14expandCapacityEm +__ZN3JSC4WREC25CharacterClassConstructor3putEt +__ZN3JSC4WREC9Generator20terminateDisjunctionERNS_14MacroAssembler8JumpListE +__ZN3JSC11NewExprNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZN3JSC17BytecodeGenerator13emitConstructEPNS_10RegisterIDES2_PNS_13ArgumentsNodeEjjj +__ZN3WTF6VectorIN3JSC20GetByIdExceptionInfoELm0EE14expandCapacityEm +__ZN3JSC16VarStatementNodeD1Ev +__ZN3JSC16VarStatementNode12releaseNodesERNS_12NodeReleaserE +__ZN3JSC17AssignResolveNode12releaseNodesERNS_12NodeReleaserE +__ZN3JSC17ObjectLiteralNode12releaseNodesERNS_12NodeReleaserE +__ZN3JSC16PropertyListNode12releaseNodesERNS_12NodeReleaserE +__ZN3JSC12PropertyNode12releaseNodesERNS_12NodeReleaserE +__ZN3JSC11UnaryOpNode12releaseNodesERNS_12NodeReleaserE +__ZN3JSC13LogicalOpNode12releaseNodesERNS_12NodeReleaserE +__ZN3JSC12BinaryOpNode12releaseNodesERNS_12NodeReleaserE +__ZN3JSC17AssignResolveNodeD1Ev +__ZN3JSC17ObjectLiteralNodeD1Ev +__ZN3JSC16PropertyListNodeD1Ev +__ZN3JSC12PropertyNodeD1Ev +__ZN3JSC14LogicalNotNodeD1Ev +__ZN3JSC10RegExpNodeD1Ev +__ZN3JSC13LogicalOpNodeD1Ev +__ZN3JSC9EqualNodeD1Ev +__ZN3JSC18NotStrictEqualNodeD1Ev +__ZN3JSC6IfNodeD1Ev +__ZN3JSC6IfNode12releaseNodesERNS_12NodeReleaserE +__ZN3JSC13AssignDotNode12releaseNodesERNS_12NodeReleaserE +__ZN3JSC8WithNodeD1Ev +__ZN3JSC8WithNode12releaseNodesERNS_12NodeReleaserE +__ZN3JSC21FunctionCallValueNode12releaseNodesERNS_12NodeReleaserE +__ZN3JSC21FunctionCallValueNodeD1Ev +__ZN3JSC9ArrayNode12releaseNodesERNS_12NodeReleaserE +__ZN3JSC9ArrayNodeD1Ev +__ZN3JSC11ElementNode12releaseNodesERNS_12NodeReleaserE +__ZN3JSC10IfElseNodeD1Ev +__ZN3JSC10IfElseNode12releaseNodesERNS_12NodeReleaserE +__ZN3JSC7AddNodeD1Ev +__ZN3JSC11NewExprNode12releaseNodesERNS_12NodeReleaserE +__ZN3JSC11NewExprNodeD1Ev +__ZN3JSC3JIT21compilePutByIdHotPathEiPNS_10IdentifierEij +__ZN3WTF6VectorIN3JSC9JumpTableELm0EE14expandCapacityEm +__ZN3WTF6VectorIN3JSC13SlowCaseEntryELm0EE6appendIS2_EEvRKT_ +__ZN3JSC12X86Assembler23X86InstructionFormatter9oneByteOpENS0_15OneByteOpcodeIDEiNS_3X8610RegisterIDES4_ii +__ZN3JSC3JIT11emitCTICallEPFPNS_23JSValueEncodedAsPointerEPvzE +__ZN3JSC3JIT17compileOpStrictEqEPNS_11InstructionENS0_21CompileOpStrictEqTypeE +__ZN3JSC3JIT23compileFastArith_op_addEPNS_11InstructionE +__ZN3JSC3JIT22compilePutByIdSlowCaseEiPNS_10IdentifierEiRPNS_13SlowCaseEntryEj +__ZN3JSC3JIT27compileOpConstructSetupArgsEPNS_11InstructionE +__ZN3JSC3JIT11emitCTICallEPFPNS_8JSObjectEPvzE +__ZN3JSC12SmallStrings27createSingleCharacterStringEPNS_12JSGlobalDataEh +__ZN3JSC11Interpreter17cti_op_new_objectEPvz +__ZN3JSC20constructEmptyObjectEPNS_9ExecStateE +__ZN3JSC11Interpreter16cti_op_put_by_idEPvz +__ZN3JSC8JSObject3putEPNS_9ExecStateERKNS_10IdentifierENS_10JSValuePtrERNS_15PutPropertySlotE +__ZN3JSC11Interpreter12cti_op_jtrueEPvz +__ZN3JSC11Interpreter10cti_op_notEPvz +__ZN3WTF7HashMapISt4pairINS_6RefPtrIN3JSC7UString3RepEEEjEPNS3_9StructureENS3_28StructureTransitionTableHashENS3_34StructureTransitionTableHashTraitsENS_10HashTraitsIS9_EEE3addERKS7_RKS9_ +__ZN3WTF9HashTableISt4pairINS_6RefPtrIN3JSC7UString3RepEEEjES1_IS7_PNS3_9StructureEENS_18PairFirstExtractorISA_EENS3_28StructureTransitionTableHashENS_14PairHashTraitsINS3_34StructureTransitionTableHashTraitsENS_10HashTraitsIS9_EEEESF_E6rehashEi +__ZN3JSC11Interpreter21cti_op_resolve_globalEPvz +__ZN3JSC8JSString18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE +__ZN3JSC15StringPrototype18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE +__ZN3JSC12StringObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE +__ZN3JSCL22stringProtoFuncIndexOfEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZNK3JSC8JSString12toThisStringEPNS_9ExecStateE +__ZNK3JSC10JSValuePtr9toIntegerEPNS_9ExecStateE +__ZN3JSC11JSImmediate12nonInlineNaNEv +__ZNK3JSC7UString4findERKS0_i +__ZN3JSC11Interpreter11cti_op_lessEPvz +__ZN3JSC11Interpreter17cti_op_new_regexpEPvz +__ZN3JSC12RegExpObjectC1EN3WTF10PassRefPtrINS_9StructureEEENS2_INS_6RegExpEEE +__ZN3JSCL20stringProtoFuncMatchEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZNK3JSC6JSCell8isObjectEPKNS_9ClassInfoE +__ZNK3JSC12RegExpObject9classInfoEv +__ZN3JSC17RegExpConstructor12performMatchEPNS_6RegExpERKNS_7UStringEiRiS6_PPi +__ZN3JSC6RegExp5matchERKNS_7UStringEiPN3WTF11OwnArrayPtrIiEE +__ZNK3JSC8JSObject9toBooleanEPNS_9ExecStateE +__ZNK3JSC7UString8toUInt32EPbb +__ZNK3JSC7UString8toDoubleEbb +__ZN3WTF6VectorIcLm32EE6resizeEm +__ZN3JSC11Interpreter16cti_op_nstricteqEPvz +__ZN3JSC10JSValuePtr19strictEqualSlowCaseES0_S0_ +__ZN3JSC11Interpreter19cti_op_new_func_expEPvz +__ZN3JSC12FuncExprNode12makeFunctionEPNS_9ExecStateEPNS_14ScopeChainNodeE +__ZNK3JSC19BracketAccessorNode10isLocationEv +__ZNK3JSC19BracketAccessorNode21isBracketAccessorNodeEv +__ZN3JSC9ForInNodeC2EPNS_12JSGlobalDataERKNS_10IdentifierEPNS_14ExpressionNodeES7_PNS_13StatementNodeEiii +__ZN3JSC19BracketAccessorNodeD1Ev +__ZN3JSC19BracketAccessorNode12releaseNodesERNS_12NodeReleaserE +__ZNK3JSC9ForInNode6isLoopEv +__ZN3JSC9ForInNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZN3JSCL20dateProtoFuncSetTimeEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSC20EvalFunctionCallNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZN3JSC17BytecodeGenerator19emitResolveWithBaseEPNS_10RegisterIDES2_RKNS_10IdentifierE +__ZN3JSC20EvalFunctionCallNodeD1Ev +__ZN3JSC20EvalFunctionCallNode12releaseNodesERNS_12NodeReleaserE +__ZN3JSC3JIT26compileOpCallEvalSetupArgsEPNS_11InstructionE +__ZN3JSC11Interpreter24cti_op_resolve_with_baseEPvz +__ZN3JSC11Interpreter16cti_op_call_evalEPvz +__ZN3JSC11Interpreter8callEvalEPNS_9ExecStateEPNS_12RegisterFileEPNS_8RegisterEiiRNS_10JSValuePtrE +__ZNK3WTF7HashMapINS_6RefPtrIN3JSC7UString3RepEEENS1_INS2_8EvalNodeEEENS_7StrHashIS5_EENS_10HashTraitsIS5_EENSA_IS7_EEE3getEPS4_ +__ZN3JSC7UString3Rep11computeHashEPKti +__ZN3JSC6Parser5parseINS_8EvalNodeEEEN3WTF10PassRefPtrIT_EEPNS_9ExecStateEPNS_8DebuggerERKNS_10SourceCodeEPiPNS_7UStringE +__ZN3WTF9HashTableINS_6RefPtrIN3JSC7UString3RepEEESt4pairIS5_NS1_INS2_8EvalNodeEEEENS_18PairFirstExtractorIS9_EENS_7StrHashIS5_EENS_14PairHashTraitsINS_10HashTraitsIS5_EENSF_IS8_EEEESG_E6rehashEi +__ZN3JSC9ExecState9thisValueEv +__ZN3JSC11Interpreter7executeEPNS_8EvalNodeEPNS_9ExecStateEPNS_8JSObjectEiPNS_14ScopeChainNodeEPNS_10JSValuePtrE +__ZN3JSC8EvalNode16generateBytecodeEPNS_14ScopeChainNodeE +__ZN3JSC17BytecodeGeneratorC2EPNS_8EvalNodeEPKNS_8DebuggerERKNS_10ScopeChainEPN3WTF7HashMapINS9_6RefPtrINS_7UString3RepEEENS_16SymbolTableEntryENS_17IdentifierRepHashENS9_10HashTraitsISE_EENS_26SymbolTableIndexHashTraitsEEEPNS_13EvalCodeBlockE +__ZN3JSC8EvalNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZN3JSC18globalFuncParseIntEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSCL24dateProtoFuncToGMTStringEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSC10formatTimeERKNS_17GregorianDateTimeEb +__ZN3JSC9BreakNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZN3JSC17BytecodeGenerator11breakTargetERKNS_10IdentifierE +__ZN3JSC9BreakNodeD1Ev +__ZN3JSC8JSString18getPrimitiveNumberEPNS_9ExecStateERdRNS_10JSValuePtrE +__ZNK3JSC8JSString8toNumberEPNS_9ExecStateE +__ZL18makeRightShiftNodePvPN3JSC14ExpressionNodeES2_b +__ZN3JSC4WREC14CharacterClass6digitsEv +__ZNK3JSC14RightShiftNode8opcodeIDEv +__ZN3JSC14RightShiftNodeD1Ev +__ZN3JSC3JIT26compileFastArith_op_rshiftEjjj +__ZN3JSC3JIT30compileFastArithSlow_op_rshiftEjjjRPNS_13SlowCaseEntryE +__ZN3JSCL20dateProtoFuncSetYearEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSC21gregorianDateTimeToMSERKNS_17GregorianDateTimeEdb +__ZN3JSCL15dateToDayInYearEiii +__ZN3JSC8EvalNode4markEv +__ZN3JSC19JSStaticScopeObjectD0Ev +__ZN3JSC18PostfixBracketNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZN3JSC18PostfixBracketNodeD1Ev +__ZN3JSC18PostfixBracketNode12releaseNodesERNS_12NodeReleaserE +__ZN3JSC9ForInNodeC2EPNS_12JSGlobalDataEPNS_14ExpressionNodeES4_PNS_13StatementNodeE +__ZN3JSC21ReadModifyBracketNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZN3JSC21ReadModifyBracketNodeD1Ev +__ZN3JSC21ReadModifyBracketNode12releaseNodesERNS_12NodeReleaserE +__ZN3JSCL20arrayProtoFuncConcatEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSC17RegExpConstructor16getConstructDataERNS_13ConstructDataE +__ZN3JSCL30constructWithRegExpConstructorEPNS_9ExecStateEPNS_8JSObjectERKNS_7ArgListE +__ZN3JSC15constructRegExpEPNS_9ExecStateERKNS_7ArgListE +__ZN3JSC23objectProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZNK3JSC8JSObject9classNameEv +__ZN3JSC18RegExpMatchesArray18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE +__ZN3JSCL20stringProtoFuncSliceEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZNK3JSC8NullNode6isNullEv +__ZN3JSC17StringConstructor11getCallDataERNS_8CallDataE +__ZN3JSCL21callStringConstructorEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZNK3JSC12StringObject8toStringEPNS_9ExecStateE +__ZN3JSCL23stringProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSC11Interpreter28cti_op_get_by_id_string_failEPvz +__ZN3JSCL19regExpProtoFuncExecEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSC11Interpreter16cti_op_is_numberEPvz +__ZNK3JSC12StringObject9classInfoEv +__ZN3JSC11Interpreter16cti_op_is_objectEPvz +__ZN3JSC3JIT30privateCompileGetByIdChainListEPNS_17StructureStubInfoEPNS_30PolymorphicAccessStructureListEiPNS_9StructureEPNS_14StructureChainEmmPNS_9ExecStateE +__ZN3JSCL23numberProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSC10Identifier5equalEPKNS_7UString3RepEPKc +__ZNK3JSC6JSCell17getTruncatedInt32ERi +__ZN3JSC15toInt32SlowCaseEdRb +__ZNK3JSC12JSNumberCell9toBooleanEPNS_9ExecStateE +__ZN3JSC9Structure24removePropertyTransitionEPS0_RKNS_10IdentifierERm +__ZN3JSC11Interpreter10cti_op_subEPvz +__ZN3JSC28globalFuncEncodeURIComponentEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSCL6encodeEPNS_9ExecStateERKNS_7ArgListEPKc +__ZNK3JSC7UString10UTF8StringEb __ZN3WTF7Unicode18convertUTF16ToUTF8EPPKtS2_PPcS4_b -__Z35NPN_InitializeVariantWithStringCopyP10_NPVariantPK9_NPString -__ZN3KJS7CStringD1Ev -__NPN_ReleaseObject -__Z12jsDeallocateP8NPObject -__ZN3KJS8Bindings10RootObject11gcUnprotectEPNS_8JSObjectE -_pow5mult -_quorem -_diff -__ZN3WTF6VectorIPN3KJS12FuncDeclNodeELm16EE14expandCapacityEmPKS3_ -__ZN3WTF6VectorIPN3KJS12FuncDeclNodeELm16EE14expandCapacityEm -__ZN3WTF6VectorIPN3KJS12FuncDeclNodeELm16EE15reserveCapacityEm -__ZN3KJS10NumberNode8setValueEd -__ZN3KJS11ResolveNode16evaluateToNumberEPNS_9ExecStateE -__ZN3KJS21dateProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS24dateProtoFuncGetFullYearEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS12NotEqualNode8evaluateEPNS_9ExecStateE -__ZN3KJS14InstanceOfNode17evaluateToBooleanEPNS_9ExecStateE -__ZN3KJS17PreIncResolveNode8evaluateEPNS_9ExecStateE -__ZNK3KJS9NumberImp9toBooleanEPNS_9ExecStateE -__ZN3KJS10LessEqNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS29objectProtoFuncHasOwnPropertyEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS10LessEqNode17evaluateToBooleanEPNS_9ExecStateE -__ZN3KJS13UnaryPlusNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS17DeleteBracketNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS17DeleteBracketNode8evaluateEPNS_9ExecStateE -__ZN3KJS20arrayProtoFuncSpliceEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS17staticValueGetterINS_13MathObjectImpEEEPNS_7JSValueEPNS_9ExecStateEPNS_8JSObjectERKNS_10IdentifierERKNS_12PropertySlotE -__ZNK3KJS13MathObjectImp16getValuePropertyEPNS_9ExecStateEi -__NPN_DeallocateObject -__ZN3KJS14PostIncDotNodeD1Ev -__ZN3KJS22ReadModifyLocalVarNodeD1Ev -__ZN3KJS10LessEqNodeD1Ev -__ZN3KJS18PostDecResolveNodeD1Ev -__ZN3KJS17DeleteBracketNodeD1Ev -__ZN3KJS18PostIncResolveNodeD1Ev -__ZN3KJS14InstanceOfNodeD1Ev -__ZN3KJS10NegateNodeD1Ev -__ZN3KJS17PreDecResolveNodeD1Ev -__ZN3KJS21ReadModifyBracketNodeD1Ev -__ZN3KJS10BitAndNodeD1Ev -__ZN3KJS9BitOrNodeD1Ev -__ZN3KJS14RightShiftNodeD1Ev -__ZN3KJS13LeftShiftNodeD1Ev -__ZN3KJS13UnaryPlusNodeD1Ev -__ZN3KJS13MathObjectImpD0Ev -__ZN3KJS14NativeErrorImpD0Ev -__ZN3KJS14ErrorObjectImpD0Ev -__ZN3KJS15RegExpObjectImpD0Ev -__ZN3KJS17DateObjectFuncImpD0Ev -__ZN3KJS13DateObjectImpD0Ev -__ZN3KJS15NumberObjectImpD0Ev -__ZN3KJS16BooleanObjectImpD0Ev -__ZN3KJS19StringObjectFuncImpD0Ev -__ZN3KJS15StringObjectImpD0Ev -__ZN3KJS14ArrayObjectImpD0Ev -__ZN3KJS17FunctionObjectImpD0Ev -__ZN3KJS15ObjectObjectImpD0Ev -__ZN3KJS20NativeErrorPrototypeD0Ev -__ZN3KJS15RegExpPrototypeD0Ev -__ZN3KJS15NumberPrototypeD0Ev -__ZN3KJS16BooleanPrototypeD0Ev -__ZN3KJS15StringPrototypeD0Ev -__ZN3KJS15ObjectPrototypeD0Ev -__ZN3KJS17FunctionPrototypeD0Ev -__ZN3KJS13PreIncDotNodeD1Ev -__ZN3KJS17staticValueGetterINS_15RegExpObjectImpEEEPNS_7JSValueEPNS_9ExecStateEPNS_8JSObjectERKNS_10IdentifierERKNS_12PropertySlotE -__ZNK3KJS15RegExpObjectImp16getValuePropertyEPNS_9ExecStateEi -__ZNK3KJS15RegExpObjectImp10getBackrefEj -__ZN3KJS16mathProtoFuncMaxEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS17staticValueGetterINS_15NumberObjectImpEEEPNS_7JSValueEPNS_9ExecStateEPNS_8JSObjectERKNS_10IdentifierERKNS_12PropertySlotE -__ZNK3KJS15NumberObjectImp16getValuePropertyEPNS_9ExecStateEi -__ZN3KJS10NegateNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS10NegateNode8evaluateEPNS_9ExecStateE -__ZN3KJS25stringProtoFuncCharCodeAtEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS21arrayProtoFuncUnShiftEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS10LessEqNode8evaluateEPNS_9ExecStateE -__ZN3KJS8JSObject15getPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE -__ZNK3KJS12PropertySlot8getValueEPNS_9ExecStateEPNS_8JSObjectEj -__ZN3KJS16mathProtoFuncMinEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS10Identifier5equalEPKNS_7UString3RepEPKc -__ZN3KJS11addSlowCaseEPNS_9ExecStateEPNS_7JSValueES3_ -__ZN3KJS8LessNode8evaluateEPNS_9ExecStateE -__ZN3KJS7DivNode16evaluateToNumberEPNS_9ExecStateE -__ZN3KJS10NegateNode16evaluateToNumberEPNS_9ExecStateE -__ZN3KJS7AddNode16evaluateToNumberEPNS_9ExecStateE -__ZN3KJS16mathProtoFuncSinEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS16mathProtoFuncLogEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS16mathProtoFuncAbsEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3WTF6VectorIPN3KJS9ExecStateELm16EE14expandCapacityEm -__ZN3WTF6VectorIPN3KJS9ExecStateELm16EE15reserveCapacityEm -__ZN3KJS17arrayProtoFuncPopEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS21stringProtoFuncSubstrEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS28globalFuncEncodeURIComponentEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS6encodeEPNS_9ExecStateERKNS_4ListEPKc -__ZN3KJS17PrefixBracketNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS17PreIncBracketNode8evaluateEPNS_9ExecStateE -__ZN3KJS16mathProtoFuncExpEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS17mathProtoFuncATanEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS17mathProtoFuncCeilEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS14AddNumbersNode8evaluateEPNS_9ExecStateE -__ZN3KJS18arrayProtoFuncSortEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS13ArrayInstance4sortEPNS_9ExecStateEPNS_8JSObjectE -__ZN3KJS13ArrayInstance17compactForSortingEv -__ZN3KJS34compareWithCompareFunctionForQSortEPKvS1_ -__ZN3KJS13ArrayInstance4sortEPNS_9ExecStateE -__ZN3KJS16mathProtoFuncPowEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS15NumberObjectImp9constructEPNS_9ExecStateERKNS_4ListE -__ZN3KJS23numberProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZNK3KJS9NumberImp8toObjectEPNS_9ExecStateE -__ZN3KJS16mathProtoFuncCosEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS17mathProtoFuncSqrtEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS17mathProtoFuncASinEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS14ExpressionNode16evaluateToNumberEPNS_9ExecStateE -__ZN3KJS11DoWhileNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS21stringProtoFuncSearchEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS13PreDecDotNode8evaluateEPNS_9ExecStateE -__ZN3KJS18PostfixBracketNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS18PostIncBracketNode8evaluateEPNS_9ExecStateE -__ZN3KJS13LeftShiftNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE +__ZN3JSC17PrefixResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZNK3JSC10NegateNode8opcodeIDEv +__ZN3JSC10NegateNodeD1Ev +__ZN3JSC11Interpreter13cti_op_negateEPvz +__ZN3JSCL17mathProtoFuncSqrtEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSC11JSImmediate12toThisObjectENS_10JSValuePtrEPNS_9ExecStateE +__ZN3JSCL16mathProtoFuncAbsEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSCL18mathProtoFuncRoundEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSCL16mathProtoFuncCosEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSCL16mathProtoFuncSinEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSC11Interpreter12cti_op_jlessEPvz +__ZNK3JSC8JSObject8toNumberEPNS_9ExecStateE +__ZN3JSC16ArrayConstructor11getCallDataERNS_8CallDataE +__ZN3JSCL20callArrayConstructorEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSC12JSNumberCell18getPrimitiveNumberEPNS_9ExecStateERdRNS_10JSValuePtrE +__ZN3JSC11Interpreter10cti_op_modEPvz +__ZL17makeLeftShiftNodePvPN3JSC14ExpressionNodeES2_b +__ZNK3JSC13LeftShiftNode8opcodeIDEv +__ZN3JSC13LeftShiftNodeD1Ev +__ZN3JSC3JIT26compileFastArith_op_lshiftEjjj +__ZN3JSC3JIT30compileFastArithSlow_op_lshiftEjjjRPNS_13SlowCaseEntryE +__ZN3JSCL16mathProtoFuncMaxEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZNK3JSC10BitAndNode8opcodeIDEv +__ZN3JSC10BitAndNodeD1Ev +__ZN3JSC3JIT26compileFastArith_op_bitandEjjj +__ZN3JSC3JIT30compileFastArithSlow_op_bitandEjjjRPNS_13SlowCaseEntryE +__ZN3JSC11Interpreter13cti_op_bitandEPvz +__ZNK3JSC14BitwiseNotNode8opcodeIDEv +__ZN3JSC14BitwiseNotNodeD1Ev +__ZN3JSC11Interpreter13cti_op_lshiftEPvz +__ZN3JSC11Interpreter13cti_op_bitnotEPvz +__ZNK3JSC22UnsignedRightShiftNode8opcodeIDEv +__ZNK3JSC10BitXOrNode8opcodeIDEv +__ZN3JSC22UnsignedRightShiftNodeD1Ev +__ZN3JSC10BitXOrNodeD1Ev +__ZN3JSCL25stringProtoFuncCharCodeAtEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSC11Interpreter14cti_op_urshiftEPvz +__ZNK3JSC12JSNumberCell18getTruncatedUInt32ERj +__ZN3JSC16toUInt32SlowCaseEdRb +__ZN3JSCL17mathProtoFuncCeilEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZNK3JSC6JSCell18getTruncatedUInt32ERj +__ZN3JSC11Interpreter12cti_op_bitorEPvz +__ZNK3JSC12JSNumberCell17getTruncatedInt32ERi +__ZNK3JSC9BitOrNode8opcodeIDEv +__ZN3JSC9BitOrNodeD1Ev +__ZN3JSC11Interpreter13cti_op_rshiftEPvz +__ZN3JSC11Interpreter13cti_op_bitxorEPvz +__ZN3JSC9parseDateERKNS_7UStringE +__ZNK3JSC12JSActivation12toThisObjectEPNS_9ExecStateE +__ZN3JSC11Interpreter19cti_op_resolve_skipEPvz +__ZN3JSCL24dateProtoFuncGetFullYearEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSC17StringConstructor16getConstructDataERNS_13ConstructDataE +__ZN3JSCL30constructWithStringConstructorEPNS_9ExecStateEPNS_8JSObjectERKNS_7ArgListE +__ZN3JSC5equalEPKNS_7UString3RepES3_ +__ZN3JSC10SwitchNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZN3JSC13CaseBlockNode20emitBytecodeForBlockERNS_17BytecodeGeneratorEPNS_10RegisterIDES4_ +__ZN3JSC13CaseBlockNode18tryOptimizedSwitchERN3WTF6VectorIPNS_14ExpressionNodeELm8EEERiS7_ +__ZN3JSCL17processClauseListEPNS_14ClauseListNodeERN3WTF6VectorIPNS_14ExpressionNodeELm8EEERNS_10SwitchKindERbRiSB_ +__ZNK3JSC10StringNode8isStringEv +__ZN3WTF6VectorIPN3JSC14ExpressionNodeELm8EE14expandCapacityEm +__ZN3WTF6VectorINS_6RefPtrIN3JSC5LabelEEELm8EE14expandCapacityEm +__ZN3JSC17BytecodeGenerator11beginSwitchEPNS_10RegisterIDENS_10SwitchInfo10SwitchTypeE +__ZN3WTF6VectorIN3JSC10SwitchInfoELm0EE14expandCapacityEm +__ZN3JSC17BytecodeGenerator9endSwitchEjPN3WTF6RefPtrINS_5LabelEEEPPNS_14ExpressionNodeEPS3_ii +__ZN3WTF6VectorIN3JSC15SimpleJumpTableELm0EE14expandCapacityEm +__ZN3WTF6VectorIiLm0EE15reserveCapacityEm +__ZN3JSC10SwitchNode12releaseNodesERNS_12NodeReleaserE +__ZN3JSC13CaseBlockNode12releaseNodesERNS_12NodeReleaserE +__ZN3JSC14ClauseListNode12releaseNodesERNS_12NodeReleaserE +__ZN3JSC14CaseClauseNode12releaseNodesERNS_12NodeReleaserE +__ZN3JSC10SwitchNodeD1Ev +__ZN3JSC13CaseBlockNodeD1Ev +__ZN3JSC14ClauseListNodeD1Ev +__ZN3JSC14CaseClauseNodeD1Ev +__ZN3WTF6VectorIN3JSC12SwitchRecordELm0EE14expandCapacityEm +__ZN3WTF6VectorIPvLm0EE15reserveCapacityEm +__ZN3JSC11Interpreter18cti_op_switch_charEPvz +__ZN3JSC8EvalNodeD1Ev +__ZN3JSCL16mathProtoFuncPowEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3WTF6VectorIcLm0EE14expandCapacityEm +__ZN3WTF6VectorIN3JSC7UString5RangeELm16EE14expandCapacityEm +__ZN3WTF6VectorIN3JSC7UStringELm16EE14expandCapacityEm +__ZN3WTF17TCMalloc_PageHeap3NewEm +__ZN3JSC7JSArray16getPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayE +__ZN3JSC9ExecState10arrayTableEPS0_ +__ZN3JSCL18regExpObjectSourceEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE +__ZN3JSC7ArgList10slowAppendENS_10JSValuePtrE +__ZN3WTF7HashSetIPN3JSC7ArgListENS_7PtrHashIS3_EENS_10HashTraitsIS3_EEE3addERKS3_ +__ZN3WTF9HashTableIPN3JSC7ArgListES3_NS_17IdentityExtractorIS3_EENS_7PtrHashIS3_EENS_10HashTraitsIS3_EES9_E6rehashEi +__ZN3WTF6VectorIN3JSC8RegisterELm8EE15reserveCapacityEm +__ZN3JSC22JSPropertyNameIterator4markEv +__ZN3JSCL16mathProtoFuncLogEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSCL29objectProtoFuncHasOwnPropertyEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSCL18arrayProtoFuncSortEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSC7JSArray4sortEPNS_9ExecStateENS_10JSValuePtrENS_8CallTypeERKNS_8CallDataE +__ZN3WTF7AVLTreeIN3JSC32AVLTreeAbstractorForArrayCompareELj44ENS_18AVLTreeDefaultBSetILj44EEEE6insertEi +__ZN3JSCltERKNS_7UStringES2_ +__ZN3WTF7AVLTreeIN3JSC32AVLTreeAbstractorForArrayCompareELj44ENS_18AVLTreeDefaultBSetILj44EEEE7balanceEi +__ZN3JSC4WREC9Generator29generateAssertionWordBoundaryERNS_14MacroAssembler8JumpListEb +__ZN3JSC12X86Assembler23X86InstructionFormatter11memoryModRMEiNS_3X8610RegisterIDES3_ii +__ZN3JSCL21stringProtoFuncConcatEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSC19globalFuncEncodeURIEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSC19globalFuncDecodeURIEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSCL6decodeEPNS_9ExecStateERKNS_7ArgListEPKcb __ZN3WTF7Unicode18UTF8SequenceLengthEc __ZN3WTF7Unicode18decodeUTF8SequenceEPKc -__ZN3KJS9StringImp18getPrimitiveNumberEPNS_9ExecStateERdRPNS_7JSValueE -__ZN3KJSltERKNS_7UStringES2_ -__ZN3KJS15ConditionalNode16evaluateToNumberEPNS_9ExecStateE -__ZN3KJS10BitAndNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS10BitAndNode17evaluateToBooleanEPNS_9ExecStateE -__ZN3KJS15DotAccessorNode15evaluateToInt32EPNS_9ExecStateE -__ZN3KJS19ImmediateNumberNode15evaluateToInt32EPNS_9ExecStateE -__ZN3KJS13ArrayInstance16getPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayE -__ZN3KJS18LocalVarAccessNode15evaluateToInt32EPNS_9ExecStateE -__ZN3KJS13LeftShiftNode16evaluateToNumberEPNS_9ExecStateE -__ZN3KJS19BracketAccessorNode16evaluateToUInt32EPNS_9ExecStateE -__ZN3KJS14RightShiftNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS14RightShiftNode8evaluateEPNS_9ExecStateE -__ZN3KJS7AddNode15evaluateToInt32EPNS_9ExecStateE -__ZN3KJS19ImmediateNumberNode16evaluateToUInt32EPNS_9ExecStateE -__ZN3KJS13LeftShiftNode8evaluateEPNS_9ExecStateE -__ZN3KJS18LocalVarAccessNode16evaluateToUInt32EPNS_9ExecStateE -__ZNK3KJS9NumberImp17getTruncatedInt32ERi -__ZN3KJS19BracketAccessorNode15evaluateToInt32EPNS_9ExecStateE -__ZN3KJS16BooleanObjectImp9constructEPNS_9ExecStateERKNS_4ListE -__ZN3KJS24booleanProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS14BitwiseNotNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS9BitOrNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS9BitOrNode8evaluateEPNS_9ExecStateE -__ZN3KJS10BitAndNode8evaluateEPNS_9ExecStateE -__ZN3KJS14BitwiseNotNode8evaluateEPNS_9ExecStateE -__ZN3KJS15NumberObjectImp14callAsFunctionEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS8Bindings8Instance32createBindingForLanguageInstanceENS1_15BindingLanguageEPvN3WTF10PassRefPtrINS0_10RootObjectEEE -__ZN3KJS8Bindings9CInstanceC2EP8NPObjectN3WTF10PassRefPtrINS0_10RootObjectEEE -__ZN3KJS8Bindings8InstanceC2EN3WTF10PassRefPtrINS0_10RootObjectEEE -__ZNK3KJS8Bindings8Instance10rootObjectEv -__ZN3KJS8Bindings8Instance19createRuntimeObjectEPS1_ -__ZN3KJS16RuntimeObjectImpC2EPNS_8Bindings8InstanceE -__ZN3KJS8Bindings10RootObject16addRuntimeObjectEPNS_16RuntimeObjectImpE -__ZN3KJS16RuntimeObjectImp18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE -__ZN3KJS8Bindings9CInstance5beginEv -__ZNK3KJS8Bindings9CInstance8getClassEv -__ZN3KJS8Bindings6CClass11classForIsAEP7NPClass -__ZN3KJS8Bindings6CClassC2EP7NPClass -__ZNK3KJS8Bindings6CClass10fieldNamedERKNS_10IdentifierEPNS0_8InstanceE -__ZNK3KJS7UString5asciiEv -__ZNK3KJS8Bindings6CClass12methodsNamedERKNS_10IdentifierEPNS0_8InstanceE -__NPN_UTF8FromIdentifier -__ZN3KJS8Bindings5Class14fallbackObjectEPNS_9ExecStateEPNS0_8InstanceERKNS_10IdentifierE -__ZN3KJS8Bindings9CInstance3endEv -__ZN3WTF6VectorIPN3KJS8Bindings6MethodELm0EE14expandCapacityEmPKS4_ -__ZN3WTF6VectorIPN3KJS8Bindings6MethodELm0EE14expandCapacityEm -__ZN3WTF6VectorIPN3KJS8Bindings6MethodELm0EE15reserveCapacityEm -__ZN3KJS16RuntimeObjectImp12methodGetterEPNS_9ExecStateEPNS_8JSObjectERKNS_10IdentifierERKNS_12PropertySlotE -__ZN3KJS13RuntimeMethodC2EPNS_9ExecStateERKNS_10IdentifierERN3WTF6VectorIPNS_8Bindings6MethodELm0EEE -__ZN3WTF6VectorIPN3KJS8Bindings6MethodELm0EEC2ERKS5_ -__ZN3KJS13RuntimeMethod14callAsFunctionEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZNK3KJS16RuntimeObjectImp9classInfoEv -__ZN3KJS8Bindings9CInstance12invokeMethodEPNS_9ExecStateERKN3WTF6VectorIPNS0_6MethodELm0EEERKNS_4ListE -__ZNK3KJS8Bindings7CMethod4nameEv -__ZN3KJS8Bindings23convertNPVariantToValueEPNS_9ExecStateEPK10_NPVariantPNS0_10RootObjectE -__ZN3KJS16RuntimeObjectImpD2Ev -__ZN3KJS8Bindings10RootObject19removeRuntimeObjectEPNS_16RuntimeObjectImpE -__ZN3KJS4Node10throwErrorEPNS_9ExecStateENS_9ErrorTypeEPKcPNS_7JSValueEPS0_RKNS_10IdentifierE -__ZN3KJS10substituteERNS_7UStringERKS0_ -__ZN3KJS4Node16rethrowExceptionEPNS_9ExecStateE -__ZN3KJS4Node15handleExceptionEPNS_9ExecStateEPNS_7JSValueE -__ZN3KJS16RuntimeObjectImp10invalidateEv -__ZN3KJS16JSVariableObject14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE -__ZN3KJS14JSGlobalObjectD2Ev -__ZN3KJS15GlobalExecStateD1Ev -__ZN3KJS14BitwiseNotNodeD1Ev -__ZN3KJSplERKNS_7UStringES2_ -__ZN3KJS5Lexer14convertUnicodeEiiii -__ZN3KJS14ArrayObjectImp14callAsFunctionEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS9Arguments3putEPNS_9ExecStateERKNS_10IdentifierEPNS_7JSValueEi -__ZN3WTF9HashTableIjSt4pairIjiENS_18PairFirstExtractorIS2_EENS_7IntHashIjEENS_14PairHashTraitsINS_10HashTraitsIjEENS8_IiEEEES9_E3addIjS2_NS_22IdentityHashTranslatorIjS2_S6_EEEES1_INS_17HashTableIteratorIjS2_S4_S6_SB_S9_EEbERKT_RKT0_ -__ZN3WTF9HashTableIjSt4pairIjiENS_18PairFirstExtractorIS2_EENS_7IntHashIjEENS_14PairHashTraitsINS_10HashTraitsIjEENS8_IiEEEES9_EC2ERKSC_ -__ZN3KJS23stringProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3WTF9HashTableIjSt4pairIjiENS_18PairFirstExtractorIS2_EENS_7IntHashIjEENS_14PairHashTraitsINS_10HashTraitsIjEENS8_IiEEEES9_E4findIjNS_22IdentityHashTranslatorIjS2_S6_EEEENS_17HashTableIteratorIjS2_S4_S6_SB_S9_EERKT_ -__ZN3KJS10BitXOrNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS10BitXOrNode8evaluateEPNS_9ExecStateE -__ZN3KJS14RightShiftNode15evaluateToInt32EPNS_9ExecStateE -__ZN3KJS10BitXOrNodeD1Ev -__ZN3KJS17DateObjectFuncImp14callAsFunctionEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS9parseDateERKNS_7UStringE -__ZN3KJS6RegExp6createERKNS_7UStringE -__ZN3KJS7ModNode16evaluateToNumberEPNS_9ExecStateE -__ZNK3KJS16RuntimeObjectImp14implementsCallEv -__ZNK3KJS8Bindings9CInstance14implementsCallEv -__ZN3KJS11Interpreter21shouldPrintExceptionsEv -__ZN3KJS4Node10throwErrorEPNS_9ExecStateENS_9ErrorTypeEPKcRKNS_10IdentifierE -__ZN3KJS12PropertySlot15undefinedGetterEPNS_9ExecStateEPNS_8JSObjectERKNS_10IdentifierERKS0_ -__ZN3KJS15SavedPropertiesD1Ev -__ZN3KJS8JSObject18isActivationObjectEv -__ZN3KJS19globalFuncDecodeURIEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS14JSGlobalObject15restoreBuiltinsERKNS_13SavedBuiltinsE -__ZN3KJS11PropertyMap7restoreERKNS_15SavedPropertiesE -__ZN3KJS16JSVariableObject19restoreLocalStorageERKNS_15SavedPropertiesE -__ZN3WTF6VectorIN3KJS17LocalStorageEntryELm32EE6resizeEm -__ZNK3KJS23FunctionCallBracketNode8streamToERNS_12SourceStreamE -__ZNK3KJS17TypeOfResolveNode10precedenceEv -__ZNK3KJS17TypeOfResolveNode8streamToERNS_12SourceStreamE -__ZNK3KJS13AssignDotNode10precedenceEv -__ZNK3KJS12ContinueNode8streamToERNS_12SourceStreamE -__ZN3KJS11FunctionImp12callerGetterEPNS_9ExecStateEPNS_8JSObjectERKNS_10IdentifierERKNS_12PropertySlotE -__ZN3KJS9BreakNodeC1ERKNS_10IdentifierE -__ZN3KJS13StatementNode9pushLabelERKNS_10IdentifierE -__ZN3KJS9ThrowNode7executeEPNS_9ExecStateE -__ZNK3KJS15NumberObjectImp19implementsConstructEv -__ZN3KJS22numberProtoFuncValueOfEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS8VoidNodeD1Ev -__ZN3KJS14ErrorObjectImp14callAsFunctionEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS18globalFuncIsFiniteEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS21ReadModifyResolveNode8evaluateEPNS_9ExecStateE -__ZN3KJS15StrictEqualNode8evaluateEPNS_9ExecStateE -__ZN3KJS27compareByStringPairForQSortEPKvS1_ -__ZN3KJS7compareERKNS_7UStringES2_ -__ZN3KJS4Node10throwErrorEPNS_9ExecStateENS_9ErrorTypeEPKcPNS_7JSValueEPS0_S8_ -__ZN3KJS21arrayProtoFuncReverseEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS20stringProtoFuncSliceEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZNK3KJS15StringObjectImp19implementsConstructEv -__ZN3KJS15StringObjectImp9constructEPNS_9ExecStateERKNS_4ListE -__ZN3KJS18PostDecResolveNode8evaluateEPNS_9ExecStateE -__ZN3KJS21dateProtoFuncSetMonthEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS23setNewValueFromDateArgsEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListEib -__ZN3KJS20dateProtoFuncSetDateEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS21dateProtoFuncSetHoursEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS23setNewValueFromTimeArgsEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListEib -__ZN3KJS23dateProtoFuncSetMinutesEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS24dateProtoFuncSetFullYearEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS8JSObject18getPrimitiveNumberEPNS_9ExecStateERdRPNS_7JSValueE -__ZN3KJS20dateProtoFuncValueOfEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS27dateProtoFuncGetUTCFullYearEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS27dateProtoFuncSetUTCFullYearEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS24dateProtoFuncGetUTCMonthEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS24dateProtoFuncSetUTCMonthEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS23dateProtoFuncGetUTCDateEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS23dateProtoFuncSetUTCDateEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS24dateProtoFuncGetUTCHoursEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS24dateProtoFuncSetUTCHoursEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS26dateProtoFuncGetUTCMinutesEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS26dateProtoFuncSetUTCMinutesEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS26dateProtoFuncGetUTCSecondsEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS26dateProtoFuncSetUTCSecondsEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS22numberProtoFuncToFixedEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS18integer_part_noexpEd -__ZN3KJS14AddNumbersNode16evaluateToNumberEPNS_9ExecStateE -__ZNK3KJS14InstanceOfNode10precedenceEv -__ZNK3KJS14InstanceOfNode8streamToERNS_12SourceStreamE -__ZNK3KJS8JSObject8toNumberEPNS_9ExecStateE -__Z15kjs_pcre_xclassiPKh -__ZN3KJS10NumberNode17evaluateToBooleanEPNS_9ExecStateE -__ZN3KJS18PostDecBracketNodeD1Ev -__ZN3KJS17PropertyNameArray3addERKNS_10IdentifierE -__ZN3KJS22errorProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS13LeftShiftNode15evaluateToInt32EPNS_9ExecStateE -__ZNK3KJS9RegExpImp14implementsCallEv -__ZN3KJS22stringProtoFuncValueOfEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS15ConditionalNode17evaluateToBooleanEPNS_9ExecStateE -__ZN3KJS16JSVariableObject16getPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayE -__ZN3KJS11DoWhileNode7executeEPNS_9ExecStateE -__ZN3KJS8Bindings23convertObjcValueToValueEPNS_9ExecStateEPvNS0_13ObjcValueTypeEPNS0_10RootObjectE -__ZN3KJS8Bindings17webUndefinedClassEv -__ZN3KJS8Bindings20webScriptObjectClassEv -__ZN3KJS8Bindings8Instance19createRuntimeObjectENS1_15BindingLanguageEPvN3WTF10PassRefPtrINS0_10RootObjectEEE -__ZN3KJS8Bindings12ObjcInstanceC2EP11objc_objectN3WTF10PassRefPtrINS0_10RootObjectEEE -__ZN3KJS8Bindings8Instance18didExecuteFunctionEv -__ZN3KJS8Bindings12ObjcInstance5beginEv -__ZNK3KJS8Bindings12ObjcInstance8getClassEv -__ZN3KJS8Bindings9ObjcClass11classForIsAEP10objc_class -__ZN3KJS8Bindings9ObjcClassC2EP10objc_class -__ZNK3KJS8Bindings9ObjcClass10fieldNamedERKNS_10IdentifierEPNS0_8InstanceE -__ZNK3KJS8Bindings9ObjcClass12methodsNamedERKNS_10IdentifierEPNS0_8InstanceE -__ZN3KJS8Bindings25convertJSMethodNameToObjcEPKcPcm -__ZN3KJS8Bindings10ObjcMethodC2EP10objc_classPKc -__ZN3KJS8Bindings12ObjcInstance3endEv -__ZN3KJS8Bindings12ObjcInstance12invokeMethodEPNS_9ExecStateERKN3WTF6VectorIPNS0_6MethodELm0EEERKNS_4ListE -__ZNK3KJS8Bindings10ObjcMethod18getMethodSignatureEv -__ZNK3KJS8Bindings10ObjcMethod4nameEv -__ZN3KJS8Bindings20objcValueTypeForTypeEPKc -__ZN3KJS8Bindings23convertValueToObjcValueEPNS_9ExecStateEPNS_7JSValueENS0_13ObjcValueTypeE -__ZNK3KJS6JSCell9getStringEv -__ZN3KJS8Bindings23convertNSStringToStringEP8NSString -__ZN3KJS8Bindings12ObjcInstanceD1Ev -__ZN3KJS9LabelNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS9LabelNode7executeEPNS_9ExecStateE -__ZN3KJS12ContinueNodeC1ERKNS_10IdentifierE -__ZN3KJS11FunctionImp12lengthGetterEPNS_9ExecStateEPNS_8JSObjectERKNS_10IdentifierERKNS_12PropertySlotE -__ZN3KJS9BitOrNode15evaluateToInt32EPNS_9ExecStateE -__ZN3KJS18EmptyStatementNode7executeEPNS_9ExecStateE -__ZN3KJS22UnsignedRightShiftNodeD1Ev -__ZN3KJS7ModNode17evaluateToBooleanEPNS_9ExecStateE -__ZN3KJS20arrayProtoFuncFilterEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS6InNode8evaluateEPNS_9ExecStateE -__ZN3KJS17arrayProtoFuncMapEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZNK3KJS10LessEqNode10precedenceEv -__ZNK3KJS10LessEqNode8streamToERNS_12SourceStreamE -__ZNK3KJS18NotStrictEqualNode10precedenceEv -__ZNK3KJS18NotStrictEqualNode8streamToERNS_12SourceStreamE -__ZN3KJS14StringInstance16getPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayE -__ZN3KJS7UString4fromEi -__ZN3KJS14StringInstance11indexGetterEPNS_9ExecStateEPNS_8JSObjectERKNS_10IdentifierERKNS_12PropertySlotE -__ZN3KJS21stringProtoFuncConcatEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS22UnsignedRightShiftNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS11ResolveNode15evaluateToInt32EPNS_9ExecStateE -__ZN3KJS19FunctionCallDotNode15evaluateToInt32EPNS_9ExecStateE -__ZN3KJS22UnsignedRightShiftNode15evaluateToInt32EPNS_9ExecStateE -__ZN3KJS11ResolveNode16evaluateToUInt32EPNS_9ExecStateE -__ZNK3KJS9NumberImp18getTruncatedUInt32ERj -__ZN3KJS10NumberNode15evaluateToInt32EPNS_9ExecStateE -__ZN3KJS7SubNode16evaluateToUInt32EPNS_9ExecStateE -__ZN3KJS14BitwiseNotNode15evaluateToInt32EPNS_9ExecStateE -__ZN3KJS10BitAndNode15evaluateToInt32EPNS_9ExecStateE -__ZN3KJS7AddNode16evaluateToUInt32EPNS_9ExecStateE -__ZN3KJS7SubNode15evaluateToInt32EPNS_9ExecStateE -__ZN3KJS8VoidNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS8VoidNode8evaluateEPNS_9ExecStateE -__ZN3KJS17DeleteResolveNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS18LocalVarDeleteNodeD1Ev -__ZN3KJS11FunctionImp15argumentsGetterEPNS_9ExecStateEPNS_8JSObjectERKNS_10IdentifierERKNS_12PropertySlotE -__ZN3KJS18LocalVarDeleteNode8evaluateEPNS_9ExecStateE -__ZN3KJS17DeleteResolveNode8evaluateEPNS_9ExecStateE -__ZNK3KJS16RuntimeObjectImp6canPutEPNS_9ExecStateERKNS_10IdentifierE -__ZN3KJS13UnaryPlusNode8evaluateEPNS_9ExecStateE -__ZN3KJS24dateProtoFuncToUTCStringEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS23booleanProtoFuncValueOfEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS11NewExprNode16evaluateToNumberEPNS_9ExecStateE -__Z22kjs_pcre_ucp_othercasej -__ZN3KJS17PreDecResolveNode8evaluateEPNS_9ExecStateE -__ZNK3KJS7JSValue7toFloatEPNS_9ExecStateE -__ZN3KJS14ExpressionNode15evaluateToInt32EPNS_9ExecStateE -__ZN3KJS4List26markProtectedListsSlowCaseEv -__ZNK3KJS6JSCell9getStringERNS_7UStringE -__ZN3KJS8TrueNode17evaluateToBooleanEPNS_9ExecStateE -__ZN3KJS9RegExpImp3putEPNS_9ExecStateERKNS_10IdentifierEPNS_7JSValueEi -__ZNK3KJS9NumberImp9getUInt32ERj -__ZN3KJS4Node10throwErrorEPNS_9ExecStateENS_9ErrorTypeEPKcPNS_7JSValueEPS0_ -__ZN3KJS23FunctionCallResolveNode15evaluateToInt32EPNS_9ExecStateE -__ZNK3KJS6JSCell18getTruncatedUInt32ERj -__ZNK3KJS9LabelNode8streamToERNS_12SourceStreamE -__ZNK3KJS17ObjectLiteralNode21needsParensIfLeftmostEv -__ZNK3KJS11DoWhileNode8streamToERNS_12SourceStreamE -__ZNK3KJS17PreDecResolveNode8streamToERNS_12SourceStreamE -__ZNK3KJS13PreIncDotNode8streamToERNS_12SourceStreamE -__ZNK3KJS13PreDecDotNode8streamToERNS_12SourceStreamE -__ZNK3KJS17DeleteResolveNode8streamToERNS_12SourceStreamE -__ZN3KJS9FalseNode17evaluateToBooleanEPNS_9ExecStateE -__ZN3KJS23dateProtoFuncSetSecondsEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZNK3KJS14PostIncDotNode8streamToERNS_12SourceStreamE -__ZNK3KJS8Bindings12ObjcInstance14implementsCallEv -__ZN3KJS8Bindings9ObjcClass14fallbackObjectEPNS_9ExecStateEPNS0_8InstanceERKNS_10IdentifierE -__ZN3KJS16BooleanObjectImp14callAsFunctionEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS11jsUndefinedEv -___tcf_2 -___tcf_6 -___tcf_0 -___tcf_5 -___tcf_3 -___tcf_4 +__ZN3JSC6JSCell18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE +__ZNK3JSC12JSNumberCell8toObjectEPNS_9ExecStateE +__ZN3JSC15constructNumberEPNS_9ExecStateENS_10JSValuePtrE +__ZN3JSCL22numberProtoFuncToFixedEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSC12JSNumberCell11getJSNumberEv +__ZN3JSCL16integerPartNoExpEd +__ZN3JSC11Interpreter27cti_op_get_by_id_proto_failEPvz +__ZN3WTF6VectorIPN3JSC10RegisterIDELm32EE14expandCapacityEm +__ZN3JSCL17arrayProtoFuncPopEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSC7JSArray3popEv +__ZNK3JSC11DoWhileNode6isLoopEv +__ZN3JSC11DoWhileNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZN3JSC11DoWhileNode12releaseNodesERNS_12NodeReleaserE +__ZN3JSC11DoWhileNodeD1Ev +__ZN3JSC11Interpreter17cti_op_switch_immEPvz +__ZN3JSCL16mathProtoFuncMinEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSC13UnaryPlusNode14stripUnaryPlusEv +__ZN3JSC13UnaryPlusNodeD1Ev +__ZN3JSCL21stringProtoFuncSubstrEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSC15globalFuncIsNaNEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSC17NumberConstructor11getCallDataERNS_8CallDataE +__ZN3JSCL21callNumberConstructorEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSC11Interpreter15cti_op_post_incEPvz +__ZN3JSCL23stringProtoFuncFontsizeEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSCL24dateProtoFuncSetFullYearEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSCL23setNewValueFromDateArgsEPNS_9ExecStateENS_10JSValuePtrERKNS_7ArgListEib +__ZN3JSCL24dateProtoFuncToUTCStringEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSCL19stringProtoFuncLinkEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSCL9dateParseEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSC11Interpreter21cti_op_loop_if_lesseqEPvz +__ZN3JSCL16mathProtoFuncExpEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSC6RegExp6createEPNS_12JSGlobalDataERKNS_7UStringE +__ZN3JSCL21dateProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSC4WREC9Generator36generateParenthesesInvertedAssertionERNS_14MacroAssembler8JumpListE +__ZNK3JSC11Interpreter18retrieveLastCallerEPNS_9ExecStateERiRlRNS_7UStringERNS_10JSValuePtrE +__ZN3JSC9CodeBlock27lineNumberForBytecodeOffsetEPNS_9ExecStateEj +__ZN3JSCL23regExpProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSCL18regExpObjectGlobalEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE +__ZN3JSCL22regExpObjectIgnoreCaseEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE +__ZN3JSCL21regExpObjectMultilineEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE +__ZN3JSC11Interpreter17cti_op_is_booleanEPvz +__ZNK3JSC12JSNumberCell11toPrimitiveEPNS_9ExecStateENS_22PreferredPrimitiveTypeE +__ZN3JSC4WREC14CharacterClass9nonspacesEv +__ZN3JSC4Heap15recordExtraCostEm +__ZN3WTF6VectorIN3JSC15StringJumpTableELm0EE15reserveCapacityEm +__ZN3WTF9HashTableINS_6RefPtrIN3JSC7UString3RepEEESt4pairIS5_NS2_14OffsetLocationEENS_18PairFirstExtractorIS8_EENS_7StrHashIS5_EENS_14PairHashTraitsINS_10HashTraitsIS5_EENSE_IS7_EEEESF_EC2ERKSI_ +__ZN3JSC11Interpreter20cti_op_switch_stringEPvz +__ZNK3JSC12JSNumberCell12toThisObjectEPNS_9ExecStateE +__ZN3JSCL22numberProtoFuncValueOfEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSC12NumberObject11getJSNumberEv +__ZNK3JSC13UnaryPlusNode8opcodeIDEv +__ZN3WTF12detachThreadEj +__ZN3WTFL26pthreadHandleForIdentifierEj +__ZN3WTFL31clearPthreadHandleForIdentifierEj +__ZN3WTF15ThreadConditionD1Ev +__ZN3WTF23waitForThreadCompletionEjPPv +__ZN3WTF20TCMalloc_ThreadCache18DestroyThreadCacheEPv +__ZN3WTF20TCMalloc_ThreadCache11DeleteCacheEPS0_ +__ZN3WTF14FastMallocZone10statisticsEP14_malloc_zone_tP19malloc_statistics_t +__ZN3JSC4Heap26protectedGlobalObjectCountEv +__ZNK3JSC11ResolveNode10isLocationEv +__ZNK3JSC11ResolveNode13isResolveNodeEv +__ZN3JSC17AssignResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZN3JSC17BytecodeGenerator18findScopedPropertyERKNS_10IdentifierERiRmbRPNS_8JSObjectE +__ZN3JSC17BytecodeGenerator15emitResolveBaseEPNS_10RegisterIDERKNS_10IdentifierE +__ZN3JSC15DotAccessorNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZN3JSC17BytecodeGenerator12newTemporaryEv +__ZN3JSC10StringNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZN3JSC17BytecodeGenerator8emitLoadEPNS_10RegisterIDERKNS_10IdentifierE +__ZN3WTF9HashTableIPN3JSC7UString3RepESt4pairIS4_PNS1_8JSStringEENS_18PairFirstExtractorIS8_EENS1_17IdentifierRepHashENS_14PairHashTraitsINS_10HashTraitsIS4_EENSD_IS7_EEEESE_E6expandEv +__ZN3JSC16ArgumentListNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZN3JSC10StringNodeD1Ev +__ZN3JSC16ArgumentListNode12releaseNodesERNS_12NodeReleaserE +__ZN3JSC16ArgumentListNodeD1Ev +__ZN3JSC11Interpreter19cti_op_resolve_baseEPvz +__ZN3JSC14JSGlobalObject3putEPNS_9ExecStateERKNS_10IdentifierENS_10JSValuePtrERNS_15PutPropertySlotE +__ZNK3JSC8JSString8toStringEPNS_9ExecStateE +__ZN3JSC13AssignDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZNK3JSC10StringNode6isPureERNS_17BytecodeGeneratorE +__ZN3JSC13ParameterNode12releaseNodesERNS_12NodeReleaserE +__ZN3WTF6VectorISt4pairIN3JSC10IdentifierEjELm0EEaSERKS5_ +__ZNK3JSC7UString14toStrictUInt32EPb +__ZN3JSC17BytecodeGenerator8emitMoveEPNS_10RegisterIDES2_ +__ZN3JSC16VarStatementNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZL12makeMultNodePvPN3JSC14ExpressionNodeES2_b +__ZN3JSC14ExpressionNode14stripUnaryPlusEv +__ZN3JSC10NumberNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZN3JSC17BytecodeGenerator8emitLoadEPNS_10RegisterIDEd +__ZN3WTF9HashTableIdSt4pairIdN3JSC10JSValuePtrEENS_18PairFirstExtractorIS4_EENS_9FloatHashIdEENS_14PairHashTraitsINS_10HashTraitsIdEENSA_IS3_EEEESB_E6expandEv +__ZNK3JSC7AddNode8opcodeIDEv +__ZNK3JSC8MultNode8opcodeIDEv +__ZN3JSC10NumberNodeD1Ev +__ZN3JSC8MultNodeD1Ev +__ZN3JSC3JIT23compileFastArith_op_mulEPNS_11InstructionE +__ZN3JSC14MacroAssembler4jz32ENS_3X8610RegisterIDENS0_5Imm32E +__ZN3JSC12X86Assembler7subl_irEiNS_3X8610RegisterIDE +__ZN3JSC3JIT20compileBinaryArithOpENS_8OpcodeIDEjjjNS_12OperandTypesE +__ZN3JSC9CodeBlock19isKnownNotImmediateEi +__ZN3JSC12X86Assembler23X86InstructionFormatter11memoryModRMEiNS_3X8610RegisterIDEi +__ZN3JSC12X86Assembler23X86InstructionFormatter9twoByteOpENS0_15TwoByteOpcodeIDEiNS_3X8610RegisterIDEi +__ZN3JSC12X86Assembler8sarl_i8rEiNS_3X8610RegisterIDE +__ZN3JSC15AssemblerBuffer7putByteEi +__ZN3JSC12X86Assembler23X86InstructionFormatter9twoByteOpENS0_15TwoByteOpcodeIDEiNS_3X8610RegisterIDE +__ZN3JSC3JIT42putDoubleResultToJSNumberCellOrJSImmediateENS_3X8613XMMRegisterIDENS1_10RegisterIDEjPNS_12X86Assembler6JmpSrcES2_S3_S3_ +__ZN3JSC3JIT27compileFastArithSlow_op_mulEPNS_11InstructionERPNS_13SlowCaseEntryE +__ZN3JSC3JIT27compileFastArithSlow_op_addEPNS_11InstructionERPNS_13SlowCaseEntryE +__ZN3JSC3JIT28compileBinaryArithOpSlowCaseENS_8OpcodeIDERPNS_13SlowCaseEntryEjjjNS_12OperandTypesE +__ZN3JSC11Interpreter31cti_op_construct_NotJSConstructEPvz +__ZN3JSC15DateConstructor16getConstructDataERNS_13ConstructDataE +__ZN3JSCL28constructWithDateConstructorEPNS_9ExecStateEPNS_8JSObjectERKNS_7ArgListE +__ZN3JSC13constructDateEPNS_9ExecStateERKNS_7ArgListE +__ZN3JSC13DatePrototype18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE +__ZN3JSCL20dateProtoFuncGetTimeEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZNK3JSC12DateInstance9classInfoEv +__ZN3JSC11Interpreter10cti_op_addEPvz +__ZN3JSC12jsNumberCellEPNS_12JSGlobalDataEd +__ZNK3JSC12JSNumberCell8toNumberEPNS_9ExecStateE +__ZN3JSC11BooleanNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZN3JSC6IfNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZNK3JSC9BlockNode7isBlockEv +__ZN3JSC9BlockNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZN3JSC9BlockNode12releaseNodesERNS_12NodeReleaserE +__ZN3JSC10JSFunction4markEv +__ZN3JSC16FunctionBodyNode4markEv +__ZN3JSC23FunctionCallResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZN3JSC17BytecodeGenerator19emitResolveFunctionEPNS_10RegisterIDES2_RKNS_10IdentifierE +__ZNK3JSC12NotEqualNode8opcodeIDEv +__ZNK3JSC8LessNode8opcodeIDEv +__ZN3JSC23FunctionCallResolveNode12releaseNodesERNS_12NodeReleaserE +__ZN3JSC23FunctionCallResolveNodeD1Ev +__ZN3JSC12NotEqualNodeD1Ev +__ZN3JSC8LessNodeD1Ev +__ZN3JSC11Interpreter19cti_op_resolve_funcEPvz +__ZN3JSC11Interpreter22cti_op_call_JSFunctionEPvz +__ZN3JSC16FunctionBodyNode16generateBytecodeEPNS_14ScopeChainNodeE +__ZN3JSC6Parser14reparseInPlaceEPNS_12JSGlobalDataEPNS_16FunctionBodyNodeE +__ZN3JSC17BytecodeGeneratorC2EPNS_16FunctionBodyNodeEPKNS_8DebuggerERKNS_10ScopeChainEPN3WTF7HashMapINS9_6RefPtrINS_7UString3RepEEENS_16SymbolTableEntryENS_17IdentifierRepHashENS9_10HashTraitsISE_EENS_26SymbolTableIndexHashTraitsEEEPNS_9CodeBlockE +__ZN3JSC16FunctionBodyNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZNK3JSC16JSVariableObject16isVariableObjectEv +__ZN3JSC17BytecodeGenerator16emitGetScopedVarEPNS_10RegisterIDEmiNS_10JSValuePtrE +__ZNK3JSC13StatementNode12isReturnNodeEv +__ZN3JSC17BytecodeGenerator10emitReturnEPNS_10RegisterIDE +__ZN3JSC11Interpreter23cti_vm_dontLazyLinkCallEPvz +__ZN3JSC11Interpreter23cti_register_file_checkEPvz +__ZN3JSC17BytecodeGenerator12addParameterERKNS_10IdentifierE +__ZNK3JSC13StatementNode7isBlockEv +__ZN3JSC10ReturnNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZNK3JSC14JSGlobalObject14isDynamicScopeEv +__ZN3JSC10ReturnNode12releaseNodesERNS_12NodeReleaserE +__ZN3JSC10ReturnNodeD1Ev +__ZN3JSC11concatenateEPNS_7UString3RepES2_ +__ZN3JSC11Interpreter23cti_op_get_by_id_secondEPvz +__ZN3JSC11Interpreter18tryCTICacheGetByIDEPNS_9ExecStateEPNS_9CodeBlockEPvNS_10JSValuePtrERKNS_10IdentifierERKNS_12PropertySlotE +__ZN3JSC3JIT26privateCompileGetByIdProtoEPNS_17StructureStubInfoEPNS_9StructureES4_mPvPNS_9ExecStateE +__ZN3JSC12X86Assembler23X86InstructionFormatter9oneByteOpENS0_15OneByteOpcodeIDEiPv +__ZNK3JSC11ResolveNode6isPureERNS_17BytecodeGeneratorE +__ZN3JSC9CodeBlock4markEv +__ZN3JSC19BracketAccessorNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZN3JSC17BytecodeGenerator12emitGetByValEPNS_10RegisterIDES2_S2_ +__ZN3JSC10JSFunction18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE +__ZN3JSC11Interpreter28cti_op_construct_JSConstructEPvz +__ZN3JSC8JSObject17createInheritorIDEv +__ZL15makePostfixNodePvPN3JSC14ExpressionNodeENS0_8OperatorEiii +__ZNK3JSC7ForNode6isLoopEv +__ZN3JSC7ForNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZN3JSC17BytecodeGenerator13newLabelScopeENS_10LabelScope4TypeEPKNS_10IdentifierE +__ZN3JSC17BytecodeGenerator8emitJumpEPNS_5LabelE +__ZN3JSC17AssignBracketNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZN3JSC8ThisNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZN3JSC17BytecodeGenerator12emitPutByValEPNS_10RegisterIDES2_S2_ +__ZN3JSC18PostfixResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZN3JSC17BytecodeGenerator14emitJumpIfTrueEPNS_10RegisterIDEPNS_5LabelE +__ZN3JSC7ForNode12releaseNodesERNS_12NodeReleaserE +__ZN3JSC7ForNodeD1Ev +__ZN3JSC18PostfixResolveNodeD1Ev +__ZN3JSC17AssignBracketNodeD1Ev +__ZN3JSC17AssignBracketNode12releaseNodesERNS_12NodeReleaserE +__ZN3JSC8ThisNodeD1Ev +__ZN3JSC3JIT27compileFastArith_op_pre_incEj +__ZN3JSC12X86Assembler2joEv +__ZN3JSC3JIT19emitSlowScriptCheckEv +__ZN3JSC3JIT31compileFastArithSlow_op_pre_incEjRPNS_13SlowCaseEntryE +__ZN3JSC11Interpreter22cti_op_call_arityCheckEPvz +__ZN3JSC10JSFunction15argumentsGetterEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE +__ZNK3JSC11Interpreter17retrieveArgumentsEPNS_9ExecStateEPNS_10JSFunctionE +__ZN3JSC9Arguments18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE +__ZN3JSC11Interpreter17cti_op_get_by_valEPvz +__ZN3JSC9Arguments18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE +__ZN3JSC11Interpreter17cti_op_put_by_valEPvz +__ZN3JSC8JSObject3putEPNS_9ExecStateEjNS_10JSValuePtrE +__ZN3JSC11Interpreter24cti_op_get_by_id_genericEPvz +__ZN3JSCL21dateProtoFuncGetMonthEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZNK3JSC12DateInstance21msToGregorianDateTimeEdbRNS_17GregorianDateTimeE +__ZN3JSC21msToGregorianDateTimeEdbRNS_17GregorianDateTimeE +__ZN3JSCL12getDSTOffsetEdd +__ZN3JSC8JSObject18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE +__ZN3JSC8JSObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE +__ZN3JSCL20dateProtoFuncGetDateEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSC11concatenateEPNS_7UString3RepEi +__ZN3JSC21ReadModifyResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZN3JSC21ReadModifyResolveNode12releaseNodesERNS_12NodeReleaserE +__ZN3JSCL20dateProtoFuncGetYearEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZL11makeSubNodePvPN3JSC14ExpressionNodeES2_b +__ZN3JSC10IfElseNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZNK3JSC10LessEqNode8opcodeIDEv +__ZNK3JSC7SubNode8opcodeIDEv +__ZN3JSC10LessEqNodeD1Ev +__ZN3JSC7SubNodeD1Ev +__ZN3JSC3JIT23compileFastArith_op_subEPNS_11InstructionE +__ZN3JSC3JIT27compileFastArithSlow_op_subEPNS_11InstructionERPNS_13SlowCaseEntryE +__ZN3JSCL21dateProtoFuncGetHoursEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSC11Interpreter13cti_op_lesseqEPvz +__ZN3JSCL23dateProtoFuncGetMinutesEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZNK3JSC13GreaterEqNode8opcodeIDEv +__ZN3JSC13GreaterEqNodeD1Ev +__ZN3WTF9HashTableINS_6RefPtrIN3JSC7UString3RepEEESt4pairIS5_NS2_16SymbolTableEntryEENS_18PairFirstExtractorIS8_EENS2_17IdentifierRepHashENS_14PairHashTraitsINS_10HashTraitsIS5_EENS2_26SymbolTableIndexHashTraitsEEESE_E4findIS5_NS_22IdentityHashTranslatorIS5_S8_SB_EEEENS_17HashTableIteratorIS5_S8_SA_SB_SG_SE_EERKT_ +__ZN3JSC8WithNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZN3JSC17BytecodeGenerator13emitPushScopeEPNS_10RegisterIDE +__ZN3WTF6VectorIN3JSC18ControlFlowContextELm0EE14expandCapacityEm +__ZN3JSC11Interpreter9cti_op_eqEPvz +__ZN3JSCeqERKNS_7UStringES2_ +__ZN3JSC11Interpreter17cti_op_push_scopeEPvz +__ZN3JSC11Interpreter14cti_op_resolveEPvz +__ZN3JSC11Interpreter16cti_op_pop_scopeEPvz +__ZN3JSC8NullNodeD1Ev +__ZN3JSC8NullNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZN3JSC17BytecodeGenerator20emitNextPropertyNameEPNS_10RegisterIDES2_PNS_5LabelE +__ZN3JSC9ForInNode12releaseNodesERNS_12NodeReleaserE +__ZN3JSC11Interpreter17cti_op_get_pnamesEPvz +__ZN3JSC22JSPropertyNameIterator6createEPNS_9ExecStateENS_10JSValuePtrE +__ZN3JSC8JSObject16getPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayE +__ZN3JSC9Structure26getEnumerablePropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayEPNS_8JSObjectE +__ZN3JSC9Structure34getEnumerablePropertyNamesInternalERNS_17PropertyNameArrayE +__ZNK3JSC6JSCell9classInfoEv +__ZN3JSC9Structure26createCachedPrototypeChainEv +__ZN3JSC14StructureChainC1EPNS_9StructureE +__ZN3JSC11Interpreter17cti_op_next_pnameEPvz +__ZN3JSC23structureChainsAreEqualEPNS_14StructureChainES1_ +__ZN3JSC13jsOwnedStringEPNS_12JSGlobalDataERKNS_7UStringE +__ZN3JSC11Interpreter10cti_op_neqEPvz +__ZN3JSC16globalFuncEscapeEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSC11JSImmediate8toStringENS_10JSValuePtrE +__ZN3JSC7UString4fromEi +__ZN3JSC7UString6appendERKS0_ +__ZN3JSC22JSPropertyNameIterator10invalidateEv +__ZN3JSCL21dateProtoFuncSetMonthEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSCL20dateProtoFuncSetDateEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSCplERKNS_7UStringES2_ +__ZN3JSC14ExecutablePool13systemReleaseERKNS0_10AllocationE +__ZNK3JSC8JSString11toPrimitiveEPNS_9ExecStateENS_22PreferredPrimitiveTypeE +__ZN3JSC16ArrayConstructor16getConstructDataERNS_13ConstructDataE +__ZN3JSCL29constructWithArrayConstructorEPNS_9ExecStateEPNS_8JSObjectERKNS_7ArgListE +__ZN3JSCL27constructArrayWithSizeQuirkEPNS_9ExecStateERKNS_7ArgListE +__ZL14makePrefixNodePvPN3JSC14ExpressionNodeENS0_8OperatorEiii +__ZN3JSC13PrefixDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZNK3JSC9WhileNode6isLoopEv +__ZN3JSC9WhileNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZN3JSC9WhileNode12releaseNodesERNS_12NodeReleaserE +__ZN3JSC13PrefixDotNode12releaseNodesERNS_12NodeReleaserE +__ZN3JSC13PrefixDotNodeD1Ev +__ZN3JSC9WhileNodeD1Ev +__ZN3JSC3JIT28compileFastArith_op_post_incEjj +__ZN3JSC3JIT32compileFastArithSlow_op_post_incEjjRPNS_13SlowCaseEntryE +__ZN3JSC11Interpreter22cti_op_push_activationEPvz +__ZN3JSC12JSActivationC1EPNS_9ExecStateEN3WTF10PassRefPtrINS_16FunctionBodyNodeEEE +__ZN3JSC12JSActivation18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE +__ZL11makeDivNodePvPN3JSC14ExpressionNodeES2_b +__ZN3JSC15ConditionalNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZNK3JSC7DivNode8opcodeIDEv +__ZN3JSC15ConditionalNode12releaseNodesERNS_12NodeReleaserE +__ZN3JSC15ConditionalNodeD1Ev +__ZN3JSC7DivNodeD1Ev +__ZN3JSC7JSArrayC2EN3WTF10PassRefPtrINS_9StructureEEEj +__ZN3JSC11Interpreter23cti_op_put_by_val_arrayEPvz +__ZN3JSC7JSArray3putEPNS_9ExecStateEjNS_10JSValuePtrE +__ZN3JSC7JSArray3putEPNS_9ExecStateERKNS_10IdentifierENS_10JSValuePtrERNS_15PutPropertySlotE +__ZN3JSC12StringObject3putEPNS_9ExecStateERKNS_10IdentifierENS_10JSValuePtrERNS_15PutPropertySlotE +__ZN3JSC7JSArray18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE +__ZN3JSC11Interpreter10cti_op_divEPvz +__ZN3JSC3JIT16patchGetByIdSelfEPNS_17StructureStubInfoEPNS_9StructureEmPv +__ZN3JSC3JIT33privateCompilePatchGetArrayLengthEPv +__ZN3JSC11Interpreter23cti_op_put_by_id_secondEPvz +__ZN3JSC11Interpreter18tryCTICachePutByIDEPNS_9ExecStateEPNS_9CodeBlockEPvNS_10JSValuePtrERKNS_15PutPropertySlotE +__ZN3JSCL19cachePrototypeChainEPNS_9ExecStateEPNS_9StructureE +__ZN3JSC3JIT31privateCompilePutByIdTransitionEPNS_17StructureStubInfoEPNS_9StructureES4_mPNS_14StructureChainEPv +__ZN3JSC9Structure22materializePropertyMapEv +__ZN3JSC3JIT19patchPutByIdReplaceEPNS_17StructureStubInfoEPNS_9StructureEmPv +__ZN3JSCL21resizePropertyStorageEPNS_8JSObjectEii +__ZN3JSC8JSObject23allocatePropertyStorageEmm +__ZN3JSC11Interpreter14cti_op_pre_incEPvz +__ZN3JSCL21stringProtoFuncCharAtEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZNK3JSC12StringObject12toThisStringEPNS_9ExecStateE +__ZN3JSC11Interpreter26cti_op_tear_off_activationEPvz +__ZN3JSC11Interpreter21cti_op_ret_scopeChainEPvz +__ZN3JSC11Interpreter27cti_op_get_by_id_proto_listEPvz +__ZN3JSC3JIT30privateCompileGetByIdProtoListEPNS_17StructureStubInfoEPNS_30PolymorphicAccessStructureListEiPNS_9StructureES6_mPNS_9ExecStateE +__ZN3JSC12JSActivationD0Ev +__ZN3JSCL26stringProtoFuncToLowerCaseEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSC8JSString14toThisJSStringEPNS_9ExecStateE +__ZN3JSC7JSArray11putSlowCaseEPNS_9ExecStateEjNS_10JSValuePtrE +__ZN3WTF11fastReallocILb0EEEPvS1_m +__ZN3JSCL24stringProtoFuncSubstringEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSC11jsSubstringEPNS_12JSGlobalDataERKNS_7UStringEjj +__ZN3JSCL20stringProtoFuncSplitEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSC19constructEmptyArrayEPNS_9ExecStateE +__ZNK3JSC11BooleanNode6isPureERNS_17BytecodeGeneratorE +__ZNK3JSC7ModNode8opcodeIDEv +__ZN3JSC7ModNodeD1Ev +__ZN3JSC3JIT23compileFastArith_op_modEjjj +__ZN3JSC3JIT27compileFastArithSlow_op_modEjjjRPNS_13SlowCaseEntryE +__ZN3JSCL23dateProtoFuncGetSecondsEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSC17BytecodeGenerator16emitPutScopedVarEmiPNS_10RegisterIDENS_10JSValuePtrE +__ZN3JSC18globalFuncUnescapeEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSC7UString6appendEt +__ZN3JSC11Interpreter19cti_vm_lazyLinkCallEPvz +__ZN3JSC3JIT8linkCallEPNS_10JSFunctionEPNS_9CodeBlockEPvPNS_12CallLinkInfoEi +__ZN3WTF6VectorIPN3JSC12CallLinkInfoELm0EE14expandCapacityEm +__ZN3JSC12X86Assembler7cmpl_imEiiNS_3X8610RegisterIDE +__ZN3JSC9CodeBlock13unlinkCallersEv +__ZNK3JSC8JSString9toBooleanEPNS_9ExecStateE +__ZN3JSC11Interpreter10cti_op_mulEPvz +__ZN3JSC11Interpreter18cti_op_to_jsnumberEPvz +__ZN3JSCL30dateProtoFuncGetTimezoneOffsetEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSCL18mathProtoFuncFloorEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSCL13jsAddSlowCaseEPNS_9ExecStateENS_10JSValuePtrES2_ +__ZN3JSC20globalFuncParseFloatEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSC7UString4fromEj +__ZN3JSC10Identifier11addSlowCaseEPNS_9ExecStateEPNS_7UString3RepE +__ZN3JSC7UString17expandPreCapacityEi +__ZN3JSC9CommaNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZN3JSC9CommaNode12releaseNodesERNS_12NodeReleaserE +__ZN3JSC16VarDeclCommaNodeD1Ev +__ZN3JSC7UStringC1EPtib +__ZN3JSC5Error6createEPNS_9ExecStateENS_9ErrorTypeERKNS_7UStringEilS6_ +__ZN3JSC22NativeErrorConstructor16getConstructDataERNS_13ConstructDataE +__ZN3JSCL35constructWithNativeErrorConstructorEPNS_9ExecStateEPNS_8JSObjectERKNS_7ArgListE +__ZN3JSC22NativeErrorConstructor9constructEPNS_9ExecStateERKNS_7ArgListE +__ZN3JSC8JSObject17putWithAttributesEPNS_9ExecStateERKNS_10IdentifierENS_10JSValuePtrEj +__ZNK3JSC8JSObject8toStringEPNS_9ExecStateE +__ZNK3JSC8JSObject11toPrimitiveEPNS_9ExecStateENS_22PreferredPrimitiveTypeE +__ZNK3JSC8JSObject12defaultValueEPNS_9ExecStateENS_22PreferredPrimitiveTypeE +__ZN3JSCL22errorProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZNK3JSC8JSObject12toThisObjectEPNS_9ExecStateE +__ZN3JSC7UString6appendEPKc +__ZN3JSC3JIT10unlinkCallEPNS_12CallLinkInfoE +__ZN3JSC11Interpreter24cti_op_put_by_id_genericEPvz +__ZN3JSC21FunctionCallValueNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZN3JSC12FuncExprNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZN3JSC17BytecodeGenerator25emitNewFunctionExpressionEPNS_10RegisterIDEPNS_12FuncExprNodeE +__ZN3WTF6VectorINS_6RefPtrIN3JSC12FuncExprNodeEEELm0EE15reserveCapacityEm +__ZN3WTF7HashSetINS_6RefPtrIN3JSC7UString3RepEEENS2_17IdentifierRepHashENS_10HashTraitsIS5_EEE3addERKS5_ +__ZN3WTF9HashTableINS_6RefPtrIN3JSC7UString3RepEEES5_NS_17IdentityExtractorIS5_EENS2_17IdentifierRepHashENS_10HashTraitsIS5_EESA_E6expandEv +__ZL14compileBracketiPiPPhPPKtS3_P9ErrorCodeiS_S_R11CompileData +__ZN3JSC4WREC9Generator20generateAssertionEOLERNS_14MacroAssembler8JumpListE +__ZN3JSC17ObjectLiteralNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZN3JSC4WREC31GeneratePatternCharacterFunctor12generateAtomEPNS0_9GeneratorERNS_14MacroAssembler8JumpListE +__ZN3JSC4WREC31GeneratePatternCharacterFunctor9backtrackEPNS0_9GeneratorE +__ZL20branchNeedsLineStartPKhjj +__ZN3JSC9ArrayNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZN3JSC17BytecodeGenerator12emitNewArrayEPNS_10RegisterIDEPNS_11ElementNodeE +__ZL17bracketIsAnchoredPKh +__ZL32branchFindFirstAssertedCharacterPKhb +__ZN3JSC10JSFunction3putEPNS_9ExecStateERKNS_10IdentifierENS_10JSValuePtrERNS_15PutPropertySlotE +__ZN3JSC11concatenateEPNS_7UString3RepEd +__ZNK3JSC12JSActivation14isDynamicScopeEv +__ZN3JSC17TypeOfResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZN3JSC15StrictEqualNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZN3JSC12ContinueNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZN3JSC17BytecodeGenerator14continueTargetERKNS_10IdentifierE +__ZN3JSC17BytecodeGenerator14emitJumpScopesEPNS_5LabelEi +__ZN3JSC15TypeOfValueNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZN3JSC15TypeOfValueNode12releaseNodesERNS_12NodeReleaserE +__ZN3JSC17TypeOfResolveNodeD1Ev +__ZN3JSC15StrictEqualNodeD1Ev +__ZN3JSC12ContinueNodeD1Ev +__ZN3JSC15TypeOfValueNodeD1Ev +__ZN3JSC11Interpreter33cti_op_create_arguments_no_paramsEPvz +__ZN3JSC11Interpreter13cti_op_typeofEPvz +__ZN3JSCL20jsTypeStringForValueEPNS_9ExecStateENS_10JSValuePtrE +__ZN3JSC6JSCell11getCallDataERNS_8CallDataE +__ZN3JSCL30comparePropertyMapEntryIndicesEPKvS1_ +__ZN3WTF6VectorIN3JSC10IdentifierELm20EE15reserveCapacityEm +__ZN3JSCL22objectProtoFuncValueOfEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSC14ArrayPrototype18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE +__ZN3JSCL22functionProtoFuncApplyEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZNK3JSC7JSArray9classInfoEv +__ZN3JSCL18arrayProtoFuncPushEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSC11Interpreter27cti_op_get_by_id_array_failEPvz +__ZN3JSC14PostfixDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZN3JSC14PostfixDotNode12releaseNodesERNS_12NodeReleaserE +__ZN3JSC11Interpreter32cti_op_get_by_id_proto_list_fullEPvz +__ZN3JSC12FuncExprNodeD1Ev +__ZN3JSC12FuncExprNode12releaseNodesERNS_12NodeReleaserE +__ZN3JSC11Interpreter26cti_op_get_by_id_self_failEPvz +__ZN3JSC3JIT29privateCompileGetByIdSelfListEPNS_17StructureStubInfoEPNS_30PolymorphicAccessStructureListEiPNS_9StructureEm +__ZN3JSCL19arrayProtoFuncSliceEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSC11Interpreter25cti_op_tear_off_argumentsEPvz +__ZN3WTF6VectorIPN3JSC9StructureELm8EE14expandCapacityEm +__ZN3JSCL44countPrototypeChainEntriesAndCheckForProxiesEPNS_9ExecStateENS_10JSValuePtrERKNS_12PropertySlotE +__ZN3JSC17DeleteBracketNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZN3JSC17DeleteBracketNodeD1Ev +__ZN3JSC17DeleteBracketNode12releaseNodesERNS_12NodeReleaserE +__ZN3JSC11Interpreter17cti_op_del_by_valEPvz +__ZN3JSC8JSObject14deletePropertyEPNS_9ExecStateEj +__ZN3JSC8JSObject14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE +__ZNK3JSC6JSCell9getUInt32ERj +__ZNK3JSC8JSObject11hasPropertyEPNS_9ExecStateERKNS_10IdentifierE +__ZN3JSCL11getPropertyEPNS_9ExecStateEPNS_8JSObjectEj +__ZN3JSC17ReadModifyDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZN3JSC17ReadModifyDotNodeD1Ev +__ZN3JSC17ReadModifyDotNode12releaseNodesERNS_12NodeReleaserE +__ZN3JSC11JSImmediate9prototypeENS_10JSValuePtrEPNS_9ExecStateE +__ZN3JSC9CodeBlock34reparseForExceptionInfoIfNecessaryEPNS_9ExecStateE +__ZNK3JSC10ScopeChain10localDepthEv +__ZNK3JSC12JSActivation9classInfoEv +__ZN3JSC6Parser7reparseINS_16FunctionBodyNodeEEEN3WTF10PassRefPtrIT_EEPNS_12JSGlobalDataEPS5_ +__ZN3JSC16FunctionBodyNode6createEPNS_12JSGlobalDataEPNS_14SourceElementsEPN3WTF6VectorISt4pairINS_10IdentifierEjELm0EEEPNS6_INS5_6RefPtrINS_12FuncDeclNodeEEELm0EEERKNS_10SourceCodeEji +__ZN3JSC13StatementNode6setLocEii +__ZN3JSC16FunctionBodyNode14copyParametersEv +__ZN3JSC16FunctionBodyNode13finishParsingEPNS_10IdentifierEm +__ZN3JSC16FunctionBodyNode31bytecodeForExceptionInfoReparseEPNS_14ScopeChainNodeEPNS_9CodeBlockE +__ZN3JSC9CodeBlock36hasGlobalResolveInfoAtBytecodeOffsetEj +__ZN3JSC6RegExpD1Ev __Z12jsRegExpFreeP8JSRegExp -__ZN3KJS25CollectorHeapIntrospector4sizeEP14_malloc_zone_tPKv -__ZN3WTF9HashTableINS_6RefPtrIN3KJS7UString3RepEEESt4pairIS5_mENS_18PairFirstExtractorIS7_EENS2_17IdentifierRepHashENS_14PairHashTraitsINS2_23IdentifierRepHashTraitsENS2_26SymbolTableIndexHashTraitsEEESC_E4findIS5_NS_22IdentityHashTranslatorIS5_S7_SA_EEEENS_17HashTableIteratorIS5_S7_S9_SA_SE_SC_EERKT_ -__ZN3KJS18AssignLocalVarNodeD1Ev -__ZN3KJS8TrueNodeD1Ev -__ZN3KJS11NewExprNodeD1Ev -__ZN3KJS19ImmediateNumberNodeD1Ev -__ZN3KJS17AssignBracketNodeD1Ev -__ZN3KJS18LocalVarAccessNodeD1Ev -__ZN3KJS16ParserRefCounted8refcountEv -__ZN3KJS14JSGlobalObject16stopTimeoutCheckEv -__ZN3KJS11GreaterNodeD1Ev -__ZN3KJS16ArgumentListNodeD1Ev -__ZN3KJS17FunctionObjectImp9constructEPNS_9ExecStateERKNS_4ListERKNS_10IdentifierERKNS_7UStringEi -__ZN3KJS6Parser5parseINS_16FunctionBodyNodeEEEN3WTF10PassRefPtrIT_EERKNS_7UStringEiPKNS_5UCharEjPiSD_PS7_ -__ZN3KJS8JSObject4callEPNS_9ExecStateEPS0_RKNS_4ListE -__ZN3KJS18AddStringRightNode8evaluateEPNS_9ExecStateE -__ZN3KJS16globalFuncEscapeEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZNK3KJS13DateObjectImp19implementsConstructEv -__ZN3KJS13DateObjectImp9constructEPNS_9ExecStateERKNS_4ListE -__ZN3KJS13DatePrototype18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE -__ZN3KJS20dateProtoFuncGetTimeEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZNK3KJS12DateInstance9classInfoEv -__ZNK3KJS9NumberImp8toNumberEPNS_9ExecStateE -__ZNK3KJS9NumberImp8toStringEPNS_9ExecStateE -__ZN3KJS9BlockNodeD1Ev -__ZN3KJS21dateProtoFuncGetMonthEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS21msToGregorianDateTimeEdbRNS_17GregorianDateTimeE -__ZN3KJS12getUTCOffsetEv -__ZN3KJS12getDSTOffsetEdd -__ZN3KJS15ConditionalNodeD1Ev -__ZN3KJS7DivNodeD1Ev -__ZN3KJS9EqualNodeD1Ev -__ZN3KJS8NullNodeD1Ev -__ZN3KJS9FalseNodeD1Ev -__ZN3KJS12NotEqualNodeD1Ev -__ZN3KJS7SubNodeD1Ev -__ZN3KJS7SubNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS24LocalVarFunctionCallNode16evaluateToNumberEPNS_9ExecStateE -__ZN3KJS21ReadModifyResolveNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS14StringInstance12lengthGetterEPNS_9ExecStateEPNS_8JSObjectERKNS_10IdentifierERKNS_12PropertySlotE -__ZN3KJS18globalFuncUnescapeEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS7DivNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS7DivNode8evaluateEPNS_9ExecStateE -__ZN3KJS18LocalVarAccessNode16evaluateToNumberEPNS_9ExecStateE -__ZN3KJS8MultNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS8MultNode8evaluateEPNS_9ExecStateE -__ZN3KJS19FunctionCallDotNode16evaluateToNumberEPNS_9ExecStateE -__ZN3KJS7SubNode8evaluateEPNS_9ExecStateE -__ZNK3KJS9NumberImp11toPrimitiveEPNS_9ExecStateENS_6JSTypeE -__ZN3KJS18AddStringRightNodeD1Ev -__ZN3KJS7AddNodeD1Ev -__ZN3KJS13LogicalOrNodeD1Ev -__ZN3KJS17PreIncResolveNodeD1Ev -__ZN3KJS8MultNodeD1Ev -__ZN3KJS8LessNodeD1Ev -__ZN3KJS14LogicalAndNodeD1Ev -__ZN3KJS10NumberNodeD1Ev -__ZN3KJS13GreaterEqNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS14LogicalNotNodeD1Ev -__ZN3KJS7ModNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS14JSGlobalObject12checkTimeoutEv -__ZN3KJS7ModNode8evaluateEPNS_9ExecStateE -__ZN3KJS15LessNumbersNode8evaluateEPNS_9ExecStateE -__ZN3KJS20dateProtoFuncGetYearEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS8ThisNodeD1Ev -__ZN3KJS19mathProtoFuncRandomEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS20globalFuncParseFloatEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS13GreaterEqNode8evaluateEPNS_9ExecStateE -__ZN3KJS20dateProtoFuncGetDateEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS18mathProtoFuncFloorEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS23stringProtoFuncFontsizeEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS11ResolveNode17evaluateToBooleanEPNS_9ExecStateE -__ZN3KJS13GreaterEqNode17evaluateToBooleanEPNS_9ExecStateE -__ZN3KJS9NumberImp18getPrimitiveNumberEPNS_9ExecStateERdRPNS_7JSValueE -__ZN3KJS19stringProtoFuncLinkEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS19dateProtoFuncGetDayEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS21dateProtoFuncGetHoursEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS23dateProtoFuncGetMinutesEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS23dateProtoFuncGetSecondsEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS9ArrayNodeD1Ev -__ZN3KJS11ElementNodeD1Ev -__ZN3KJS17ObjectLiteralNodeD1Ev -__ZN3KJS14PostfixDotNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS14PostIncDotNode8evaluateEPNS_9ExecStateE -__ZN3KJS19PlaceholderTrueNodeD1Ev -__ZN3KJS19PostDecLocalVarNode8evaluateEPNS_9ExecStateE -__ZN3KJS17ReadModifyDotNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS17ReadModifyDotNode8evaluateEPNS_9ExecStateE -__ZN3KJS21FunctionCallValueNodeD1Ev -__ZN3KJS10BitAndNode16evaluateToUInt32EPNS_9ExecStateE -__ZN3KJS14AddNumbersNode15evaluateToInt32EPNS_9ExecStateE -__ZN3KJS10BitXOrNode15evaluateToInt32EPNS_9ExecStateE -__ZN3KJS22UnsignedRightShiftNode8evaluateEPNS_9ExecStateE -__ZN3KJS8MultNode16evaluateToUInt32EPNS_9ExecStateE -__ZN3KJS7DivNode16evaluateToUInt32EPNS_9ExecStateE -__ZN3KJS19StringObjectFuncImp14callAsFunctionEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS7ModNode16evaluateToUInt32EPNS_9ExecStateE -__ZN3KJS10BitAndNode16evaluateToNumberEPNS_9ExecStateE -__ZN3KJS14RightShiftNode16evaluateToNumberEPNS_9ExecStateE -__ZN3KJS14AddNumbersNode16evaluateToUInt32EPNS_9ExecStateE -__ZN3KJS14globalFuncEvalEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS6Parser5parseINS_8EvalNodeEEEN3WTF10PassRefPtrIT_EERKNS_7UStringEiPKNS_5UCharEjPiSD_PS7_ -__ZN3KJS13EvalExecStateC1EPNS_14JSGlobalObjectEPNS_8EvalNodeEPNS_9ExecStateE -__ZN3KJS8EvalNode7executeEPNS_9ExecStateE -__ZN3KJS8EvalNodeD1Ev -__ZN3KJS23FunctionCallBracketNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS23FunctionCallBracketNode8evaluateEPNS_9ExecStateE -__ZN3KJS16PropertyListNodeD1Ev -__ZN3KJS12PropertyNodeD1Ev -__ZN3KJS13CaseBlockNodeD1Ev -__ZN3KJS14CaseClauseNodeD1Ev -__ZN3KJS14ClauseListNodeD1Ev -__ZN3KJS9RegExpImp18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE -__ZN3KJS17staticValueGetterINS_9RegExpImpEEEPNS_7JSValueEPNS_9ExecStateEPNS_8JSObjectERKNS_10IdentifierERKNS_12PropertySlotE -__ZNK3KJS9RegExpImp16getValuePropertyEPNS_9ExecStateEi -__ZN3KJS9ThrowNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS15StrictEqualNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS19regExpProtoFuncTestEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS9RegExpImp5matchEPNS_9ExecStateERKNS_4ListE -__ZN3KJS15StrictEqualNode17evaluateToBooleanEPNS_9ExecStateE -__ZN3KJS18NotStrictEqualNodeD1Ev -__ZN3KJS15StrictEqualNodeD1Ev -__ZN3KJS18LocalVarTypeOfNodeD1Ev -__ZN3KJS19globalFuncEncodeURIEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS17TypeOfResolveNode8evaluateEPNS_9ExecStateE -__ZN3KJS26stringProtoFuncLastIndexOfEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZNK3KJS7JSValue20toIntegerPreserveNaNEPNS_9ExecStateE -__ZNK3KJS7UString5rfindERKS0_i -__ZN3KJS15TypeOfValueNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS15TypeOfValueNode8evaluateEPNS_9ExecStateE -__ZNK3KJS17FunctionObjectImp19implementsConstructEv -__ZN3KJS17FunctionObjectImp9constructEPNS_9ExecStateERKNS_4ListE -__ZNK3KJS8JSObject11hasPropertyEPNS_9ExecStateERKNS_10IdentifierE -__ZN3KJS30dateProtoFuncGetTimezoneOffsetEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS8JSObject3putEPNS_9ExecStateEjPNS_7JSValueEi -__ZN3KJS6InNodeD1Ev -__ZNK3KJS9Arguments9classInfoEv -__ZN3KJS10BitXOrNode17evaluateToBooleanEPNS_9ExecStateE -__ZN3KJS19addSlowCaseToNumberEPNS_9ExecStateEPNS_7JSValueES3_ -__ZN3KJS8JSObject14deletePropertyEPNS_9ExecStateEj -__ZNK3KJS9WhileNode8streamToERNS_12SourceStreamE -__ZNK3KJS9FalseNode8streamToERNS_12SourceStreamE -__ZNK3KJS7DivNode8streamToERNS_12SourceStreamE -__ZNK3KJS7DivNode10precedenceEv -__ZNK3KJS15StrictEqualNode8streamToERNS_12SourceStreamE -__ZNK3KJS15StrictEqualNode10precedenceEv -__ZNK3KJS16VarDeclCommaNode10precedenceEv -__ZNK3KJS17PreIncResolveNode8streamToERNS_12SourceStreamE -__ZNK3KJS9FalseNode10precedenceEv -__ZN3KJS14InstanceOfNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZNK3KJS19InternalFunctionImp21implementsHasInstanceEv -__ZN3KJS8JSObject11hasInstanceEPNS_9ExecStateEPNS_7JSValueE -__ZN3WTF14FastMallocZone9forceLockEP14_malloc_zone_t -__ZN3KJS25CollectorHeapIntrospector9forceLockEP14_malloc_zone_t -__ZN3WTF14FastMallocZone11forceUnlockEP14_malloc_zone_t -__ZN3KJS25CollectorHeapIntrospector11forceUnlockEP14_malloc_zone_t -__ZNK3KJS23FunctionCallBracketNode10precedenceEv -__ZN3KJS14InstanceOfNode8evaluateEPNS_9ExecStateE -__ZNK3KJS9ThrowNode8streamToERNS_12SourceStreamE -__ZNK3KJS7SubNode10precedenceEv -__ZNK3KJS7SubNode8streamToERNS_12SourceStreamE -__ZNK3KJS10NegateNode10precedenceEv -__ZNK3KJS10NegateNode8streamToERNS_12SourceStreamE -__ZNK3KJS12FuncDeclNode8streamToERNS_12SourceStreamE -__ZNK3KJS18PostDecResolveNode8streamToERNS_12SourceStreamE -__ZNK3KJS9BreakNode8streamToERNS_12SourceStreamE -__ZNK3KJS6InNode10precedenceEv -__ZNK3KJS6InNode8streamToERNS_12SourceStreamE -__ZN3KJS14StringInstanceC2EPNS_8JSObjectERKNS_7UStringE -__ZN3KJS18PostDecBracketNode8evaluateEPNS_9ExecStateE -__ZN3KJS28dateProtoFuncGetMilliSecondsEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZNK3KJS18PostIncResolveNode8streamToERNS_12SourceStreamE -__ZN3KJS13ArrayInstance14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE -__ZN3KJS14StringInstance14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE -__ZN3KJS15AssignErrorNodeD1Ev -__ZN3WTF6VectorIcLm0EE14expandCapacityEmPKc -__ZN3WTF6VectorIcLm0EE14expandCapacityEm -_JSContextGetGlobalObject -_JSClassCreate +__ZN3JSC12JSActivation4markEv +__ZN3JSC9ThrowNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZN3JSC9ThrowNode12releaseNodesERNS_12NodeReleaserE +__ZN3JSC9ThrowNodeD1Ev +__ZNK3JSC21UStringSourceProvider6lengthEv +__ZNK3JSC21UStringSourceProvider4dataEv +__ZN3JSC21UStringSourceProviderD1Ev +__ZN3JSC3JIT26privateCompileGetByIdChainEPNS_17StructureStubInfoEPNS_9StructureEPNS_14StructureChainEmmPvPNS_9ExecStateE +__ZN3JSCL18arrayProtoFuncJoinEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3WTF7HashSetIPN3JSC8JSObjectENS_7PtrHashIS3_EENS_10HashTraitsIS3_EEE3addERKS3_ +__ZN3WTF9HashTableIPN3JSC8JSObjectES3_NS_17IdentityExtractorIS3_EENS_7PtrHashIS3_EENS_10HashTraitsIS3_EES9_E6rehashEi +__ZN3WTF6VectorItLm256EE14expandCapacityEm +__ZN3WTF9HashTableIPN3JSC8JSObjectES3_NS_17IdentityExtractorIS3_EENS_7PtrHashIS3_EENS_10HashTraitsIS3_EES9_E4findIS3_NS_22IdentityHashTranslatorIS3_S3_S7_EEEENS_17HashTableIteratorIS3_S3_S5_S7_S9_S9_EERKT_ +__ZN3JSC3JIT28compileFastArith_op_post_decEjj +__ZN3JSC3JIT27compileFastArith_op_pre_decEj +__ZN3JSC3JIT32compileFastArithSlow_op_post_decEjjRPNS_13SlowCaseEntryE +__ZN3JSC3JIT31compileFastArithSlow_op_pre_decEjRPNS_13SlowCaseEntryE +__ZN3JSCL26stringProtoFuncToUpperCaseEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSC9Arguments4markEv +__ZN3JSC11Interpreter17cti_timeout_checkEPvz +__ZN3JSCL18stringFromCharCodeEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSC17ObjectConstructor16getConstructDataERNS_13ConstructDataE +__ZN3JSCL30constructWithObjectConstructorEPNS_9ExecStateEPNS_8JSObjectERKNS_7ArgListE +__ZN3JSC19JSStaticScopeObject4markEv +__ZN3JSC17NumberConstructor18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE +__ZN3JSC21ThrowableBinaryOpNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZNK3JSC6InNode8opcodeIDEv +__ZN3JSC11Interpreter9cti_op_inEPvz +__ZN3JSC11Interpreter21cti_op_put_by_id_failEPvz +__ZN3JSC17RegExpConstructor3putEPNS_9ExecStateERKNS_10IdentifierENS_10JSValuePtrERNS_15PutPropertySlotE +__ZN3JSC11Interpreter18cti_op_is_functionEPvz +__ZN3JSC18globalFuncIsFiniteEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSCL21arrayProtoFuncForEachEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSCL17arrayProtoFuncMapEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSC12StringObject14toThisJSStringEPNS_9ExecStateE +__ZNK3JSC8JSString12toThisObjectEPNS_9ExecStateE +__ZN3JSCL21arrayProtoFuncIndexOfEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSC13DeleteDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZN3JSC17BytecodeGenerator14emitDeleteByIdEPNS_10RegisterIDES2_RKNS_10IdentifierE +__ZN3JSC13DeleteDotNode12releaseNodesERNS_12NodeReleaserE +__ZN3JSC11Interpreter16cti_op_del_by_idEPvz +__ZN3JSC10JSFunction14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE +__ZN3JSC10JSFunction12callerGetterEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE +__ZNK3JSC11Interpreter14retrieveCallerEPNS_9ExecStateEPNS_16InternalFunctionE +__ZN3JSCL22arrayProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSC16ErrorConstructor16getConstructDataERNS_13ConstructDataE +__ZN3JSCL29constructWithErrorConstructorEPNS_9ExecStateEPNS_8JSObjectERKNS_7ArgListE +__ZN3JSC14constructErrorEPNS_9ExecStateERKNS_7ArgListE +__ZN3JSC12JSActivation3putEPNS_9ExecStateERKNS_10IdentifierENS_10JSValuePtrERNS_15PutPropertySlotE +__ZN3WTF6VectorIN3JSC14MacroAssembler4JumpELm16EE14expandCapacityEm +__ZN3JSC14InstanceOfNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZN3JSC17BytecodeGenerator14emitInstanceOfEPNS_10RegisterIDES2_S2_S2_ +__ZN3JSC14InstanceOfNodeD1Ev +__ZN3JSC11JSImmediate8toObjectENS_10JSValuePtrEPNS_9ExecStateE +__ZNK3JSC12NumberObject9classInfoEv +__ZN3JSC11Interpreter17cti_op_instanceofEPvz +__ZNK3JSC7UString6substrEii +__ZN3JSCL20arrayProtoFuncSpliceEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSC19FunctionConstructor16getConstructDataERNS_13ConstructDataE +__ZN3JSCL32constructWithFunctionConstructorEPNS_9ExecStateEPNS_8JSObjectERKNS_7ArgListE +__ZN3JSC17constructFunctionEPNS_9ExecStateERKNS_7ArgListERKNS_10IdentifierERKNS_7UStringEi +__ZNK3JSC17ExprStatementNode15isExprStatementEv +__ZNK3JSC12FuncExprNode14isFuncExprNodeEv +__ZN3JSC7ArgList9markListsERN3WTF7HashSetIPS0_NS1_7PtrHashIS3_EENS1_10HashTraitsIS3_EEEE +__ZN3JSC9CommaNodeD1Ev +__ZN3JSC11Interpreter12cti_op_throwEPvz +__ZN3JSC11Interpreter14throwExceptionERPNS_9ExecStateERNS_10JSValuePtrEjb +__ZNK3JSC8JSObject22isNotAnObjectErrorStubEv +__ZN3JSC9CodeBlock32expressionRangeForBytecodeOffsetEPNS_9ExecStateEjRiS3_S3_ +__ZNK3JSC8JSObject19isWatchdogExceptionEv +__ZN3JSC9CodeBlock24handlerForBytecodeOffsetEj +__ZN3JSC11Interpreter15unwindCallFrameERPNS_9ExecStateENS_10JSValuePtrERjRPNS_9CodeBlockE +__ZN3JSCL23returnToThrowTrampolineEPNS_12JSGlobalDataEPvRS2_ +__ZN3JSC19ctiSetReturnAddressEPPvS0_ +ctiVMThrowTrampoline +__ZN3JSC11Interpreter12cti_vm_throwEPvz +__ZN3JSC11Interpreter21cti_op_push_new_scopeEPvz +__ZN3JSC19JSStaticScopeObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE +__ZN3JSC9Arguments3putEPNS_9ExecStateERKNS_10IdentifierENS_10JSValuePtrERNS_15PutPropertySlotE +__ZN3JSC4WREC9Generator27generateNonGreedyQuantifierERNS_14MacroAssembler8JumpListERNS0_19GenerateAtomFunctorEjj +__ZN3JSCL21arrayProtoFuncReverseEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSC7UString6appendEPKti +__ZN3JSCL26stringProtoFuncLastIndexOfEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZNK3JSC10JSValuePtr20toIntegerPreserveNaNEPNS_9ExecStateE +__Z22jsc_pcre_ucp_othercasej +__ZN3JSCL24regExpConstructorDollar1EPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE +__ZN3JSCL24regExpConstructorDollar2EPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE +__ZN3JSCL24regExpConstructorDollar3EPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE +__ZN3JSCL24regExpConstructorDollar4EPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE +__ZN3JSCL19dateProtoFuncGetDayEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZNK3JSC19JSStaticScopeObject14isDynamicScopeEv +__ZN3JSCL35objectProtoFuncPropertyIsEnumerableEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZNK3JSC8JSObject21getPropertyAttributesEPNS_9ExecStateERKNS_10IdentifierERj +__ZN3WTF9HashTableIjSt4pairIjN3JSC10JSValuePtrEENS_18PairFirstExtractorIS4_EENS_7IntHashIjEENS_14PairHashTraitsINS_10HashTraitsIjEENSA_IS3_EEEESB_EC2ERKSE_ +__ZN3JSC11Interpreter14cti_op_pre_decEPvz +__ZN3JSC11Interpreter16cti_op_new_arrayEPvz +__ZN3JSC14constructArrayEPNS_9ExecStateERKNS_7ArgListE +__ZN3JSC10JSFunction11getCallDataERNS_8CallDataE +__ZN3JSC4callEPNS_9ExecStateENS_10JSValuePtrENS_8CallTypeERKNS_8CallDataES2_RKNS_7ArgListE +__ZN3JSC11Interpreter7executeEPNS_16FunctionBodyNodeEPNS_9ExecStateEPNS_10JSFunctionEPNS_8JSObjectERKNS_7ArgListEPNS_14ScopeChainNodeEPNS_10JSValuePtrE +__ZN3JSC9LabelNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZN3JSC9LabelNode12releaseNodesERNS_12NodeReleaserE +__ZN3JSC11Interpreter15cti_op_stricteqEPvz +__Z15jsRegExpExecutePK8JSRegExpPKtiiPii +__ZL5matchPKtPKhiR9MatchData +__ZN3JSC18RegExpMatchesArrayC2EPNS_9ExecStateEPNS_24RegExpConstructorPrivateE +__ZN3JSC18RegExpMatchesArray18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE +__ZN3JSC18RegExpMatchesArray17fillArrayInstanceEPNS_9ExecStateE +__ZN3JSC7JSArray18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE +__ZN3JSC12RegExpObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE +__ZN3JSCL19regExpProtoFuncTestEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSC12RegExpObject5matchEPNS_9ExecStateERKNS_7ArgListE +__ZN3JSCL21functionProtoFuncCallEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZNK3JSC8JSString8toObjectEPNS_9ExecStateE +__ZNK3JSC7ArgList8getSliceEiRS0_ +__ZN3JSC17RegExpConstructor18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE +__ZN3JSC23FunctionCallBracketNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZN3JSC23FunctionCallBracketNode12releaseNodesERNS_12NodeReleaserE +__ZN3JSC23FunctionCallBracketNodeD1Ev +__ZN3JSC11Interpreter16cti_op_is_stringEPvz +__ZN3JSC7TryNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZN3JSC17BytecodeGenerator9emitCatchEPNS_10RegisterIDEPNS_5LabelES4_ +__ZN3WTF6VectorIN3JSC11HandlerInfoELm0EE14expandCapacityEm +__ZN3JSC17BytecodeGenerator16emitPushNewScopeEPNS_10RegisterIDERNS_10IdentifierES2_ +__ZN3JSC7TryNode12releaseNodesERNS_12NodeReleaserE +__ZN3WTF6VectorIN3JSC14ExecutablePool10AllocationELm2EE14expandCapacityEm +__ZN3JSC11Interpreter19cti_op_loop_if_lessEPvz +__ZN3JSCL22stringProtoFuncReplaceEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZNK3JSC7UString30spliceSubstringsWithSeparatorsEPKNS0_5RangeEiPKS0_i +__Z15jsc_pcre_xclassiPKh +__ZN3JSC18RegExpMatchesArray3putEPNS_9ExecStateEjNS_10JSValuePtrE +__ZN3JSC7JSArray9setLengthEj +__ZN3JSCL21arrayProtoFuncUnShiftEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSCL19arrayProtoFuncShiftEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSC7JSArray14deletePropertyEPNS_9ExecStateEj +__ZN3JSC11Interpreter19cti_op_is_undefinedEPvz +__ZNK3JSC9Arguments9classInfoEv +__ZN3JSC9Arguments11fillArgListEPNS_9ExecStateERNS_7ArgListE +__ZN3JSC11Interpreter23cti_op_create_argumentsEPvz +__ZN3JSC17PropertyNameArray3addEPNS_7UString3RepE +__ZN3WTF7HashSetIPN3JSC7UString3RepENS_7PtrHashIS4_EENS_10HashTraitsIS4_EEE3addERKS4_ +__ZN3WTF9HashTableIPN3JSC7UString3RepES4_NS_17IdentityExtractorIS4_EENS_7PtrHashIS4_EENS_10HashTraitsIS4_EESA_E6expandEv +__ZN3WTF6VectorIN3JSC10IdentifierELm20EE14expandCapacityEm +__ZN3JSC11Interpreter19cti_op_convert_thisEPvz +__ZN3JSC17PrefixBracketNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZN3JSC17PrefixBracketNodeD1Ev +__ZN3JSC17PrefixBracketNode12releaseNodesERNS_12NodeReleaserE +__ZN3JSCL25functionProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZNK3JSC10JSFunction9classInfoEv +__ZN3JSC7CStringD1Ev +__ZN3JSC6JSLock12DropAllLocksC1Eb +__ZN3JSCL17createJSLockCountEv +__ZN3JSC6JSLock12DropAllLocksD1Ev +__ZN3JSC26createNotAnObjectErrorStubEPNS_9ExecStateEb +__ZN3JSC13JSNotAnObject3putEPNS_9ExecStateERKNS_10IdentifierENS_10JSValuePtrERNS_15PutPropertySlotE +__ZNK3JSC22JSNotAnObjectErrorStub22isNotAnObjectErrorStubEv +__ZN3JSC22createNotAnObjectErrorEPNS_9ExecStateEPNS_22JSNotAnObjectErrorStubEjPNS_9CodeBlockE +__ZN3JSC9CodeBlock37getByIdExceptionInfoForBytecodeOffsetEPNS_9ExecStateEjRNS_8OpcodeIDE +__ZN3JSCL18createErrorMessageEPNS_9ExecStateEPNS_9CodeBlockEiiiNS_10JSValuePtrENS_7UStringE +__ZNK3JSC7UString5asciiEv +__ZN3JSC16InternalFunctionC2EPNS_12JSGlobalDataEN3WTF10PassRefPtrINS_9StructureEEERKNS_10IdentifierE +__ZN3WTF13tryFastCallocEmm +__ZN3JSC13JSNotAnObjectD0Ev +__ZN3JSCL31dateProtoFuncToLocaleTimeStringEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSCL16formatLocaleDateEPNS_9ExecStateEPNS_12DateInstanceEdNS_20LocaleDateTimeFormatERKNS_7ArgListE +__ZN3JSC16InternalFunction4nameEPNS_12JSGlobalDataE +__ZNK3JSC6JSCell9getStringERNS_7UStringE +__ZN3JSC28globalFuncDecodeURIComponentEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZNK3JSC14ExpressionNode8isStringEv +__ZN3JSC17RegExpConstructor11getCallDataERNS_8CallDataE +__ZN3JSCL21callRegExpConstructorEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSC23createNotAFunctionErrorEPNS_9ExecStateENS_10JSValuePtrEjPNS_9CodeBlockE +__ZN3JSC11Interpreter17cti_op_jmp_scopesEPvz +__ZN3JSC17BytecodeGenerator18emitJumpSubroutineEPNS_10RegisterIDEPNS_5LabelE +__ZN3WTF6VectorIN3JSC3JIT7JSRInfoELm0EE14expandCapacityEm +__ZN3JSC18RegExpMatchesArray16getPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayE +__ZN3JSC28createUndefinedVariableErrorEPNS_9ExecStateERKNS_10IdentifierEjPNS_9CodeBlockE +__ZN3JSC17DeleteResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZN3JSCL21stringProtoFuncSearchEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSCL27objectProtoFuncDefineGetterEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSC8JSObject12defineGetterEPNS_9ExecStateERKNS_10IdentifierEPS0_ +__ZN3JSC9Structure22getterSetterTransitionEPS0_ +__ZN3JSCL27objectProtoFuncLookupGetterEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSC8JSObject12lookupGetterEPNS_9ExecStateERKNS_10IdentifierE +__ZNK3JSC6JSCell14isGetterSetterEv +__ZN3JSCL27objectProtoFuncLookupSetterEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSC8JSObject12lookupSetterEPNS_9ExecStateERKNS_10IdentifierE +__ZN3JSC10JSFunction12lengthGetterEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE +__ZN3JSCL27objectProtoFuncDefineSetterEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSC8JSObject12defineSetterEPNS_9ExecStateERKNS_10IdentifierEPS0_ +__ZNK3JSC12GetterSetter14isGetterSetterEv +__ZN3JSC12GetterSetter4markEv +__ZN3JSC16JSVariableObject14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE +__ZNK3JSC8JSObject11hasPropertyEPNS_9ExecStateEj +__ZN3JSC17BytecodeGenerator21emitComplexJumpScopesEPNS_5LabelEPNS_18ControlFlowContextES4_ +__ZN3JSC8JSObject22fillGetterPropertySlotERNS_12PropertySlotEPNS_10JSValuePtrE +__ZN3JSC12PropertySlot14functionGetterEPNS_9ExecStateERKNS_10IdentifierERKS0_ +__ZN3JSC7JSArray4sortEPNS_9ExecStateE +__ZN3JSC7JSArray17compactForSortingEv +__ZN3JSCL24booleanProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSC8VoidNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZN3JSC8VoidNodeD1Ev +__ZN3JSC8VoidNode12releaseNodesERNS_12NodeReleaserE +__ZN3JSC13JSNotAnObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE +__ZN3JSC12StringObject18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE +__ZN3JSCL27compareByStringPairForQSortEPKvS1_ +__ZN3JSC6Parser7reparseINS_8EvalNodeEEEN3WTF10PassRefPtrIT_EEPNS_12JSGlobalDataEPS5_ +__ZN3JSC8EvalNode6createEPNS_12JSGlobalDataEPNS_14SourceElementsEPN3WTF6VectorISt4pairINS_10IdentifierEjELm0EEEPNS6_INS5_6RefPtrINS_12FuncDeclNodeEEELm0EEERKNS_10SourceCodeEji +__ZN3JSC8EvalNode31bytecodeForExceptionInfoReparseEPNS_14ScopeChainNodeEPNS_9CodeBlockE +__ZN3JSC17NumberConstructor16getConstructDataERNS_13ConstructDataE +__ZN3JSCL30constructWithNumberConstructorEPNS_9ExecStateEPNS_8JSObjectERKNS_7ArgListE +__ZNK3JSC8JSObject16isVariableObjectEv +__ZN3JSC36constructBooleanFromImmediateBooleanEPNS_9ExecStateENS_10JSValuePtrE +__ZN3JSC13BooleanObjectD0Ev +__ZN3WTF9HashTableINS_6RefPtrIN3JSC7UString3RepEEESt4pairIS5_NS2_14OffsetLocationEENS_18PairFirstExtractorIS8_EENS_7StrHashIS5_EENS_14PairHashTraitsINS_10HashTraitsIS5_EENSE_IS7_EEEESF_E4findIPS4_NS_29RefPtrHashMapRawKeyTranslatorISK_S8_SH_SC_EEEENS_17HashTableIteratorIS5_S8_SA_SC_SH_SF_EERKT_ +__ZN3JSC10throwErrorEPNS_9ExecStateENS_9ErrorTypeE +__ZN3JSC14globalFuncEvalEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSC11Interpreter7executeEPNS_8EvalNodeEPNS_9ExecStateEPNS_8JSObjectEPNS_14ScopeChainNodeEPNS_10JSValuePtrE +__ZN3JSC11Interpreter19cti_op_put_by_indexEPvz +__ZN3JSCL25numberConstructorMaxValueEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE +__ZN3JSCL28numberConstructorPosInfinityEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE +__ZN3JSCL28numberConstructorNegInfinityEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE +__ZN3JSCL17mathProtoFuncATanEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSC18RegExpMatchesArray14deletePropertyEPNS_9ExecStateEj +__ZN3JSC18RegExpMatchesArray3putEPNS_9ExecStateERKNS_10IdentifierENS_10JSValuePtrERNS_15PutPropertySlotE +__ZN3JSC7JSArray14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE +__ZN3JSC18EmptyStatementNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZN3JSCL17mathProtoFuncASinEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSCL18mathProtoFuncATan2EPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSC16ErrorConstructor11getCallDataERNS_8CallDataE +__ZN3JSCL20callErrorConstructorEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSCL7dateNowEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSC18BooleanConstructor11getCallDataERNS_8CallDataE +__ZN3JSCL22callBooleanConstructorEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSCL20arrayProtoFuncFilterEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSC4WREC9Generator28generateParenthesesAssertionERNS_14MacroAssembler8JumpListE +__ZN3JSCL21regExpObjectLastIndexEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE +__ZN3JSCL18arrayProtoFuncSomeEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSC12RegExpObject3putEPNS_9ExecStateERKNS_10IdentifierENS_10JSValuePtrERNS_15PutPropertySlotE +__ZN3JSCL24setRegExpObjectLastIndexEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrE +__ZN3JSC26createNotAConstructorErrorEPNS_9ExecStateENS_10JSValuePtrEjPNS_9CodeBlockE +__ZN3JSC15isStrWhiteSpaceEt +__ZN3JSCL27dateProtoFuncGetUTCFullYearEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSCL24dateProtoFuncGetUTCMonthEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSCL23dateProtoFuncGetUTCDateEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSCL24dateProtoFuncGetUTCHoursEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSCL26dateProtoFuncGetUTCMinutesEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSCL7dateUTCEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSCL21dateProtoFuncSetHoursEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSCL23setNewValueFromTimeArgsEPNS_9ExecStateENS_10JSValuePtrERKNS_7ArgListEib +__ZN3JSCL23dateProtoFuncSetMinutesEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSCL23dateProtoFuncSetSecondsEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSCL28dateProtoFuncSetMilliSecondsEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSC7CStringaSERKS0_ +__ZN3JSCL22dateProtoFuncGetUTCDayEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZNK3JSC7UString8toUInt32EPb +__ZN3JSC12RegExpObject11getCallDataERNS_8CallDataE +__ZNK3JSC8JSObject14isGlobalObjectEv +__ZN3JSC8JSString18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE +__ZN3JSC8JSObject18getPrimitiveNumberEPNS_9ExecStateERdRNS_10JSValuePtrE +__ZN3JSC10throwErrorEPNS_9ExecStateENS_9ErrorTypeEPKc +__ZN3JSC16JSVariableObject16getPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayE +__ZN3JSC17BytecodeGenerator18emitUnexpectedLoadEPNS_10RegisterIDEb +__ZN3WTF6VectorIN3JSC10JSValuePtrELm0EE14expandCapacityEm +__ZN3JSC18BooleanConstructor16getConstructDataERNS_13ConstructDataE +__ZN3JSCL31constructWithBooleanConstructorEPNS_9ExecStateEPNS_8JSObjectERKNS_7ArgListE +__ZN3JSC16constructBooleanEPNS_9ExecStateERKNS_7ArgListE +__ZN3JSCL26stringFromCharCodeSlowCaseEPNS_9ExecStateERKNS_7ArgListE +__ZN3JSCL27dateProtoFuncSetUTCFullYearEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSCL26dateProtoFuncGetUTCSecondsEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSCL31dateProtoFuncGetUTCMillisecondsEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSCL28dateProtoFuncGetMilliSecondsEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZNK3JSC12JSNumberCell9getUInt32ERj +__ZN3JSC13JSNotAnObject18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE +__ZN3JSCL23booleanProtoFuncValueOfEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSCL27dateProtoFuncToLocaleStringEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSC9Arguments14deletePropertyEPNS_9ExecStateEj +__ZNK3JSC21UStringSourceProvider8getRangeEii +__ZN3JSC22NativeErrorConstructor11getCallDataERNS_8CallDataE +__ZN3JSCL23dateProtoFuncSetUTCDateEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +JSClassCreate __ZN13OpaqueJSClass6createEPK17JSClassDefinition __ZN13OpaqueJSClassC2EPK17JSClassDefinitionPS_ -_JSClassRetain -_JSObjectMake -__ZN13OpaqueJSClass9prototypeEPK15OpaqueJSContext -__ZN3KJS16JSCallbackObjectINS_8JSObjectEE4initEPNS_9ExecStateE -_JSStringCreateWithUTF8CString -_JSObjectSetProperty -_JSStringRelease -__Z30makeGetterOrSetterPropertyNodeRKN3KJS10IdentifierES2_PNS_13ParameterNodeEPNS_16FunctionBodyNodeE -__ZN3KJS8JSObject12defineGetterEPNS_9ExecStateERKNS_10IdentifierEPS0_ -__ZN3KJS8JSObject12defineSetterEPNS_9ExecStateERKNS_10IdentifierEPS0_ -__ZNK3KJS15GetterSetterImp4typeEv -__ZNK3KJS8JSObject6canPutEPNS_9ExecStateERKNS_10IdentifierE -__ZN3KJS13ConstDeclNodeC1ERKNS_10IdentifierEPNS_14ExpressionNodeE -__Z26appendToVarDeclarationListRPN3KJS20ParserRefCountedDataIN3WTF6VectorISt4pairINS_10IdentifierEjELm16EEEEEPNS_13ConstDeclNodeE -__ZN3KJS18ConstStatementNodeC1EPNS_13ConstDeclNodeE -__ZN3KJS16JSCallbackObjectINS_8JSObjectEE18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE -__ZN3KJS16JSCallbackObjectINS_8JSObjectEE20staticFunctionGetterEPNS_9ExecStateEPS1_RKNS_10IdentifierERKNS_12PropertySlotE -__ZN3KJS18JSCallbackFunctionC1EPNS_9ExecStateEPFPK13OpaqueJSValuePK15OpaqueJSContextPS3_S9_mPKS5_PS5_ERKNS_10IdentifierE -__ZN3KJS18JSCallbackFunction14callAsFunctionEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -_JSObjectGetPrivate -__ZNK3KJS16JSCallbackObjectINS_8JSObjectEE9classInfoEv -_JSStringCreateWithCharacters -_JSValueMakeString -__ZN3KJS12PropertySlot14functionGetterEPNS_9ExecStateEPNS_8JSObjectERKNS_10IdentifierERKS0_ -__ZN3WTF10fastCallocEmm -_JSObjectGetProperty -_JSValueToObject -_JSValueProtect -_JSObjectCallAsFunction -_JSValueMakeNumber -_JSValueMakeBoolean -_JSObjectCallAsConstructor -__ZN3KJS15GetterSetterImp4markEv -_JSValueMakeUndefined -_JSValueUnprotect -_JSValueIsNumber -_JSValueToNumber -__ZN3KJS16JSCallbackObjectINS_8JSObjectEED0Ev -__Z25clearReferenceToPrototypeP13OpaqueJSValue -_JSClassRelease -_JSStringIsEqualToUTF8CString -_JSStringIsEqual -__ZN3KJSeqERKNS_7UStringES2_ -__ZN3KJS16JSCallbackObjectINS_8JSObjectEE14callbackGetterEPNS_9ExecStateEPS1_RKNS_10IdentifierERKNS_12PropertySlotE -_JSStringCreateWithCFString -__ZN3KJS7UStringC2EPNS_5UCharEib -__ZN3KJS16JSCallbackObjectINS_8JSObjectEE3putEPNS_9ExecStateERKNS_10IdentifierEPNS_7JSValueEi -_JSObjectSetPrivate -__ZN3KJS15GetterSetterImpD0Ev -__ZN3KJS27objectProtoFuncLookupGetterEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZNK3KJS17PreIncResolveNode10precedenceEv -__ZNK3KJS10SwitchNode8streamToERNS_12SourceStreamE -__ZNK3KJS13CaseBlockNode8streamToERNS_12SourceStreamE -__ZNK3KJS14CaseClauseNode8streamToERNS_12SourceStreamE -__ZN3KJS18ConstStatementNodeD1Ev -__ZN3KJS17PreDecBracketNodeD1Ev -__ZN3KJS11Interpreter24setShouldPrintExceptionsEb -__ZN3KJS9Collector26protectedGlobalObjectCountEv -__ZN3KJS9Collector4sizeEv -__ZN3KJS9Collector17globalObjectCountEv -__ZN3KJS9Collector20protectedObjectCountEv -__ZN3KJS9Collector25protectedObjectTypeCountsEv -__ZNK3KJS15NumberObjectImp9classInfoEv -__ZNK3KJS15RegExpPrototype9classInfoEv -__ZNK3KJS15RegExpObjectImp9classInfoEv -__ZNK3KJS14NativeErrorImp9classInfoEv -__ZNK3KJS13MathObjectImp9classInfoEv -__ZN3WTF6VectorIPN3KJS7JSValueELm8EE14expandCapacityEmPKS3_ -__ZN3WTF6VectorIPN3KJS7JSValueELm8EE14expandCapacityEm -__ZN3KJS15ConditionalNode15evaluateToInt32EPNS_9ExecStateE -__ZN3KJS9Arguments14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE -__ZNK3KJS17DeleteBracketNode8streamToERNS_12SourceStreamE -__ZNK3KJS9BitOrNode10precedenceEv -__ZNK3KJS9BitOrNode8streamToERNS_12SourceStreamE -__ZNK3KJS7ModNode10precedenceEv -__ZNK3KJS7ModNode8streamToERNS_12SourceStreamE -__ZN3KJS31dateProtoFuncToLocaleTimeStringEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS16formatLocaleDateEPNS_9ExecStateEdbbRKNS_4ListE -__ZN3KJS31dateProtoFuncToLocaleDateStringEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS9BitOrNode17evaluateToBooleanEPNS_9ExecStateE -__ZN3KJS7DivNode15evaluateToInt32EPNS_9ExecStateE -__ZN3KJS14BitwiseNotNode16evaluateToUInt32EPNS_9ExecStateE -__ZN3KJS13ActivationImp14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE -__ZN3KJS27objectProtoFuncDefineGetterEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS17PreDecBracketNode8evaluateEPNS_9ExecStateE -__ZNK3KJS16BooleanObjectImp19implementsConstructEv -__ZN3KJS27objectProtoFuncDefineSetterEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS8JSObject22fillGetterPropertySlotERNS_12PropertySlotEPPNS_7JSValueE -__ZN3KJS10StringNode17evaluateToBooleanEPNS_9ExecStateE -__ZN3KJS13UnaryPlusNode16evaluateToNumberEPNS_9ExecStateE -__ZN3KJS31dateProtoFuncGetUTCMillisecondsEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS17FunctionObjectImp14callAsFunctionEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS15DeleteValueNodeD1Ev -__ZN3KJS15RegExpObjectImp14callAsFunctionEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS22dateProtoFuncGetUTCDayEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS8MultNode15evaluateToInt32EPNS_9ExecStateE -__ZN3KJS4Node18setErrorCompletionEPNS_9ExecStateENS_9ErrorTypeEPKc -__ZN3KJS10StringNode16evaluateToNumberEPNS_9ExecStateE -__ZN3KJS27dateProtoFuncToLocaleStringEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS22UnsignedRightShiftNode16evaluateToNumberEPNS_9ExecStateE -__ZNK3KJS18PostIncResolveNode10precedenceEv -__ZNK3KJS21ReadModifyResolveNode10precedenceEv -__ZNK3KJS21FunctionCallValueNode10precedenceEv -__ZN3KJS4Node15handleExceptionEPNS_9ExecStateE -__ZNK3KJS13UnaryPlusNode10precedenceEv -__ZNK3KJS13UnaryPlusNode8streamToERNS_12SourceStreamE -__ZN3KJS4Node10throwErrorEPNS_9ExecStateENS_9ErrorTypeEPKcPNS_7JSValueERKNS_10IdentifierE -__ZNK3KJS15DotAccessorNode17isDotAccessorNodeEv -__ZNK3KJS14PostfixDotNode10precedenceEv -__ZN3KJS23regExpProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZNK3KJS14PostDecDotNode8streamToERNS_12SourceStreamE -__ZNK3KJS9CommaNode10precedenceEv -__ZNK3KJS17ReadModifyDotNode10precedenceEv -__ZNK3KJS13DeleteDotNode8streamToERNS_12SourceStreamE -__ZNK3KJS19PlaceholderTrueNode8streamToERNS_12SourceStreamE -__ZNK3KJS17AssignBracketNode10precedenceEv -__ZNK3KJS8WithNode8streamToERNS_12SourceStreamE -__ZNK3KJS17DeleteBracketNode10precedenceEv -__ZN3KJS15ObjectObjectImp14callAsFunctionEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -_KJS_JSCreateNativeJSObject -__ZN3KJS8Bindings12JavaJSObject6invokeEPNS0_19JSObjectCallContextE -__ZN3KJS8Bindings12JavaJSObject12createNativeEx -__ZN3KJS8Bindings24findProtectingRootObjectEPNS_8JSObjectE -_KJS_JSObject_JSObjectEval -__ZN3KJS8Bindings12JavaJSObjectC1Ex -__ZNK3KJS8Bindings12JavaJSObject4evalEP8_jstring -__ZN3KJS8Bindings9getJNIEnvEv -__ZN3KJS8Bindings9getJavaVMEv -__ZN3KJS8Bindings30getUCharactersFromJStringInEnvEP7JNIEnv_P8_jstring -__ZN3KJS8Bindings33releaseUCharactersForJStringInEnvEP7JNIEnv_P8_jstringPKt -__ZNK3KJS8Bindings12JavaJSObject21convertValueToJObjectEPNS_7JSValueE -__ZN7JNIEnv_9NewObjectEP7_jclassP10_jmethodIDz -_KJS_JSObject_JSFinalize -__ZN3KJS19stringProtoFuncBoldEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZNK3KJS15RegExpObjectImp15getRightContextEv -__ZNK3KJS15RegExpObjectImp14getLeftContextEv -__ZN3KJS13LeftShiftNode16evaluateToUInt32EPNS_9ExecStateE -__ZN3KJS7ModNode15evaluateToInt32EPNS_9ExecStateE -__ZNK3KJS18PostDecResolveNode10precedenceEv -__ZN3KJS28dateProtoFuncSetMilliSecondsEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS32stringProtoFuncToLocaleLowerCaseEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__NPN_SetException -__ZN3KJS18mathProtoFuncATan2EPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS8Bindings12JavaInstanceC2EP8_jobjectN3WTF10PassRefPtrINS0_10RootObjectEEE -__ZN3KJS8Bindings12JavaInstance5beginEv -__ZNK3KJS8Bindings12JavaInstance8getClassEv -__ZN3KJS8Bindings9JavaClassC2EP8_jobject -__ZN3KJS8Bindings19callJNIObjectMethodEP8_jobjectPKcS4_z -__ZN3KJS8Bindings13callJNIMethodE7JNITypeP8_jobjectPKcS5_Pc -__ZN3KJS8Bindings24getCharactersFromJStringEP8_jstring -__ZN3KJS8Bindings27releaseCharactersForJStringEP8_jstringPKc -__ZN3KJS8Bindings9JavaFieldC2EP7JNIEnv_P8_jobject -__ZN3KJS7CStringaSERKS0_ -__ZN3KJS8Bindings20JNITypeFromClassNameEPKc -__ZN3KJS8Bindings14JObjectWrapperC1EP8_jobject -__ZNK3KJS8Bindings9JavaField4nameEv -__ZN3KJS8Bindings10JavaMethodC2EP7JNIEnv_P8_jobject -__ZN3KJS8Bindings16callJNIIntMethodEP8_jobjectPKcS4_z -__ZN3KJS8Bindings26callJNIStaticBooleanMethodEP7_jclassPKcS4_z -__ZN3KJS8Bindings19callJNIStaticMethodE7JNITypeP7_jclassPKcS5_Pc -__ZNK3KJS8Bindings10JavaMethod4nameEv -__ZN3KJS8Bindings13JavaParameterC2EP7JNIEnv_P8_jstring -__ZNK3KJS8Bindings9JavaClass10fieldNamedERKNS_10IdentifierEPNS0_8InstanceE -__ZNK3KJS8Bindings9JavaClass12methodsNamedERKNS_10IdentifierEPNS0_8InstanceE -__ZN3KJS8Bindings12JavaInstance3endEv -__ZN3KJS8Bindings12JavaInstanceD1Ev -__ZN3KJS8Bindings9JavaClassD1Ev -__ZN3WTF20deleteAllPairSecondsIPN3KJS8Bindings5FieldEKNS_7HashMapINS_6RefPtrINS1_7UString3RepEEES4_NS_7PtrHashIS9_EENS_10HashTraitsIS9_EENSC_IS4_EEEEEEvRT0_ -__ZN3KJS8Bindings14JObjectWrapperD1Ev -__ZN3KJS35objectProtoFuncPropertyIsEnumerableEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS31dateProtoFuncSetUTCMillisecondsEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZNK3KJS12FuncExprNode21needsParensIfLeftmostEv -__ZN3KJS13DateObjectImp14callAsFunctionEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS11NewExprNode17evaluateToBooleanEPNS_9ExecStateE -__ZN3KJS29numberProtoFuncToLocaleStringEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS25dateProtoFuncToDateStringEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS9BitOrNode16evaluateToNumberEPNS_9ExecStateE -__ZNK3KJS7JSValue8toUInt32EPNS_9ExecStateE -__ZNK3KJS8JSObject3getEPNS_9ExecStateEj -__ZNK3KJS7JSValue16toUInt32SlowCaseEPNS_9ExecStateERb -__ZN3KJS9Collector29markOtherThreadConservativelyEPNS0_6ThreadE -__ZN3WTF20TCMalloc_ThreadCache18DestroyThreadCacheEPv -__ZN3WTF20TCMalloc_ThreadCache11DeleteCacheEPS0_ -__ZN3KJS23destroyRegisteredThreadEPv -__ZN3KJS28numberProtoFuncToExponentialEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS26numberProtoFuncToPrecisionEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS15RegExpObjectImp16putValuePropertyEPNS_9ExecStateEiPNS_7JSValueEi -__ZNK3KJS15RegExpObjectImp12getLastParenEv -__ZN3KJS10throwErrorEPNS_9ExecStateENS_9ErrorTypeE -__ZN3KJS18arrayProtoFuncSomeEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS9LabelNode9pushLabelERKNS_10IdentifierE -__ZN3KJS9Collector32reportOutOfMemoryToAllExecStatesEv -__ZN3KJS5Error6createEPNS_9ExecStateENS_9ErrorTypeEPKc -__ZNK3KJS17PreDecResolveNode10precedenceEv -__ZN3KJS17mathProtoFuncACosEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS16mathProtoFuncTanEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZNK3KJS16PostfixErrorNode8streamToERNS_12SourceStreamE -__ZNK3KJS15PrefixErrorNode8streamToERNS_12SourceStreamE -__ZNK3KJS15AssignErrorNode8streamToERNS_12SourceStreamE -__ZN3KJS16PostfixErrorNode8evaluateEPNS_9ExecStateE -__ZN3KJS4Node10throwErrorEPNS_9ExecStateENS_9ErrorTypeEPKcS5_ -__ZN3KJS16PostfixErrorNodeD1Ev -__ZNK3KJS13LeftShiftNode8streamToERNS_12SourceStreamE -__ZNK3KJS13LeftShiftNode10precedenceEv -__ZNK3KJS14RightShiftNode8streamToERNS_12SourceStreamE -__ZNK3KJS14RightShiftNode10precedenceEv -__ZNK3KJS22UnsignedRightShiftNode8streamToERNS_12SourceStreamE -__ZNK3KJS22UnsignedRightShiftNode10precedenceEv -__ZNK3KJS10BitAndNode8streamToERNS_12SourceStreamE -__ZNK3KJS10BitAndNode10precedenceEv -__ZNK3KJS10BitXOrNode8streamToERNS_12SourceStreamE -__ZNK3KJS10BitXOrNode10precedenceEv -__ZN3KJS15AssignErrorNode8evaluateEPNS_9ExecStateE -__ZN3KJS4Node10throwErrorEPNS_9ExecStateENS_9ErrorTypeEPKc -__ZN3KJS13char_sequenceEci -__ZN3KJS15LessStringsNode8evaluateEPNS_9ExecStateE -__ZN3KJS15LessStringsNodeD1Ev -__ZN3KJS15DeleteValueNode8evaluateEPNS_9ExecStateE -__ZN3KJS22regExpProtoFuncCompileEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS15PrefixErrorNode8evaluateEPNS_9ExecStateE -__ZN3KJS28objectProtoFuncIsPrototypeOfEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS15PrefixErrorNodeD1Ev -__ZN3KJS19arrayProtoFuncEveryEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS29objectProtoFuncToLocaleStringEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS25arrayProtoFuncLastIndexOfEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3WTF6VectorItLm0EE6resizeEm -__ZN3WTF6VectorItLm0EE14expandCapacityEm -__ZN3WTF6VectorItLm0EE15reserveCapacityEm -__ZN3KJS28arrayProtoFuncToLocaleStringEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS18ConstStatementNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS13ConstDeclNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE -__ZN3KJS18ConstStatementNode7executeEPNS_9ExecStateE -__ZN3KJS13ConstDeclNode8evaluateEPNS_9ExecStateE -__ZN3KJS15AssignConstNode8evaluateEPNS_9ExecStateE -__ZN3KJS16PostIncConstNode8evaluateEPNS_9ExecStateE -__ZN3KJS16PostDecConstNode8evaluateEPNS_9ExecStateE -__ZN3KJS15PreIncConstNode8evaluateEPNS_9ExecStateE -__ZN3KJS15PreDecConstNode8evaluateEPNS_9ExecStateE -__ZN3KJS19ReadModifyConstNode8evaluateEPNS_9ExecStateE -__ZNK3KJS13ActivationImp9classInfoEv -__ZN3KJS16PostIncConstNodeD1Ev -__ZN3KJS15PreIncConstNodeD1Ev -__ZN3KJS15PreDecConstNodeD1Ev -__ZNK3KJS13DeleteDotNode10precedenceEv -__ZN3KJS28stringProtoFuncLocaleCompareEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZN3KJS10NumberNode16evaluateToUInt32EPNS_9ExecStateE -__ZN3KJS19FunctionCallDotNode16evaluateToUInt32EPNS_9ExecStateE -__ZNK3KJS21ReadModifyBracketNode8streamToERNS_12SourceStreamE -__ZN3KJS10BitXOrNode16evaluateToNumberEPNS_9ExecStateE -___tcf_1 -__ZNK3KJS7UString6is8BitEv -__ZN3KJS15DotAccessorNode16evaluateToUInt32EPNS_9ExecStateE -__ZN3KJS24stringProtoFuncFontcolorEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE -__ZNK3KJS14NativeErrorImp19implementsConstructEv -__ZN3KJS19PostDecLocalVarNode16evaluateToNumberEPNS_9ExecStateE -__ZN3KJS19PostDecLocalVarNode15evaluateToInt32EPNS_9ExecStateE -__ZN3KJS13UnaryPlusNode17evaluateToBooleanEPNS_9ExecStateE +__ZN3JSC7UString3Rep14createFromUTF8EPKc +__ZN3WTF7Unicode18convertUTF8ToUTF16EPPKcS2_PPtS4_b +__ZN3WTF7HashMapINS_6RefPtrIN3JSC7UString3RepEEEP19StaticFunctionEntryNS_7StrHashIS5_EENS_10HashTraitsIS5_EENSA_IS7_EEE3addERKS5_RKS7_ +__ZN3WTF9HashTableINS_6RefPtrIN3JSC7UString3RepEEESt4pairIS5_P19StaticFunctionEntryENS_18PairFirstExtractorIS9_EENS_7StrHashIS5_EENS_14PairHashTraitsINS_10HashTraitsIS5_EENSF_IS8_EEEESG_E6expandEv +JSClassRetain +JSObjectMake +__ZN3JSC4Heap14registerThreadEv +__ZN3JSC6JSLockC1EPNS_9ExecStateE +__ZN3JSC16JSCallbackObjectINS_8JSObjectEE4initEPNS_9ExecStateE +__ZN13OpaqueJSClass9prototypeEPN3JSC9ExecStateE +__ZN13OpaqueJSClass11contextDataEPN3JSC9ExecStateE +__ZN3WTF9HashTableIP13OpaqueJSClassSt4pairIS2_P24OpaqueJSClassContextDataENS_18PairFirstExtractorIS6_EENS_7PtrHashIS2_EENS_14PairHashTraitsINS_10HashTraitsIS2_EENSC_IS5_EEEESD_E6expandEv +__ZN24OpaqueJSClassContextDataC2EP13OpaqueJSClass +JSStringCreateWithCFString +JSObjectSetProperty +__ZNK14OpaqueJSString10identifierEPN3JSC12JSGlobalDataE +JSStringRelease +__ZL30makeGetterOrSetterPropertyNodePvRKN3JSC10IdentifierES3_PNS0_13ParameterNodeEPNS0_16FunctionBodyNodeERKNS0_10SourceCodeE +__ZN3JSC18ConstStatementNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZN3JSC13ConstDeclNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZN3JSC13ConstDeclNode14emitCodeSingleERNS_17BytecodeGeneratorE +__ZN3JSC17BytecodeGenerator13emitPutGetterEPNS_10RegisterIDERKNS_10IdentifierES2_ +__ZN3JSC17BytecodeGenerator13emitPutSetterEPNS_10RegisterIDERKNS_10IdentifierES2_ +__ZN3JSC18ConstStatementNodeD1Ev +__ZN3JSC18ConstStatementNode12releaseNodesERNS_12NodeReleaserE +__ZN3JSC13ConstDeclNode12releaseNodesERNS_12NodeReleaserE +__ZN3JSC11Interpreter17cti_op_put_getterEPvz +__ZN3JSC11Interpreter17cti_op_put_setterEPvz +__ZN3JSC16JSCallbackObjectINS_8JSObjectEE18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE +__ZN3JSC7UString3Rep13createCopyingEPKti +__ZN3JSC16JSCallbackObjectINS_8JSObjectEE20staticFunctionGetterEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE +__ZN3JSC18JSCallbackFunctionC1EPNS_9ExecStateEPFPK13OpaqueJSValuePK15OpaqueJSContextPS3_S9_mPKS5_PS5_ERKNS_10IdentifierE +__ZN3JSC18JSCallbackFunction11getCallDataERNS_8CallDataE +__ZN3JSC18JSCallbackFunction4callEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSC6JSLock12DropAllLocksC1EPNS_9ExecStateE +JSValueIsObjectOfClass +__ZN3JSC6JSCell9getObjectEv +__ZNK3JSC16JSCallbackObjectINS_8JSObjectEE9classInfoEv +JSObjectGetPrivate +JSValueMakeString +__ZNK14OpaqueJSString7ustringEv +JSValueMakeBoolean +JSContextGetGlobalObject +JSStringCreateWithUTF8CString +JSObjectGetProperty +JSValueToObject +JSObjectIsFunction +JSObjectCallAsFunction +JSValueMakeUndefined +__ZN3JSC18JSCallbackFunctionD0Ev +__ZN3JSC16JSCallbackObjectINS_8JSObjectEED0Ev +__ZL25clearReferenceToPrototypeP13OpaqueJSValue +JSClassRelease +__ZN3JSC15AssignErrorNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZN3JSC23ThrowableExpressionData14emitThrowErrorERNS_17BytecodeGeneratorENS_9ErrorTypeEPKc +__ZN3JSC17BytecodeGenerator12emitNewErrorEPNS_10RegisterIDENS_9ErrorTypeENS_10JSValuePtrE +__ZN3JSC15AssignErrorNodeD1Ev +__ZN3JSC15AssignErrorNode12releaseNodesERNS_12NodeReleaserE +__ZN3JSC12StringObject14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE +__ZN3JSC12StringObject16getPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayE +__ZN3JSC9ExecState11stringTableEPS0_ +__ZN3JSCL24dateProtoFuncSetUTCHoursEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN14OpaqueJSString6createERKN3JSC7UStringE +JSStringIsEqualToUTF8CString +__ZN3JSC16JSCallbackObjectINS_8JSObjectEE14callbackGetterEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE +JSValueToStringCopy +JSStringCopyCFString +JSValueMakeNumber +__ZN3JSC16JSCallbackObjectINS_8JSObjectEE3putEPNS_9ExecStateERKNS_10IdentifierENS_10JSValuePtrERNS_15PutPropertySlotE +JSValueToNumber +JSObjectSetPrivate +__ZN3JSC8Profiler8profilerEv +__ZN3JSC8Profiler13stopProfilingEPNS_9ExecStateERKNS_7UStringE +__ZN3JSC8JSObject15unwrappedObjectEv +JSStringCreateWithCharacters +__ZN3JSC9Structure18startIgnoringLeaksEv +__ZN3JSC9Structure17stopIgnoringLeaksEv +JSValueProtect +JSObjectCallAsConstructor +__ZN3JSC10JSFunction16getConstructDataERNS_13ConstructDataE +__ZN3JSC9constructEPNS_9ExecStateENS_10JSValuePtrENS_13ConstructTypeERKNS_13ConstructDataERKNS_7ArgListE +__ZN3JSC10JSFunction9constructEPNS_9ExecStateERKNS_7ArgListE +__ZN3JSCL28stringProtoFuncLocaleCompareEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3WTF8Collator11userDefaultEv +__ZNK3WTF8Collator7collateEPKtmS2_m +__ZNK3WTF8Collator14createCollatorEv +__ZN3WTF8CollatorD1Ev +__ZN3WTF8Collator15releaseCollatorEv +__ZNK3JSC22NativeErrorConstructor9classInfoEv +JSValueUnprotect +JSValueIsNumber +__ZN3JSC8Debugger6attachEPNS_14JSGlobalObjectE +__ZN3WTF7HashSetIPN3JSC14JSGlobalObjectENS_7PtrHashIS3_EENS_10HashTraitsIS3_EEE3addERKS3_ +__ZN3WTF9HashTableIPN3JSC14JSGlobalObjectES3_NS_17IdentityExtractorIS3_EENS_7PtrHashIS3_EENS_10HashTraitsIS3_EES9_E6rehashEi +__ZN3JSC4Heap14primaryHeapEndEv +__ZN3JSC4Heap16primaryHeapBeginEv +__ZNK3JSC15RegExpPrototype9classInfoEv +__ZNK3JSC17NumberConstructor9classInfoEv +__ZNK3JSC17RegExpConstructor9classInfoEv +__ZNK3JSC10MathObject9classInfoEv +__ZNK3JSC18JSCallbackFunction9classInfoEv +JSValueIsString +JSStringGetLength +JSStringGetCharactersPtr +__ZN3JSC11Interpreter12cti_op_debugEPvz +__ZN3JSC11Interpreter5debugEPNS_9ExecStateENS_11DebugHookIDEii +__ZNK3JSC17DebuggerCallFrame4typeEv +__ZNK3JSC17DebuggerCallFrame12functionNameEv +__ZNK3JSC17DebuggerCallFrame10thisObjectEv +__ZN3WTF28setMainThreadCallbacksPausedEb +__ZN3JSC8Debugger6detachEPNS_14JSGlobalObjectE +__ZN3WTF9HashTableIPN3JSC14JSGlobalObjectES3_NS_17IdentityExtractorIS3_EENS_7PtrHashIS3_EENS_10HashTraitsIS3_EES9_E4findIS3_NS_22IdentityHashTranslatorIS3_S3_S7_EEEENS_17HashTableIteratorIS3_S3_S5_S7_S9_S9_EERKT_ +__ZN3WTF6VectorIN3JSC20FunctionRegisterInfoELm0EE14expandCapacityEm +__ZN3JSC8Profiler14startProfilingEPNS_9ExecStateERKNS_7UStringE +__ZN3JSC16ProfileGenerator6createERKNS_7UStringEPNS_9ExecStateEj +__ZN3JSC16ProfileGeneratorC2ERKNS_7UStringEPNS_9ExecStateEj +__ZN3JSC7Profile6createERKNS_7UStringEj +__ZN3JSC11TreeProfile6createERKNS_7UStringEj +__ZN3JSC7ProfileC2ERKNS_7UStringEj +__ZN3JSC11ProfileNodeC1ERKNS_14CallIdentifierEPS0_S4_ +__ZN3JSC33getCurrentUTCTimeWithMicrosecondsEv +__ZN3JSC16ProfileGenerator24addParentForConsoleStartEPNS_9ExecStateE +__ZN3JSC8Profiler20createCallIdentifierEPNS_12JSGlobalDataENS_10JSValuePtrERKNS_7UStringEi +__ZN3JSC11ProfileNode10insertNodeEN3WTF10PassRefPtrIS0_EE +__ZN3WTF6VectorINS_6RefPtrIN3JSC16ProfileGeneratorEEELm0EE14expandCapacityEm +__ZN3WTF10RefCountedIN3JSC16ProfileGeneratorEE5derefEv +__ZN3JSC8Profiler11willExecuteEPNS_9ExecStateENS_10JSValuePtrE +__ZN3JSC8Profiler10didExecuteEPNS_9ExecStateENS_10JSValuePtrE +__ZN3JSC16ProfileGenerator11willExecuteERKNS_14CallIdentifierE +__ZN3JSC11ProfileNode11willExecuteERKNS_14CallIdentifierE +__ZN3JSC11Interpreter24cti_op_profile_will_callEPvz +__ZN3JSC11Interpreter23cti_op_profile_did_callEPvz +__ZN3JSC16ProfileGenerator10didExecuteERKNS_14CallIdentifierE +__ZN3JSC11ProfileNode10didExecuteEv +__ZN3JSCL28numberProtoFuncToExponentialEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSCL26numberProtoFuncToPrecisionEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSC11Interpreter16cti_op_new_errorEPvz +__ZN3JSC19JSStaticScopeObject3putEPNS_9ExecStateERKNS_10IdentifierENS_10JSValuePtrERNS_15PutPropertySlotE +__ZN3JSC4WREC14CharacterClass11nonwordcharEv +__ZN3JSC19FunctionConstructor11getCallDataERNS_8CallDataE +__ZN3JSCL23callFunctionConstructorEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSC17ObjectConstructor11getCallDataERNS_8CallDataE +__ZN3JSCL21callObjectConstructorEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSC12JSActivation14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE +__ZN3JSCL26dateProtoFuncSetUTCMinutesEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSCL26dateProtoFuncSetUTCSecondsEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSC15PrefixErrorNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZN3JSC15PrefixErrorNode12releaseNodesERNS_12NodeReleaserE +__ZN3JSC15PrefixErrorNodeD1Ev +__ZN3JSCL19stringProtoFuncBoldEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3WTF6VectorIPNS0_IN3JSC10RegisterIDELm512EEELm32EE15reserveCapacityEm +__ZN3JSC12StringObjectC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEERKNS_7UStringE +__ZN3JSCL24regExpConstructorDollar5EPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE +__ZN3JSC24createStackOverflowErrorEPNS_9ExecStateE +__ZN3JSC6JSCell3putEPNS_9ExecStateERKNS_10IdentifierENS_10JSValuePtrERNS_15PutPropertySlotE +JSValueIsEqual +__ZN3JSC10JSValuePtr13equalSlowCaseEPNS_9ExecStateES0_S0_ +__ZN3JSCL16mathProtoFuncTanEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSC11Interpreter15cti_op_post_decEPvz +__ZN3JSCL28regExpConstructorLeftContextEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE +__ZN3JSCL31dateProtoFuncToLocaleDateStringEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSC21DebuggerStatementNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZN3JSC21DebuggerStatementNodeD1Ev +__ZN3JSCL12charSequenceEci +__ZN3JSCL17mathProtoFuncACosEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSC4Heap24setGCProtectNeedsLockingEv +__ZNK3JSC7UString6is8BitEv +__ZN3WTF9ByteArray6createEm +__ZN3JSC11JSByteArrayC1EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEPNS3_9ByteArrayEPKNS_9ClassInfoE +__ZN3JSC11JSByteArray18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE +__ZN3JSC11Interpreter28cti_op_get_by_val_byte_arrayEPvz +__ZN3JSC11JSByteArray3putEPNS_9ExecStateEjNS_10JSValuePtrE +__ZN3JSC11JSByteArray3putEPNS_9ExecStateERKNS_10IdentifierENS_10JSValuePtrERNS_15PutPropertySlotE +__ZN3JSC11JSByteArray18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE +__ZN3JSC11Interpreter28cti_op_put_by_val_byte_arrayEPvz +__ZN3JSCL28objectProtoFuncIsPrototypeOfEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSC14JSGlobalObject12defineGetterEPNS_9ExecStateERKNS_10IdentifierEPNS_8JSObjectE +__ZN3JSC14JSGlobalObject12defineSetterEPNS_9ExecStateERKNS_10IdentifierEPNS_8JSObjectE +__ZN3JSC6JSCell16getConstructDataERNS_13ConstructDataE +__ZN3JSCL25numberConstructorNaNValueEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE +__ZN3JSCL23throwStackOverflowErrorEPNS_9ExecStateEPNS_12JSGlobalDataEPvRS4_ +__ZN3JSCL24regExpConstructorDollar6EPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE +__ZN3JSCL24regExpConstructorDollar7EPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE +__ZN3JSC9ExecState9mathTableEPS0_ +__ZN3JSC9ExecState22regExpConstructorTableEPS0_ +__ZN3JSCL24regExpConstructorDollar8EPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE +__ZN3JSCL24regExpConstructorDollar9EPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE +__ZN3JSCL22regExpConstructorInputEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE +__ZN3JSCL25setRegExpConstructorInputEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrE +__ZN3JSCL26regExpConstructorLastMatchEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE +__ZN3JSCL26regExpConstructorLastParenEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE +__ZN3JSCL26regExpConstructorMultilineEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE +__ZN3JSCL29setRegExpConstructorMultilineEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrE +__ZN3JSCL29regExpConstructorRightContextEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE +__ZN3JSC16PostfixErrorNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZN3JSC16PostfixErrorNode12releaseNodesERNS_12NodeReleaserE +__ZN3JSC16PostfixErrorNodeD1Ev +__ZN3JSC6JSCell11getJSNumberEv +__ZN3JSC14JSGlobalObject17putWithAttributesEPNS_9ExecStateERKNS_10IdentifierENS_10JSValuePtrEj +__ZN3JSCL25arrayProtoFuncLastIndexOfEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSCL25numberConstructorMinValueEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE +__ZN3JSCL22regExpProtoFuncCompileEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSCL19arrayProtoFuncEveryEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSCL29objectProtoFuncToLocaleStringEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSC6JSCell14toThisJSStringEPNS_9ExecStateE +__ZNK3JSC6JSCell12toThisStringEPNS_9ExecStateE +__ZN3JSCL31dateProtoFuncSetUTCMillisecondsEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSCL24dateProtoFuncSetUTCMonthEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSCL28arrayProtoFuncToLocaleStringEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSC12JSActivation18getArgumentsGetterEv +__ZN3JSC12JSActivation15argumentsGetterEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE +__ZN3JSC9ExecState9dateTableEPS0_ +__ZN3JSC23createInvalidParamErrorEPNS_9ExecStateEPKcNS_10JSValuePtrEjPNS_9CodeBlockE +__ZNK3JSC15DotAccessorNode17isDotAccessorNodeEv +__ZNK3JSC14ExpressionNode17isDotAccessorNodeEv +__ZN3JSC13JSNotAnObject3putEPNS_9ExecStateEjNS_10JSValuePtrE +__ZN3JSC15DeleteValueNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE +__ZN3JSC15DeleteValueNodeD1Ev +__ZN3JSC15DeleteValueNode12releaseNodesERNS_12NodeReleaserE +__ZN3JSC17BytecodeGenerator18emitUnexpectedLoadEPNS_10RegisterIDEd +__ZN3JSC4WREC14CharacterClass9nondigitsEv +__ZNK3JSC19JSStaticScopeObject12toThisObjectEPNS_9ExecStateE +__ZNK3JSC16JSVariableObject21getPropertyAttributesEPNS_9ExecStateERKNS_10IdentifierERj +__ZN3JSCL25dateProtoFuncToDateStringEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSCL25dateProtoFuncToTimeStringEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE +__ZN3JSC17BytecodeGenerator35emitThrowExpressionTooDeepExceptionEv +__ZN3JSC12JSGlobalData6createEv +__ZN3WTF12isMainThreadEv +__ZN3JSC4Heap7destroyEv +__ZN3JSC12JSGlobalDataD1Ev +__ZN3JSC11InterpreterD1Ev +__ZN3JSC12RegisterFileD1Ev +__ZNK3JSC9HashTable11deleteTableEv +__ZN3JSC5LexerD1Ev +__ZN3WTF20deleteAllPairSecondsIP24OpaqueJSClassContextDataKNS_7HashMapIP13OpaqueJSClassS2_NS_7PtrHashIS5_EENS_10HashTraitsIS5_EENS8_IS2_EEEEEEvRT0_ +__ZN3JSC17CommonIdentifiersD2Ev +__ZN3JSC21deleteIdentifierTableEPNS_15IdentifierTableE +__ZN3JSC4HeapD1Ev +__ZN3JSC12SmallStringsD1Ev +__ZN3JSC12JSGlobalData10ClientDataD2Ev +__ZN3WTF8CollatorC1EPKc +__ZN3WTF8Collator18setOrderLowerFirstEb +__ZN3JSC35createInterruptedExecutionExceptionEPNS_12JSGlobalDataE +__ZNK3JSC25InterruptedExecutionError19isWatchdogExceptionEv diff --git a/JavaScriptCore/JavaScriptCore.pri b/JavaScriptCore/JavaScriptCore.pri index 22dcbb1..6aee0aa 100644 --- a/JavaScriptCore/JavaScriptCore.pri +++ b/JavaScriptCore/JavaScriptCore.pri @@ -2,15 +2,30 @@ VPATH += $$PWD INCLUDEPATH += tmp -INCLUDEPATH += $$PWD $$PWD/kjs $$PWD/debugger $$PWD/runtime $$PWD/wtf $$PWD/wtf/unicode $$PWD/VM $$PWD/profiler $$PWD/API $$PWD/.. \ - $$PWD/ForwardingHeaders +INCLUDEPATH += $$PWD $$PWD/parser $$PWD/bytecompiler $$PWD/debugger $$PWD/runtime $$PWD/wtf $$PWD/wtf/unicode $$PWD/interpreter $$PWD/jit $$PWD/profiler $$PWD/wrec $$PWD/API $$PWD/.. \ + $$PWD/ForwardingHeaders $$PWD/bytecode $$PWD/assembler DEFINES += BUILDING_QT__ isEmpty(GENERATED_SOURCES_DIR):GENERATED_SOURCES_DIR = tmp GENERATED_SOURCES_DIR_SLASH = $$GENERATED_SOURCES_DIR/ -win32-*: GENERATED_SOURCES_DIR_SLASH ~= s|/|\| -win32-g++: LIBS += -lwinmm +win32-* { + GENERATED_SOURCES_DIR_SLASH ~= s|/|\| + LIBS += -lwinmm +} +# Disable the JIT due to numerous observed miscompilations :( +#CONFIG(release):isEqual(QT_ARCH,i386) { +# JIT_DEFINES = ENABLE_JIT ENABLE_WREC ENABLE_JIT_OPTIMIZE_CALL ENABLE_JIT_OPTIMIZE_PROPERTY_ACCESS ENABLE_JIT_OPTIMIZE_ARITHMETIC +# # gcc <= 4.1 is known to miscompile, so require >= 4.2, written as major > 3 and minor > 1 +# linux-g++*:greaterThan(QT_GCC_MAJOR_VERSION,3):greaterThan(QT_GCC_MINOR_VERSION,1) { +# DEFINES += $$JIT_DEFINES +# SOURCES += wtf/TCSystemAlloc.cpp +# DEFINES -= USE_SYSTEM_MALLOC +# } +# win32-msvc* { +# DEFINES += $$JIT_DEFINES +# } +#} include(pcre/pcre.pri) @@ -24,15 +39,17 @@ LUT_FILES += \ runtime/RegExpObject.cpp KEYWORDLUT_FILES += \ - kjs/keywords.table + parser/Keywords.table -KJSBISON += \ - kjs/grammar.y +JSCBISON += \ + parser/Grammar.y SOURCES += \ wtf/Assertions.cpp \ + wtf/ByteArray.cpp \ wtf/HashTable.cpp \ wtf/MainThread.cpp \ + wtf/RandomNumber.cpp \ wtf/RefCountedLeakCounter.cpp \ wtf/unicode/CollatorDefault.cpp \ wtf/unicode/icu/CollatorICU.cpp \ @@ -54,14 +71,30 @@ SOURCES += \ runtime/JSVariableObject.cpp \ runtime/JSActivation.cpp \ runtime/JSNotAnObject.cpp \ - VM/CodeBlock.cpp \ - VM/CodeGenerator.cpp \ - VM/ExceptionHelpers.cpp \ + bytecode/CodeBlock.cpp \ + bytecode/StructureStubInfo.cpp \ + bytecode/JumpTable.cpp \ + jit/JIT.cpp \ + jit/JITCall.cpp \ + jit/JITArithmetic.cpp \ + jit/JITPropertyAccess.cpp \ + jit/ExecutableAllocator.cpp \ + bytecompiler/BytecodeGenerator.cpp \ + runtime/ExceptionHelpers.cpp \ runtime/JSPropertyNameIterator.cpp \ - VM/Machine.cpp \ - VM/Opcode.cpp \ - VM/SamplingTool.cpp \ - VM/RegisterFile.cpp + interpreter/Interpreter.cpp \ + bytecode/Opcode.cpp \ + bytecode/SamplingTool.cpp \ + wrec/CharacterClass.cpp \ + wrec/CharacterClassConstructor.cpp \ + wrec/WREC.cpp \ + wrec/WRECFunctors.cpp \ + wrec/WRECGenerator.cpp \ + wrec/WRECParser.cpp \ + interpreter/RegisterFile.cpp + +win32-*: SOURCES += jit/ExecutableAllocatorWin.cpp +else: SOURCES += jit/ExecutableAllocatorPosix.cpp # AllInOneFile.cpp helps gcc analize and optimize code # Other compilers may be able to do this at link time @@ -74,29 +107,32 @@ SOURCES += \ runtime/BooleanObject.cpp \ runtime/BooleanPrototype.cpp \ runtime/CallData.cpp \ - kjs/collector.cpp \ + runtime/Collector.cpp \ runtime/CommonIdentifiers.cpp \ runtime/ConstructData.cpp \ + wtf/CurrentTime.cpp \ runtime/DateConstructor.cpp \ runtime/DateInstance.cpp \ runtime/DateMath.cpp \ runtime/DatePrototype.cpp \ debugger/Debugger.cpp \ debugger/DebuggerCallFrame.cpp \ - kjs/dtoa.cpp \ + debugger/DebuggerActivation.cpp \ + wtf/dtoa.cpp \ runtime/Error.cpp \ runtime/ErrorConstructor.cpp \ runtime/ErrorInstance.cpp \ runtime/ErrorPrototype.cpp \ - runtime/ExecState.cpp \ + interpreter/CallFrame.cpp \ runtime/FunctionConstructor.cpp \ runtime/FunctionPrototype.cpp \ runtime/GetterSetter.cpp \ runtime/GlobalEvalFunction.cpp \ - kjs/identifier.cpp \ + runtime/Identifier.cpp \ runtime/InternalFunction.cpp \ - kjs/interpreter.cpp \ + runtime/Completion.cpp \ runtime/JSArray.cpp \ + runtime/JSByteArray.cpp \ runtime/JSCell.cpp \ runtime/JSFunction.cpp \ runtime/JSGlobalObjectFunctions.cpp \ @@ -107,24 +143,23 @@ SOURCES += \ runtime/JSString.cpp \ runtime/JSValue.cpp \ runtime/JSWrapperObject.cpp \ - kjs/lexer.cpp \ - kjs/lookup.cpp \ + parser/Lexer.cpp \ + runtime/Lookup.cpp \ runtime/MathObject.cpp \ runtime/NativeErrorConstructor.cpp \ runtime/NativeErrorPrototype.cpp \ - kjs/nodes.cpp \ - kjs/nodes2string.cpp \ + parser/Nodes.cpp \ runtime/NumberConstructor.cpp \ runtime/NumberObject.cpp \ runtime/NumberPrototype.cpp \ runtime/ObjectConstructor.cpp \ runtime/ObjectPrototype.cpp \ - kjs/operations.cpp \ - kjs/Parser.cpp \ + runtime/Operations.cpp \ + parser/Parser.cpp \ runtime/PropertyNameArray.cpp \ runtime/PropertySlot.cpp \ runtime/PrototypeFunction.cpp \ - kjs/regexp.cpp \ + runtime/RegExp.cpp \ runtime/RegExpConstructor.cpp \ runtime/RegExpObject.cpp \ runtime/RegExpPrototype.cpp \ @@ -133,9 +168,9 @@ SOURCES += \ runtime/StringConstructor.cpp \ runtime/StringObject.cpp \ runtime/StringPrototype.cpp \ - runtime/StructureID.cpp \ - runtime/StructureIDChain.cpp \ - kjs/ustring.cpp \ + runtime/Structure.cpp \ + runtime/StructureChain.cpp \ + runtime/UString.cpp \ profiler/HeavyProfile.cpp \ profiler/Profile.cpp \ profiler/ProfileGenerator.cpp \ @@ -143,31 +178,33 @@ SOURCES += \ profiler/Profiler.cpp \ profiler/TreeProfile.cpp \ wtf/FastMalloc.cpp \ + wtf/Threading.cpp \ wtf/ThreadingQt.cpp \ wtf/qt/MainThreadQt.cpp # GENERATOR 1-A: LUT creator lut.output = $$GENERATED_SOURCES_DIR/${QMAKE_FILE_BASE}.lut.h -lut.commands = perl $$PWD/kjs/create_hash_table ${QMAKE_FILE_NAME} -i > ${QMAKE_FILE_OUT} +lut.commands = perl $$PWD/create_hash_table ${QMAKE_FILE_NAME} -i > ${QMAKE_FILE_OUT} lut.depend = ${QMAKE_FILE_NAME} lut.input = LUT_FILES lut.CONFIG += no_link addExtraCompiler(lut) # GENERATOR 1-B: particular LUT creator (for 1 file only) -keywordlut.output = $$GENERATED_SOURCES_DIR/lexer.lut.h -keywordlut.commands = perl $$PWD/kjs/create_hash_table ${QMAKE_FILE_NAME} -i > ${QMAKE_FILE_OUT} +keywordlut.output = $$GENERATED_SOURCES_DIR/Lexer.lut.h +keywordlut.commands = perl $$PWD/create_hash_table ${QMAKE_FILE_NAME} -i > ${QMAKE_FILE_OUT} keywordlut.depend = ${QMAKE_FILE_NAME} keywordlut.input = KEYWORDLUT_FILES keywordlut.CONFIG += no_link addExtraCompiler(keywordlut) # GENERATOR 2: bison grammar -kjsbison.output = $$GENERATED_SOURCES_DIR/${QMAKE_FILE_BASE}.cpp -kjsbison.commands = bison -d -p kjsyy ${QMAKE_FILE_NAME} -o ${QMAKE_FILE_BASE}.tab.c && $(MOVE) ${QMAKE_FILE_BASE}.tab.c ${QMAKE_FILE_OUT} && $(MOVE) ${QMAKE_FILE_BASE}.tab.h $$GENERATED_SOURCES_DIR/${QMAKE_FILE_BASE}.h -kjsbison.depend = ${QMAKE_FILE_NAME} -kjsbison.input = KJSBISON -kjsbison.variable_out = GENERATED_SOURCES -kjsbison.dependency_type = TYPE_C -kjsbison.CONFIG = target_predeps -addExtraCompilerWithHeader(kjsbison) +jscbison.output = $$GENERATED_SOURCES_DIR/${QMAKE_FILE_BASE}.cpp +jscbison.commands = bison -d -p jscyy ${QMAKE_FILE_NAME} -o ${QMAKE_FILE_BASE}.tab.c && $(MOVE) ${QMAKE_FILE_BASE}.tab.c ${QMAKE_FILE_OUT} && $(MOVE) ${QMAKE_FILE_BASE}.tab.h $$GENERATED_SOURCES_DIR/${QMAKE_FILE_BASE}.h +jscbison.depend = ${QMAKE_FILE_NAME} +jscbison.input = JSCBISON +jscbison.variable_out = GENERATED_SOURCES +jscbison.dependency_type = TYPE_C +jscbison.CONFIG = target_predeps +addExtraCompilerWithHeader(jscbison) + diff --git a/JavaScriptCore/JavaScriptCore.pro b/JavaScriptCore/JavaScriptCore.pro index 19fb0fd..56dae05 100644 --- a/JavaScriptCore/JavaScriptCore.pro +++ b/JavaScriptCore/JavaScriptCore.pro @@ -67,3 +67,6 @@ QMAKE_EXTRA_TARGETS += generated_files qt-port: lessThan(QT_MINOR_VERSION, 4) { DEFINES += QT_BEGIN_NAMESPACE="" QT_END_NAMESPACE="" } + +*-g++*:QMAKE_CXXFLAGS_RELEASE -= -O2 +*-g++*:QMAKE_CXXFLAGS_RELEASE += -O3 diff --git a/JavaScriptCore/JavaScriptCore.scons b/JavaScriptCore/JavaScriptCore.scons new file mode 100644 index 0000000..24e5003 --- /dev/null +++ b/JavaScriptCore/JavaScriptCore.scons @@ -0,0 +1,307 @@ +# The keys in sources are the paths to the directories +# the values are an array of source files in those directories to compile +sources = {} +sources['API'] = [ + 'API/JSBase.cpp', + 'API/JSCallbackConstructor.cpp', + 'API/JSCallbackFunction.cpp', + 'API/JSCallbackObject.cpp', + 'API/JSClassRef.cpp', + 'API/JSContextRef.cpp', + 'API/JSObjectRef.cpp', + 'API/JSProfilerPrivate.cpp', + 'API/JSStringRef.cpp', + 'API/JSValueRef.cpp', + 'API/OpaqueJSString.cpp', +] +sources['bytecompiler'] = [ + 'bytecompiler/BytecodeGenerator.cpp', +] +sources['debugger'] = [ + 'debugger/Debugger.cpp', + 'debugger/DebuggerActivation.cpp', + 'debugger/DebuggerCallFrame.cpp', +] +sources['parser'] = [ + 'parser/Lexer.cpp', + 'parser/Nodes.cpp', + 'parser/Parser.cpp', +] +sources['pcre'] = [ + 'pcre/pcre_compile.cpp', + 'pcre/pcre_exec.cpp', + 'pcre/pcre_tables.cpp', + 'pcre/pcre_ucp_searchfuncs.cpp', + 'pcre/pcre_xclass.cpp', +] +sources['profiler'] = [ + 'profiler/HeavyProfile.cpp', + 'profiler/Profile.cpp', + 'profiler/ProfileGenerator.cpp', + 'profiler/ProfileNode.cpp', + 'profiler/Profiler.cpp', + 'profiler/TreeProfile.cpp', +] +sources['runtime'] = [ + 'runtime/ArgList.cpp', + 'runtime/Arguments.cpp', + 'runtime/ArrayConstructor.cpp', + 'runtime/ArrayPrototype.cpp', + 'runtime/BooleanConstructor.cpp', + 'runtime/BooleanObject.cpp', + 'runtime/BooleanPrototype.cpp', + 'runtime/CallData.cpp', + 'runtime/Collector.cpp', + 'runtime/Completion.cpp', + 'runtime/CommonIdentifiers.cpp', + 'runtime/ConstructData.cpp', + 'runtime/DateConstructor.cpp', + 'runtime/DateInstance.cpp', + 'runtime/DateMath.cpp', + 'runtime/DatePrototype.cpp', + 'runtime/Error.cpp', + 'runtime/ErrorConstructor.cpp', + 'runtime/ErrorInstance.cpp', + 'runtime/ErrorPrototype.cpp', + 'runtime/ExceptionHelpers.cpp', + 'runtime/FunctionConstructor.cpp', + 'runtime/FunctionPrototype.cpp', + 'runtime/GetterSetter.cpp', + 'runtime/GlobalEvalFunction.cpp', + 'runtime/Identifier.cpp', + 'runtime/InitializeThreading.cpp', + 'runtime/InternalFunction.cpp', + 'runtime/JSActivation.cpp', + 'runtime/JSArray.cpp', + 'runtime/JSByteArray.cpp', + 'runtime/JSCell.cpp', + 'runtime/JSFunction.cpp', + 'runtime/JSGlobalData.cpp', + 'runtime/JSGlobalObject.cpp', + 'runtime/JSGlobalObjectFunctions.cpp', + 'runtime/JSImmediate.cpp', + 'runtime/JSLock.cpp', + 'runtime/JSNotAnObject.cpp', + 'runtime/JSNumberCell.cpp', + 'runtime/JSObject.cpp', + 'runtime/JSPropertyNameIterator.cpp', + 'runtime/JSStaticScopeObject.cpp', + 'runtime/JSString.cpp', + 'runtime/JSValue.cpp', + 'runtime/JSVariableObject.cpp', + 'runtime/JSWrapperObject.cpp', + 'runtime/Lookup.cpp', + 'runtime/MathObject.cpp', + 'runtime/NativeErrorConstructor.cpp', + 'runtime/NativeErrorPrototype.cpp', + 'runtime/NumberConstructor.cpp', + 'runtime/NumberObject.cpp', + 'runtime/NumberPrototype.cpp', + 'runtime/ObjectConstructor.cpp', + 'runtime/ObjectPrototype.cpp', + 'runtime/Operations.cpp', + 'runtime/PropertyNameArray.cpp', + 'runtime/PropertySlot.cpp', + 'runtime/PrototypeFunction.cpp', + 'runtime/RegExp.cpp', + 'runtime/RegExpConstructor.cpp', + 'runtime/RegExpObject.cpp', + 'runtime/RegExpPrototype.cpp', + 'runtime/ScopeChain.cpp', + 'runtime/SmallStrings.cpp', + 'runtime/StringConstructor.cpp', + 'runtime/StringObject.cpp', + 'runtime/StringPrototype.cpp', + 'runtime/Structure.cpp', + 'runtime/StructureChain.cpp', + 'runtime/UString.cpp', +] +sources['bytecode'] = [ + 'bytecode/CodeBlock.cpp', + 'bytecode/StructureStubInfo.cpp', + 'bytecode/JumpTable.cpp', + 'bytecode/Opcode.cpp', + 'bytecode/SamplingTool.cpp', +] +sources['interpreter'] = [ + 'interpreter/CallFrame.cpp', + 'interpreter/Interpreter.cpp', + 'interpreter/RegisterFile.cpp', +] +sources['jit'] = [ + 'jit/ExecutableAllocator.cpp', + 'jit/JIT.cpp', +] +sources['wrec'] = [ + 'wrec/CharacterClass.cpp', + 'wrec/CharacterClassConstructor.cpp', + 'wrec/WREC.cpp', + 'wrec/WRECFunctors.cpp', + 'wrec/WRECGenerator.cpp', + 'wrec/WRECParser.cpp', +] +sources['wtf'] = [ + 'wtf/Assertions.cpp', + 'wtf/ByteArray.cpp', + 'wtf/CurrentTime.cpp', + 'wtf/FastMalloc.cpp', + 'wtf/HashTable.cpp', + 'wtf/RandomNumber.cpp', + 'wtf/RefCountedLeakCounter.cpp', + 'wtf/Threading.cpp', + 'wtf/dtoa.cpp', +] +sources['wtf/unicode'] = [ + 'wtf/unicode/CollatorDefault.cpp', + 'wtf/unicode/UTF8.cpp', +] +sources['wtf/unicode/icu'] = [ + 'wtf/unicode/icu/CollatorICU.cpp', +] + +env = Environment() + +building_on_win32 = env['PLATFORM'] == 'win32' or env['PLATFORM'] == 'cygwin' + +# Scons uses gcc when building under cygwin by default +# We also have to manually force 8.0 or Scons will try and +# look up what version to use using the registry and fail +# due to lack of cygwin-python registry support +if env['PLATFORM'] == 'cygwin': + env['MSVS_VERSION'] = '8.0' + # Some systems have PROGRAMFILES, some have ProgramFiles + # Scons msvc tool only expects 'ProgramFiles' + import os + if os.getenv('PROGRAMFILES') and not os.getenv('ProgramFiles'): + os.environ['ProgramFiles'] = os.getenv('PROGRAMFILES') + + env.Tool('msvc') + env.Tool('mslink') + env.Tool('mslib') + +# Scons is failing to carry the %PATH% value through correctly +# Hack IncrediBuild into our path so cl.exe doesn't crash +if env['PLATFORM'] == 'win32': + env.AppendENVPath('PATH', 'c:/Program Files/Xoreax/IncrediBuild') + +if env['PLATFORM'] == 'darwin': + sources['API'].append('API/JSStringRefCF.cpp') + sources['profiler'].append('profiler/ProfilerServer.mm') + sources['wtf'].append('wtf/ThreadingPthreads.cpp') + sources['wtf'].append('wtf/MainThread.cpp') + sources['wtf/mac'] = ['wtf/mac/MainThreadMac.mm'] + sources['wtf'].append('wtf/TCSystemAlloc.cpp') + sources['jit'].append('jit/ExecutableAllocatorPosix.cpp') +elif building_on_win32: + sources['wtf'].append('wtf/ThreadingNone.cpp') + sources['jit'].append('jit/ExecutableAllocatorWin.cpp') + env.Append(CPPDEFINES = ['ENABLE_JSC_MULTIPLE_THREADS=0']) + +derived_sources_path = 'DerivedSources/JavaScriptCore/' +def DerivedSources(path): + return derived_sources_path + path + +derived_sources_results = map(DerivedSources, [ + 'ArrayPrototype.lut.h', + 'DatePrototype.lut.h', + 'MathObject.lut.h', + 'NumberConstructor.lut.h', + 'RegExpConstructor.lut.h', + 'RegExpObject.lut.h', + 'StringPrototype.lut.h' + 'chartables.c', + 'grammar.cpp', + 'grammar.h', + 'lexer.lut.h', +]) + +derived_sources_sources = [ + 'runtime/ArrayPrototype.cpp', + 'runtime/DatePrototype.cpp', + 'runtime/MathObject.cpp', + 'runtime/NumberConstructor.cpp', + 'runtime/RegExpConstructor.cpp', + 'runtime/RegExpObject.cpp', + 'runtime/StringPrototype.cpp', + 'parser/Grammar.y', + 'parser/Lexer.cpp', +] + +# Generate DerivedSources +# Make sure Windows knows where bash (and all the other cygwin commands) live +if env['PLATFORM'] == 'win32': + env.AppendENVPath('PATH', 'C:/cygwin/bin') +env.Command(derived_sources_results, derived_sources_sources, 'bash make-generated-sources.sh') +sources[derived_sources_path] = [DerivedSources('Grammar.cpp')] + +# Handle os-version specific build settings +if env['PLATFORM'] == 'darwin': + from subprocess import Popen, PIPE + version_pieces = Popen(["sw_vers", "-productVersion"], stdout = PIPE).communicate()[0].split('.') + if map(int, version_pieces)[:2] > (10, 5): + # Dtrace doesn't exist in Tiger, and was broken in Leopard + env.Command(DerivedSources('TracingDtrace.h'), 'runtime/Tracing.d', '/usr/sbin/dtrace -h -o $TARGET -s $SOURCE') + +# This build file builds the Chromium port for now, support for +# others could be added later. +env.Append(CPPDEFINES = ['BUILDING_CHROMIUM__']) + +# I'm not certain how many of these windows defines are actually required. +if building_on_win32: + env.Append(CPPDEFINES = ['_WIN32_WINNT=0x0600', 'WINVER=0x0600', 'WIN32', '_WINDOWS', 'NOMINMAX', 'UNICODE', '_UNICODE', '__STD_C', '_HAS_EXCEPTIONS=0']) + +# Scons out-of-the-box only supports precompiled headers for MSVC +# remove this when we fix Scons to understand GCC precompiled headers +if env['CC'] == 'gcc': + env['CCFLAGS'] = '-include JavaScriptCorePrefix.h' +# Turns out the MSVC PCH support is badly broken +# env['PCH'] = 'JavaScriptCorePrefix.h' +# env['PCHSTOP'] = 'JavaScriptCorePrefix.h' + +if env['PLATFORM'] == 'darwin': + env['FRAMEWORKS'] = ['CoreFoundation', 'Foundation'] + env['LIBS'] = ['icucore'] + # Apple does not ship the ICU headers with Mac OS X, so WebKit includes a copy of 3.2 headers + env.Append(CPPPATH = 'icu') + +webkit_libraries_path = "../WebKitLibraries/win/" +def WebKitLibraries(path): + return webkit_libraries_path + path + +include_paths = ['.', '..', 'ForwardingHeaders'] + sources.keys() +env.Append(CPPPATH = include_paths) +if building_on_win32: + env.Append(CPPPATH = ['os-win32', WebKitLibraries('include')]) + env.Prepend(LIBPATH = [WebKitLibraries('lib')]) + env.Append(LIBS = ['icuin', 'icuuc', 'user32', 'winmm']) + +# Save off a copy of the environment for use with jsc +jsc_env = env.Clone() + +if building_on_win32: + env.StaticLibrary("JavaScriptCore", sources.values()) +else: + env.SharedLibrary("JavaScriptCore", sources.values()) + + +env = jsc_env + +# Build the jsc testing shell +shell_sources = ['jsc.cpp'] +build_directory = '.' # This should be changed to point to wherever JavaScriptCore gets built to + +# It's hacky to re-use the same environment from JavaScriptCore +# but it makes building on windows easier for now +env['CPPPATH'] = include_paths +env['LIBS'] = ['JavaScriptCore'] +env['LIBPATH'] = [build_directory] + +if env['PLATFORM'] == 'darwin': + env.Append(LIBS = ['edit']) + env.Append(CPPPATH = 'icu') +elif building_on_win32: + env.Append(CPPPATH = ['os-win32', WebKitLibraries('include')]) + env.Prepend(LIBPATH = [WebKitLibraries('lib')]) + env.Append(LIBS = ['icuin', 'icuuc', 'user32', 'winmm']) + +env.Program('jsc', shell_sources) diff --git a/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj b/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj index 3c64f3c..e28adab 100644 --- a/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj +++ b/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj @@ -42,7 +42,7 @@ />
<Tool
Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""$(WebKitOutputDir)\obj\JavaScriptCore\DerivedSources\";../../;../../API/;../../pcre/;../../kjs/;../../runtime/;../../VM/;../../wtf/;../../profiler;../../masm/;../../debugger/;../../wrec/;"$(WebKitLibrariesDir)\include";"$(WebKitLibrariesDir)\include\icu";../../../icu/include;"$(WebKitOutputDir)\include\JavaScriptCore";"$(WebKitLibrariesDir)\include\pthreads";"$(WebKitLibrariesDir)\Include\CoreFoundation\OSXCompatibilityHeaders";"$(WebKitLibrariesDir)\Include\CoreFoundation\OSXCompatibilityHeaders\GNUCompatibility""
+ AdditionalIncludeDirectories=""$(WebKitOutputDir)\obj\JavaScriptCore\DerivedSources\";../../;../../API/;../../pcre/;../../parser/;../../bytecompiler/;../../jit/;../../runtime/;../../bytecode/;../../interpreter/;../../wtf/;../../profiler;../../assembler/;../../debugger/;../../wrec/;"$(WebKitLibrariesDir)\include";"$(WebKitLibrariesDir)\include\icu";../../../icu/include;"$(WebKitOutputDir)\include\JavaScriptCore";"$(WebKitLibrariesDir)\include\pthreads";"$(WebKitLibrariesDir)\Include\CoreFoundation\OSXCompatibilityHeaders";"$(WebKitLibrariesDir)\Include\CoreFoundation\OSXCompatibilityHeaders\GNUCompatibility""
PreprocessorDefinitions="__STD_C"
ForcedIncludeFiles=""
/>
@@ -73,7 +73,7 @@ />
<Tool
Name="VCPostBuildEventTool"
- CommandLine="mkdir 2>NUL "$(WebKitOutputDir)\include\JavaScriptCore"

xcopy /y /d "$(ProjectDir)\..\..\wtf\*.h" "$(WebKitOutputDir)\include\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\wtf\unicode\*.h" "$(WebKitOutputDir)\include\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\wtf\unicode\icu\*.h" "$(WebKitOutputDir)\include\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\kjs\*.h" "$(WebKitOutputDir)\include\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\runtime\*.h" "$(WebKitOutputDir)\include\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\VM\*.h" "$(WebKitOutputDir)\include\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\masm\*.h" "$(WebKitOutputDir)\include\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\wrec\*.h" "$(WebKitOutputDir)\include\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\debugger\*.h" "$(WebKitOutputDir)\include\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\profiler\*.h" "$(WebKitOutputDir)\include\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\kjs\create_hash_table" "$(WebKitOutputDir)\include\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\pcre\pcre.h" "$(WebKitOutputDir)\include\JavaScriptCore"

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

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

if exist "$(WebKitOutputDir)\buildfailed" del "$(WebKitOutputDir)\buildfailed"
"
/>
</Configuration>
<Configuration
@@ -104,7 +104,7 @@ />
<Tool
Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""$(WebKitOutputDir)\obj\JavaScriptCore\DerivedSources\";../../;../../API/;../../pcre/;../../kjs/;../../runtime/;../../VM/;../../wtf/;../../profiler;../../masm/;../../debugger/;../../wrec/;"$(WebKitLibrariesDir)\include";"$(WebKitLibrariesDir)\include\icu";../../../icu/include;"$(WebKitOutputDir)\include\JavaScriptCore";"$(WebKitLibrariesDir)\include\pthreads";"$(WebKitLibrariesDir)\Include\CoreFoundation\OSXCompatibilityHeaders";"$(WebKitLibrariesDir)\Include\CoreFoundation\OSXCompatibilityHeaders\GNUCompatibility""
+ AdditionalIncludeDirectories=""$(WebKitOutputDir)\obj\JavaScriptCore\DerivedSources\";../../;../../API/;../../pcre/;../../parser/;../../bytecompiler/;../../jit/;../../runtime/;../../bytecode/;../../interpreter/;../../wtf/;../../profiler;../../assembler/;../../debugger/;../../wrec/;"$(WebKitLibrariesDir)\include";"$(WebKitLibrariesDir)\include\icu";../../../icu/include;"$(WebKitOutputDir)\include\JavaScriptCore";"$(WebKitLibrariesDir)\include\pthreads";"$(WebKitLibrariesDir)\Include\CoreFoundation\OSXCompatibilityHeaders";"$(WebKitLibrariesDir)\Include\CoreFoundation\OSXCompatibilityHeaders\GNUCompatibility""
PreprocessorDefinitions="__STD_C"
ForcedIncludeFiles=""
/>
@@ -135,7 +135,7 @@ />
<Tool
Name="VCPostBuildEventTool"
- CommandLine="mkdir 2>NUL "$(WebKitOutputDir)\include\JavaScriptCore"

xcopy /y /d "$(ProjectDir)\..\..\wtf\*.h" "$(WebKitOutputDir)\include\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\wtf\unicode\*.h" "$(WebKitOutputDir)\include\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\wtf\unicode\icu\*.h" "$(WebKitOutputDir)\include\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\kjs\*.h" "$(WebKitOutputDir)\include\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\runtime\*.h" "$(WebKitOutputDir)\include\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\VM\*.h" "$(WebKitOutputDir)\include\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\masm\*.h" "$(WebKitOutputDir)\include\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\wrec\*.h" "$(WebKitOutputDir)\include\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\debugger\*.h" "$(WebKitOutputDir)\include\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\profiler\*.h" "$(WebKitOutputDir)\include\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\kjs\create_hash_table" "$(WebKitOutputDir)\include\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\pcre\pcre.h" "$(WebKitOutputDir)\include\JavaScriptCore"

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

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

if exist "$(WebKitOutputDir)\buildfailed" del "$(WebKitOutputDir)\buildfailed"
"
/>
</Configuration>
<Configuration
@@ -165,7 +165,7 @@ />
<Tool
Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""$(WebKitOutputDir)\obj\JavaScriptCore\DerivedSources\";../../;../../API/;../../pcre/;../../kjs/;../../runtime/;../../VM/;../../wtf/;../../profiler;../../masm/;../../debugger/;../../wrec/;"$(WebKitLibrariesDir)\include";"$(WebKitLibrariesDir)\include\icu";../../../icu/include;"$(WebKitOutputDir)\include\JavaScriptCore";"$(WebKitLibrariesDir)\include\pthreads";"$(WebKitLibrariesDir)\Include\CoreFoundation\OSXCompatibilityHeaders";"$(WebKitLibrariesDir)\Include\CoreFoundation\OSXCompatibilityHeaders\GNUCompatibility""
+ AdditionalIncludeDirectories=""$(WebKitOutputDir)\obj\JavaScriptCore\DerivedSources\";../../;../../API/;../../pcre/;../../parser/;../../bytecompiler/;../../jit/;../../runtime/;../../bytecode/;../../interpreter/;../../wtf/;../../profiler;../../assembler/;../../debugger/;../../wrec/;"$(WebKitLibrariesDir)\include";"$(WebKitLibrariesDir)\include\icu";../../../icu/include;"$(WebKitOutputDir)\include\JavaScriptCore";"$(WebKitLibrariesDir)\include\pthreads";"$(WebKitLibrariesDir)\Include\CoreFoundation\OSXCompatibilityHeaders";"$(WebKitLibrariesDir)\Include\CoreFoundation\OSXCompatibilityHeaders\GNUCompatibility""
PreprocessorDefinitions="__STD_C"
ForcedIncludeFiles=""
/>
@@ -196,7 +196,7 @@ />
<Tool
Name="VCPostBuildEventTool"
- CommandLine="mkdir 2>NUL "$(WebKitOutputDir)\include\JavaScriptCore"

xcopy /y /d "$(ProjectDir)\..\..\wtf\*.h" "$(WebKitOutputDir)\include\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\wtf\unicode\*.h" "$(WebKitOutputDir)\include\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\wtf\unicode\icu\*.h" "$(WebKitOutputDir)\include\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\kjs\*.h" "$(WebKitOutputDir)\include\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\runtime\*.h" "$(WebKitOutputDir)\include\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\VM\*.h" "$(WebKitOutputDir)\include\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\masm\*.h" "$(WebKitOutputDir)\include\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\wrec\*.h" "$(WebKitOutputDir)\include\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\debugger\*.h" "$(WebKitOutputDir)\include\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\profiler\*.h" "$(WebKitOutputDir)\include\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\kjs\create_hash_table" "$(WebKitOutputDir)\include\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\pcre\pcre.h" "$(WebKitOutputDir)\include\JavaScriptCore"

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

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

if exist "$(WebKitOutputDir)\buildfailed" del "$(WebKitOutputDir)\buildfailed"
"
/>
</Configuration>
<Configuration
@@ -227,7 +227,7 @@ />
<Tool
Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""$(WebKitOutputDir)\obj\JavaScriptCore\DerivedSources\";../../;../../API/;../../pcre/;../../kjs/;../../runtime/;../../VM/;../../wtf/;../../profiler;../../masm/;../../debugger/;../../wrec/;"$(WebKitLibrariesDir)\include";"$(WebKitLibrariesDir)\include\icu";../../../icu/include;"$(WebKitOutputDir)\include\JavaScriptCore";"$(WebKitLibrariesDir)\include\pthreads";"$(WebKitLibrariesDir)\Include\CoreFoundation\OSXCompatibilityHeaders";"$(WebKitLibrariesDir)\Include\CoreFoundation\OSXCompatibilityHeaders\GNUCompatibility""
+ AdditionalIncludeDirectories=""$(WebKitOutputDir)\obj\JavaScriptCore\DerivedSources\";../../;../../API/;../../pcre/;../../parser/;../../bytecompiler/;../../jit/;../../runtime/;../../bytecode/;../../interpreter/;../../wtf/;../../profiler;../../assembler/;../../debugger/;../../wrec/;"$(WebKitLibrariesDir)\include";"$(WebKitLibrariesDir)\include\icu";../../../icu/include;"$(WebKitOutputDir)\include\JavaScriptCore";"$(WebKitLibrariesDir)\include\pthreads";"$(WebKitLibrariesDir)\Include\CoreFoundation\OSXCompatibilityHeaders";"$(WebKitLibrariesDir)\Include\CoreFoundation\OSXCompatibilityHeaders\GNUCompatibility""
PreprocessorDefinitions="__STD_C"
ForcedIncludeFiles=""
/>
@@ -258,7 +258,7 @@ />
<Tool
Name="VCPostBuildEventTool"
- CommandLine="mkdir 2>NUL "$(WebKitOutputDir)\include\JavaScriptCore"

xcopy /y /d "$(ProjectDir)\..\..\wtf\*.h" "$(WebKitOutputDir)\include\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\wtf\unicode\*.h" "$(WebKitOutputDir)\include\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\wtf\unicode\icu\*.h" "$(WebKitOutputDir)\include\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\kjs\*.h" "$(WebKitOutputDir)\include\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\runtime\*.h" "$(WebKitOutputDir)\include\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\VM\*.h" "$(WebKitOutputDir)\include\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\masm\*.h" "$(WebKitOutputDir)\include\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\wrec\*.h" "$(WebKitOutputDir)\include\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\debugger\*.h" "$(WebKitOutputDir)\include\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\profiler\*.h" "$(WebKitOutputDir)\include\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\kjs\create_hash_table" "$(WebKitOutputDir)\include\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\pcre\pcre.h" "$(WebKitOutputDir)\include\JavaScriptCore"

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

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

if exist "$(WebKitOutputDir)\buildfailed" del "$(WebKitOutputDir)\buildfailed"
"
/>
</Configuration>
</Configurations>
@@ -266,7 +266,7 @@ </References>
<Files>
<Filter
- Name="KJS"
+ Name="JavaScriptCore"
>
<File
RelativePath="..\..\runtime\ArgList.cpp"
@@ -333,15 +333,23 @@ >
</File>
<File
+ RelativePath="..\..\interpreter\CallFrame.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\interpreter\CallFrame.h"
+ >
+ </File>
+ <File
RelativePath="..\..\runtime\ClassInfo.h"
>
</File>
<File
- RelativePath="..\..\kjs\collector.cpp"
+ RelativePath="..\..\runtime\Collector.cpp"
>
</File>
<File
- RelativePath="..\..\kjs\collector.h"
+ RelativePath="..\..\runtime\Collector.h"
>
</File>
<File
@@ -357,11 +365,15 @@ >
</File>
<File
- RelativePath="..\..\kjs\completion.h"
+ RelativePath="..\..\runtime\Completion.cpp"
>
</File>
<File
- RelativePath="..\..\kjs\config.h"
+ RelativePath="..\..\runtime\Completion.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\config.h"
>
</File>
<File
@@ -405,14 +417,6 @@ >
</File>
<File
- RelativePath="..\..\kjs\dtoa.cpp"
- >
- </File>
- <File
- RelativePath="..\..\kjs\dtoa.h"
- >
- </File>
- <File
RelativePath="..\..\runtime\Error.cpp"
>
</File>
@@ -445,14 +449,6 @@ >
</File>
<File
- RelativePath="..\..\runtime\ExecState.cpp"
- >
- </File>
- <File
- RelativePath="..\..\runtime\ExecState.h"
- >
- </File>
- <File
RelativePath="..\..\runtime\FunctionConstructor.cpp"
>
</File>
@@ -485,11 +481,11 @@ >
</File>
<File
- RelativePath="..\..\kjs\identifier.cpp"
+ RelativePath="..\..\runtime\Identifier.cpp"
>
</File>
<File
- RelativePath="..\..\kjs\identifier.h"
+ RelativePath="..\..\runtime\Identifier.h"
>
</File>
<File
@@ -509,11 +505,7 @@ >
</File>
<File
- RelativePath="..\..\kjs\interpreter.cpp"
- >
- </File>
- <File
- RelativePath="..\..\kjs\interpreter.h"
+ RelativePath="..\..\runtime\Interpreter.h"
>
</File>
<File
@@ -533,6 +525,14 @@ >
</File>
<File
+ RelativePath="..\..\runtime\JSByteArray.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\runtime\JSByteArray.h"
+ >
+ </File>
+ <File
RelativePath="..\..\runtime\JSCell.cpp"
>
</File>
@@ -657,15 +657,15 @@ >
</File>
<File
- RelativePath="..\..\kjs\LabelScope.h"
+ RelativePath="..\..\bytecompiler\LabelScope.h"
>
</File>
<File
- RelativePath="..\..\kjs\lookup.cpp"
+ RelativePath="..\..\runtime\Lookup.cpp"
>
</File>
<File
- RelativePath="..\..\kjs\lookup.h"
+ RelativePath="..\..\runtime\Lookup.h"
>
</File>
<File
@@ -693,7 +693,7 @@ >
</File>
<File
- RelativePath="..\..\kjs\NodeInfo.h"
+ RelativePath="..\..\parser\NodeInfo.h"
>
</File>
<File
@@ -737,11 +737,11 @@ >
</File>
<File
- RelativePath="..\..\kjs\operations.cpp"
+ RelativePath="..\..\runtime\Operations.cpp"
>
</File>
<File
- RelativePath="..\..\kjs\operations.h"
+ RelativePath="..\..\runtime\Operations.h"
>
</File>
<File
@@ -765,7 +765,7 @@ >
</File>
<File
- RelativePath="..\..\kjs\protect.h"
+ RelativePath="..\..\runtime\Protect.h"
>
</File>
<File
@@ -777,11 +777,11 @@ >
</File>
<File
- RelativePath="..\..\kjs\regexp.cpp"
+ RelativePath="..\..\runtime\RegExp.cpp"
>
</File>
<File
- RelativePath="..\..\kjs\regexp.h"
+ RelativePath="..\..\runtime\RegExp.h"
>
</File>
<File
@@ -829,11 +829,11 @@ >
</File>
<File
- RelativePath="..\..\kjs\SourceProvider.h"
+ RelativePath="..\..\parser\SourceCode.h"
>
</File>
<File
- RelativePath="..\..\kjs\SourceCode.h"
+ RelativePath="..\..\parser\SourceProvider.h"
>
</File>
<File
@@ -865,23 +865,23 @@ >
</File>
<File
- RelativePath="..\..\runtime\StructureID.cpp"
+ RelativePath="..\..\runtime\Structure.cpp"
>
</File>
<File
- RelativePath="..\..\runtime\StructureID.h"
+ RelativePath="..\..\runtime\Structure.h"
>
</File>
<File
- RelativePath="..\..\runtime\StructureIDChain.cpp"
+ RelativePath="..\..\runtime\StructureChain.cpp"
>
</File>
<File
- RelativePath="..\..\runtime\StructureIDChain.h"
+ RelativePath="..\..\runtime\StructureChain.h"
>
</File>
<File
- RelativePath="..\..\runtime\StructureIDTransitionTable.h"
+ RelativePath="..\..\runtime\StructureTransitionTable.h"
>
</File>
<File
@@ -889,11 +889,11 @@ >
</File>
<File
- RelativePath="..\..\kjs\ustring.cpp"
+ RelativePath="..\..\runtime\UString.cpp"
>
</File>
<File
- RelativePath="..\..\kjs\ustring.h"
+ RelativePath="..\..\runtime\UString.h"
>
</File>
<Filter
@@ -908,7 +908,7 @@ >
</File>
<File
- RelativePath="$(WebKitOutputDir)\obj\$(ProjectName)\DerivedSources\grammar.cpp"
+ RelativePath="$(WebKitOutputDir)\obj\$(ProjectName)\DerivedSources\Grammar.cpp"
>
<FileConfiguration
Name="Debug|Win32"
@@ -945,7 +945,7 @@ </FileConfiguration>
</File>
<File
- RelativePath="$(WebKitOutputDir)\obj\$(ProjectName)\DerivedSources\grammar.h"
+ RelativePath="$(WebKitOutputDir)\obj\$(ProjectName)\DerivedSources\Grammar.h"
>
</File>
<File
@@ -1186,27 +1186,27 @@ Name="Compiler"
>
<File
- RelativePath="..\..\VM\CodeGenerator.cpp"
+ RelativePath="..\..\bytecompiler\BytecodeGenerator.cpp"
>
</File>
<File
- RelativePath="..\..\VM\CodeGenerator.h"
+ RelativePath="..\..\bytecompiler\BytecodeGenerator.h"
>
</File>
<File
- RelativePath="..\..\VM\LabelID.h"
+ RelativePath="..\..\bytecompiler\Label.h"
>
</File>
<File
- RelativePath="..\..\kjs\lexer.cpp"
+ RelativePath="..\..\parser\Lexer.cpp"
>
</File>
<File
- RelativePath="..\..\kjs\lexer.h"
+ RelativePath="..\..\parser\Lexer.h"
>
</File>
<File
- RelativePath="..\..\kjs\nodes.cpp"
+ RelativePath="..\..\parser\Nodes.cpp"
>
<FileConfiguration
Name="Release_PGO|Win32"
@@ -1218,111 +1218,111 @@ </FileConfiguration>
</File>
<File
- RelativePath="..\..\kjs\nodes.h"
+ RelativePath="..\..\parser\Nodes.h"
>
</File>
<File
- RelativePath="..\..\kjs\nodes2string.cpp"
+ RelativePath="..\..\parser\Parser.cpp"
>
</File>
<File
- RelativePath="..\..\kjs\Parser.cpp"
+ RelativePath="..\..\parser\Parser.h"
>
</File>
<File
- RelativePath="..\..\kjs\Parser.h"
+ RelativePath="..\..\bytecompiler\RegisterID.h"
>
</File>
<File
- RelativePath="..\..\VM\RegisterID.h"
- >
- </File>
- <File
- RelativePath="..\..\VM\SegmentedVector.h"
+ RelativePath="..\..\bytecompiler\SegmentedVector.h"
>
</File>
</Filter>
<Filter
- Name="VM"
+ Name="bytecode"
>
<File
- RelativePath="..\..\VM\CodeBlock.cpp"
+ RelativePath="..\..\bytecode\StructureStubInfo.cpp"
>
</File>
<File
- RelativePath="..\..\VM\CodeBlock.h"
+ RelativePath="..\..\bytecode\StructureStubInfo.h"
>
</File>
<File
- RelativePath="..\..\VM\CTI.cpp"
+ RelativePath="..\..\bytecode\CodeBlock.cpp"
>
- <FileConfiguration
- Name="Release_PGO|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- WholeProgramOptimization="false"
- />
- </FileConfiguration>
</File>
<File
- RelativePath="..\..\VM\CTI.h"
+ RelativePath="..\..\bytecode\CodeBlock.h"
>
</File>
<File
- RelativePath="..\..\VM\ExceptionHelpers.cpp"
+ RelativePath="..\..\bytecode\JumpTable.cpp"
>
</File>
<File
- RelativePath="..\..\VM\ExceptionHelpers.h"
+ RelativePath="..\..\bytecode\JumpTable.h"
>
</File>
<File
- RelativePath="..\..\VM\Instruction.h"
+ RelativePath="..\..\bytecode\EvalCodeCache.h"
>
</File>
<File
- RelativePath="..\..\runtime\JSPropertyNameIterator.cpp"
+ RelativePath="..\..\runtime\ExceptionHelpers.cpp"
>
</File>
<File
- RelativePath="..\..\runtime\JSPropertyNameIterator.h"
+ RelativePath="..\..\interpreter\ExceptionHelpers.h"
>
</File>
<File
- RelativePath="..\..\VM\Machine.cpp"
+ RelativePath="..\..\bytecode\Instruction.h"
>
</File>
<File
- RelativePath="..\..\VM\Machine.h"
+ RelativePath="..\..\interpreter\Interpreter.cpp"
>
</File>
<File
- RelativePath="..\..\VM\Opcode.cpp"
+ RelativePath="..\..\interpreter\Interpreter.h"
>
</File>
<File
- RelativePath="..\..\VM\Opcode.h"
+ RelativePath="..\..\runtime\JSPropertyNameIterator.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\runtime\JSPropertyNameIterator.h"
>
</File>
<File
- RelativePath="..\..\VM\Register.h"
+ RelativePath="..\..\bytecode\Opcode.cpp"
>
</File>
<File
- RelativePath="..\..\VM\RegisterFile.cpp"
+ RelativePath="..\..\bytecode\Opcode.h"
>
</File>
<File
- RelativePath="..\..\VM\RegisterFile.h"
+ RelativePath="..\..\interpreter\Register.h"
>
</File>
<File
- RelativePath="..\..\VM\SamplingTool.cpp"
+ RelativePath="..\..\interpreter\RegisterFile.cpp"
>
</File>
<File
- RelativePath="..\..\VM\SamplingTool.h"
+ RelativePath="..\..\interpreter\RegisterFile.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\bytecode\SamplingTool.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\bytecode\SamplingTool.h"
>
</File>
</Filter>
@@ -1338,6 +1338,14 @@ >
</File>
<File
+ RelativePath="..\..\debugger\DebuggerActivation.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\debugger\DebuggerActivation.h"
+ >
+ </File>
+ <File
RelativePath="..\..\debugger\DebuggerCallFrame.cpp"
>
</File>
@@ -1347,10 +1355,14 @@ </File>
</Filter>
<Filter
- Name="masm"
+ Name="assembler"
>
<File
- RelativePath="..\..\masm\X86Assembler.h"
+ RelativePath="..\..\assembler\AssemblerBuffer.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\assembler\X86Assembler.h"
>
</File>
</Filter>
@@ -1358,6 +1370,14 @@ Name="wrec"
>
<File
+ RelativePath="..\..\wrec\CharacterClass.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\wrec\CharacterClass.h"
+ >
+ </File>
+ <File
RelativePath="..\..\wrec\CharacterClassConstructor.cpp"
>
</File>
@@ -1366,6 +1386,10 @@ >
</File>
<File
+ RelativePath="..\..\wrec\Quantifier.h"
+ >
+ </File>
+ <File
RelativePath="..\..\wrec\WREC.cpp"
>
</File>
@@ -1373,6 +1397,102 @@ RelativePath="..\..\wrec\WREC.h"
>
</File>
+ <File
+ RelativePath="..\..\wrec\WRECFunctors.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\wrec\WRECFunctors.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\wrec\WRECGenerator.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\wrec\WRECGenerator.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\wrec\WRECParser.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\wrec\WRECParser.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="jit"
+ >
+ <File
+ RelativePath="..\..\jit\JIT.cpp"
+ >
+ <FileConfiguration
+ Name="Release_PGO|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ WholeProgramOptimization="false"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\jit\JIT.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\jit\ExecutableAllocator.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\jit\ExecutableAllocatorWin.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\jit\ExecutableAllocator.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\jit\JITArithmetic.cpp"
+ >
+ <FileConfiguration
+ Name="Release_PGO|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ WholeProgramOptimization="false"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\jit\JITCall.cpp"
+ >
+ <FileConfiguration
+ Name="Release_PGO|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ WholeProgramOptimization="false"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\jit\JITInlineMethods.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\jit\JITPropertyAccess.cpp"
+ >
+ <FileConfiguration
+ Name="Release_PGO|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ WholeProgramOptimization="false"
+ />
+ </FileConfiguration>
+ </File>
</Filter>
</Files>
<Globals>
diff --git a/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTF.vcproj b/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTF.vcproj index 29d7a51..3934b15 100644 --- a/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTF.vcproj +++ b/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTF.vcproj @@ -1,7 +1,7 @@ -<?xml version="1.0" encoding="Windows-1252"?>
+<?xml version="1.0" encoding="windows-1251"?>
<VisualStudioProject
ProjectType="Visual C++"
- Version="8.00"
+ Version="8,00"
Name="WTF"
ProjectGUID="{AA8A5A85-592B-4357-BC60-E0E91E026AF6}"
RootNamespace="WTF"
@@ -42,7 +42,7 @@ />
<Tool
Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""$(WebKitOutputDir)\obj\JavaScriptCore\$(ConfigurationName)\DerivedSources\";../../;"../../os-win32/";../../pcre/;../../kjs/;../../wtf/;../../wtf/unicode/;"$(WebKitLibrariesDir)\include";"$(WebKitLibrariesDir)\include\icu";../../../icu/include;../../bindings;../../bindings/c;../../bindings/jni;"$(WebKitOutputDir)\include\JavaScriptCore";"$(WebKitLibrariesDir)\include\pthreads""
+ AdditionalIncludeDirectories=""$(WebKitOutputDir)\obj\JavaScriptCore\$(ConfigurationName)\DerivedSources\";../../;"../../os-win32/";../../pcre/;../../parser/;../../wtf/;../../wtf/unicode/;"$(WebKitLibrariesDir)\include";"$(WebKitLibrariesDir)\include\icu";../../../icu/include;../../bindings;../../bindings/c;../../bindings/jni;"$(WebKitOutputDir)\include\JavaScriptCore";"$(WebKitLibrariesDir)\include\pthreads""
PreprocessorDefinitions="__STD_C"
ForcedIncludeFiles=""
/>
@@ -105,7 +105,7 @@ />
<Tool
Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""$(WebKitOutputDir)\obj\JavaScriptCore\$(ConfigurationName)\DerivedSources\";../../;"../../os-win32/";../../pcre/;../../kjs/;../../wtf/;../../wtf/unicode/;"$(WebKitLibrariesDir)\include";"$(WebKitLibrariesDir)\include\icu";../../../icu/include;../../bindings;../../bindings/c;../../bindings/jni;"$(WebKitOutputDir)\include\JavaScriptCore";"$(WebKitLibrariesDir)\include\pthreads""
+ AdditionalIncludeDirectories=""$(WebKitOutputDir)\obj\JavaScriptCore\$(ConfigurationName)\DerivedSources\";../../;"../../os-win32/";../../pcre/;../../parser/;../../wtf/;../../wtf/unicode/;"$(WebKitLibrariesDir)\include";"$(WebKitLibrariesDir)\include\icu";../../../icu/include;../../bindings;../../bindings/c;../../bindings/jni;"$(WebKitOutputDir)\include\JavaScriptCore";"$(WebKitLibrariesDir)\include\pthreads""
PreprocessorDefinitions="__STD_C"
ForcedIncludeFiles=""
/>
@@ -167,7 +167,7 @@ />
<Tool
Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""$(WebKitOutputDir)\obj\JavaScriptCore\$(ConfigurationName)\DerivedSources\";../../;"../../os-win32/";../../pcre/;../../kjs/;../../wtf/;../../wtf/unicode/;"$(WebKitLibrariesDir)\include";"$(WebKitLibrariesDir)\include\icu";../../../icu/include;../../bindings;../../bindings/c;../../bindings/jni;"$(WebKitOutputDir)\include\JavaScriptCore";"$(WebKitLibrariesDir)\include\pthreads""
+ AdditionalIncludeDirectories=""$(WebKitOutputDir)\obj\JavaScriptCore\$(ConfigurationName)\DerivedSources\";../../;"../../os-win32/";../../pcre/;../../parser/;../../wtf/;../../wtf/unicode/;"$(WebKitLibrariesDir)\include";"$(WebKitLibrariesDir)\include\icu";../../../icu/include;../../bindings;../../bindings/c;../../bindings/jni;"$(WebKitOutputDir)\include\JavaScriptCore";"$(WebKitLibrariesDir)\include\pthreads""
PreprocessorDefinitions="__STD_C"
ForcedIncludeFiles=""
/>
@@ -230,6 +230,14 @@ RelativePath="..\..\wtf\Assertions.h"
>
</File>
+ <File
+ RelativePath="..\..\wtf\ByteArray.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\wtf\ByteArray.h"
+ >
+ </File>
<File
RelativePath="..\..\wtf\unicode\Collator.h"
>
@@ -243,10 +251,26 @@ >
</File>
<File
+ RelativePath="..\..\wtf\CurrentTime.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\wtf\CurrentTime.h"
+ >
+ </File>
+ <File
RelativePath="..\..\wtf\Deque.h"
>
</File>
<File
+ RelativePath="..\..\wtf\dtoa.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\wtf\dtoa.h"
+ >
+ </File>
+ <File
RelativePath="..\..\wtf\FastMalloc.cpp"
>
</File>
@@ -351,6 +375,22 @@ >
</File>
<File
+ RelativePath="..\..\wtf\PtrAndFlags.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\wtf\RandomNumber.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\wtf\RandomNumber.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\wtf\RandomNumberSeed.h"
+ >
+ </File>
+ <File
RelativePath="..\..\wtf\RefCounted.h"
>
</File>
@@ -371,6 +411,10 @@ >
</File>
<File
+ RelativePath="..\..\wtf\StdLibExtras.h"
+ >
+ </File>
+ <File
RelativePath="..\..\wtf\StringExtras.h"
>
</File>
@@ -395,6 +439,10 @@ >
</File>
<File
+ RelativePath="..\..\wtf\Threading.cpp"
+ >
+ </File>
+ <File
RelativePath="..\..\wtf\Threading.h"
>
</File>
@@ -407,6 +455,10 @@ >
</File>
<File
+ RelativePath="..\..\wtf\ThreadSpecificWin.cpp"
+ >
+ </File>
+ <File
RelativePath="..\..\wtf\unicode\Unicode.h"
>
</File>
diff --git a/JavaScriptCore/JavaScriptCore.vcproj/jsc/jsc.vcproj b/JavaScriptCore/JavaScriptCore.vcproj/jsc/jsc.vcproj index 4d2a32d..0b3a006 100644 --- a/JavaScriptCore/JavaScriptCore.vcproj/jsc/jsc.vcproj +++ b/JavaScriptCore/JavaScriptCore.vcproj/jsc/jsc.vcproj @@ -39,7 +39,7 @@ />
<Tool
Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""$(WebKitOutputDir)\include";"$(WebKitOutputDir)\obj\JavaScriptCore\$(ConfigurationName)\DerivedSources\";../../;"../../os-win32/";../../pcre/;../../kjs/;../../runtime/;../../VM/;../../wtf/;../../debugger/;"$(WebKitLibrariesDir)\include\icu";"$(WebKitLibrariesDir)\include\pthreads";../../../icu/include;"$(WebKitLibrariesDir)\include""
+ AdditionalIncludeDirectories=""$(WebKitOutputDir)\include";"$(WebKitOutputDir)\obj\JavaScriptCore\$(ConfigurationName)\DerivedSources\";../../;"../../os-win32/";../../pcre/;../../assembler/;../../wrec/;../../parser/;../../runtime/;../../VM/;../../bytecode/;../../interpreter/;../../wtf/;../../debugger/;../../bytecompiler/;"$(WebKitLibrariesDir)\include\icu";"$(WebKitLibrariesDir)\include\pthreads";../../../icu/include;"$(WebKitLibrariesDir)\include";../../jit/"
PreprocessorDefinitions="__STD_C"
/>
<Tool
@@ -109,7 +109,7 @@ />
<Tool
Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""$(WebKitOutputDir)\include";"$(WebKitOutputDir)\obj\JavaScriptCore\$(ConfigurationName)\DerivedSources\";../../;"../../os-win32/";../../pcre/;../../kjs/;../../runtime/;../../VM/;../../wtf/;../../debugger/;"$(WebKitLibrariesDir)\include\icu";"$(WebKitLibrariesDir)\include\pthreads";../../../icu/include;"$(WebKitLibrariesDir)\include""
+ AdditionalIncludeDirectories=""$(WebKitOutputDir)\include";"$(WebKitOutputDir)\obj\JavaScriptCore\$(ConfigurationName)\DerivedSources\";../../;"../../os-win32/";../../pcre/;../../assembler/;../../wrec/;../../parser/;../../runtime/;../../VM/;../../bytecode/;../../interpreter/;../../wtf/;../../debugger/;../../bytecompiler/;"$(WebKitLibrariesDir)\include\icu";"$(WebKitLibrariesDir)\include\pthreads";../../../icu/include;"$(WebKitLibrariesDir)\include";../../jit/"
PreprocessorDefinitions="__STD_C"
/>
<Tool
@@ -178,7 +178,7 @@ />
<Tool
Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""$(WebKitOutputDir)\include";"$(WebKitOutputDir)\obj\JavaScriptCore\$(ConfigurationName)\DerivedSources\";../../;"../../os-win32/";../../pcre/;../../kjs/;../../runtime/;../../VM/;../../wtf/;../../debugger/;"$(WebKitLibrariesDir)\include\icu";"$(WebKitLibrariesDir)\include\pthreads";../../../icu/include;"$(WebKitLibrariesDir)\include""
+ AdditionalIncludeDirectories=""$(WebKitOutputDir)\include";"$(WebKitOutputDir)\obj\JavaScriptCore\$(ConfigurationName)\DerivedSources\";../../;"../../os-win32/";../../pcre/;../../assembler/;../../wrec/;../../parser/;../../runtime/;../../VM/;../../bytecode/;../../interpreter/;../../wtf/;../../debugger/;../../bytecompiler/;"$(WebKitLibrariesDir)\include\icu";"$(WebKitLibrariesDir)\include\pthreads";../../../icu/include;"$(WebKitLibrariesDir)\include";../../jit/"
PreprocessorDefinitions="__STD_C"
/>
<Tool
@@ -228,7 +228,7 @@ </References>
<Files>
<File
- RelativePath="..\..\kjs\Shell.cpp"
+ RelativePath="..\..\jsc.cpp"
>
</File>
</Files>
diff --git a/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj b/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj index df4bfed..3c02898 100644 --- a/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj +++ b/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj @@ -36,11 +36,33 @@ /* 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 */; }; + 088FA5BC0EF76D4300578E6F /* RandomNumber.h in Headers */ = {isa = PBXBuildFile; fileRef = 088FA5BA0EF76D4300578E6F /* RandomNumber.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 08E279E90EF83B10007DB523 /* RandomNumberSeed.h in Headers */ = {isa = PBXBuildFile; fileRef = 08E279E80EF83B10007DB523 /* RandomNumberSeed.h */; }; + 0B1F921D0F1753500036468E /* PtrAndFlags.h in Headers */ = {isa = PBXBuildFile; fileRef = 0B1F921B0F17502D0036468E /* PtrAndFlags.h */; settings = {ATTRIBUTES = (Private, ); }; }; 140B7D1D0DC69AF7009C42B8 /* JSActivation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 14DA818F0D99FD2000B0A4FB /* JSActivation.cpp */; }; 140D17D70E8AD4A9000CD17D /* JSBasePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 140D17D60E8AD4A9000CD17D /* JSBasePrivate.h */; settings = {ATTRIBUTES = (Private, ); }; }; 141211310A48794D00480255 /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 932F5BD90822A1C700736975 /* JavaScriptCore.framework */; }; 141211340A48795800480255 /* minidom.c in Sources */ = {isa = PBXBuildFile; fileRef = 141211020A48780900480255 /* minidom.c */; }; 1421359B0A677F4F00A8195E /* JSBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1421359A0A677F4F00A8195E /* JSBase.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"; }; }; + 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 */; }; + 1429D8DD0ED2205B00B89619 /* CallFrame.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1429D8DB0ED2205B00B89619 /* CallFrame.cpp */; }; + 1429D8DE0ED2205B00B89619 /* CallFrame.h in Headers */ = {isa = PBXBuildFile; fileRef = 1429D8DC0ED2205B00B89619 /* CallFrame.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 1429D92F0ED22D7000B89619 /* JIT.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1429D92D0ED22D7000B89619 /* JIT.cpp */; }; + 1429D9300ED22D7000B89619 /* JIT.h in Headers */ = {isa = PBXBuildFile; fileRef = 1429D92E0ED22D7000B89619 /* JIT.h */; }; + 1429D9C40ED23C3900B89619 /* CharacterClass.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1429D9C20ED23C3900B89619 /* CharacterClass.cpp */; }; + 1429D9C50ED23C3900B89619 /* CharacterClass.h in Headers */ = {isa = PBXBuildFile; fileRef = 1429D9C30ED23C3900B89619 /* CharacterClass.h */; }; + 1429DA4A0ED245EC00B89619 /* Quantifier.h in Headers */ = {isa = PBXBuildFile; fileRef = 1429DA490ED245EC00B89619 /* Quantifier.h */; }; + 1429DA820ED2482900B89619 /* WRECFunctors.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1429DA800ED2482900B89619 /* WRECFunctors.cpp */; }; + 1429DA830ED2482900B89619 /* WRECFunctors.h in Headers */ = {isa = PBXBuildFile; fileRef = 1429DA810ED2482900B89619 /* WRECFunctors.h */; }; + 1429DABF0ED263E700B89619 /* WRECParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 1429DABD0ED263E700B89619 /* WRECParser.h */; }; + 1429DAC00ED263E700B89619 /* WRECParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1429DABE0ED263E700B89619 /* WRECParser.cpp */; }; + 1429DAE00ED2645B00B89619 /* WRECGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 1429DADE0ED2645B00B89619 /* WRECGenerator.h */; }; + 1429DAE10ED2645B00B89619 /* WRECGenerator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1429DADF0ED2645B00B89619 /* WRECGenerator.cpp */; }; 143A97E60A4A06E200456B66 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6560A4CF04B3B3E7008AE952 /* CoreFoundation.framework */; }; 1440057F0A5335640005F061 /* JSNode.c in Sources */ = {isa = PBXBuildFile; fileRef = 1440F6420A4F8B6A0005F061 /* JSNode.c */; }; 144005CB0A5338D10005F061 /* JSNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 1440F6410A4F8B6A0005F061 /* JSNode.h */; }; @@ -59,22 +81,21 @@ 147B84630E6DE6B1004775A4 /* PutPropertySlot.h in Headers */ = {isa = PBXBuildFile; fileRef = 147B84620E6DE6B1004775A4 /* PutPropertySlot.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 */; }; - 14909A2D0DCAF6CD00B29EB3 /* ExecState.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 14BD53F40A3E12D800BAF59C /* ExecState.cpp */; }; 149559EE0DDCDDF700648087 /* DebuggerCallFrame.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 149559ED0DDCDDF700648087 /* DebuggerCallFrame.cpp */; }; - 149B15EB0D81F986009CB8C7 /* Opcode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 149B15E50D81F986009CB8C7 /* Opcode.cpp */; }; - 149B1AA00D86ED73009CB8C7 /* CodeBlock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 149B1A9E0D86ED73009CB8C7 /* CodeBlock.cpp */; }; 14ABDF600A437FEF00ECCA01 /* JSCallbackObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 14ABDF5E0A437FEF00ECCA01 /* JSCallbackObject.cpp */; }; 14B8EC720A5652090062BE54 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6560A4CF04B3B3E7008AE952 /* CoreFoundation.framework */; }; 14BD59C50A3E8F9F00BAF59C /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 932F5BD90822A1C700736975 /* JavaScriptCore.framework */; }; 14BD5A300A3E91F600BAF59C /* JSContextRef.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 14BD5A290A3E91F600BAF59C /* JSContextRef.cpp */; }; 14BD5A320A3E91F600BAF59C /* JSValueRef.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 14BD5A2B0A3E91F600BAF59C /* JSValueRef.cpp */; }; - 14E0FF120DBAAED00007C0AB /* Machine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 149B15E70D81F986009CB8C7 /* Machine.cpp */; settings = {COMPILER_FLAGS = "-fno-tree-pre"; }; }; 14F3488F0E95EF8A003648BC /* CollectorHeapIterator.h in Headers */ = {isa = PBXBuildFile; fileRef = 14F3488E0E95EF8A003648BC /* CollectorHeapIterator.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 180B9B080F16D94F009BDBC5 /* CurrentTime.h in Headers */ = {isa = PBXBuildFile; fileRef = 180B9AF00F16C569009BDBC5 /* CurrentTime.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 180B9BFE0F16E94D009BDBC5 /* CurrentTime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 180B9AEF0F16C569009BDBC5 /* CurrentTime.cpp */; }; 1C61516C0EBAC7A00031376F /* ProfilerServer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1C61516A0EBAC7A00031376F /* ProfilerServer.mm */; settings = {COMPILER_FLAGS = "-fno-strict-aliasing"; }; }; 1C61516D0EBAC7A00031376F /* ProfilerServer.h in Headers */ = {isa = PBXBuildFile; fileRef = 1C61516B0EBAC7A00031376F /* ProfilerServer.h */; }; 5D53726F0E1C54880021E549 /* Tracing.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D53726E0E1C54880021E549 /* Tracing.h */; }; 5D5D8AB60E0D0A7200F9C692 /* jsc in Copy Into Framework */ = {isa = PBXBuildFile; fileRef = 932F5BE10822A1C700736975 /* jsc */; }; 5D5D8AD10E0D0EBE00F9C692 /* libedit.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 5D5D8AD00E0D0EBE00F9C692 /* libedit.dylib */; }; + 5D6A566B0F05995500266145 /* Threading.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5D6A566A0F05995500266145 /* Threading.cpp */; }; 5DE6E5B30E1728EC00180407 /* create_hash_table in Headers */ = {isa = PBXBuildFile; fileRef = F692A8540255597D01FF60F7 /* create_hash_table */; settings = {ATTRIBUTES = (Private, ); }; }; 6507D29E0E871E5E00D7D896 /* TypeInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 6507D2970E871E4A00D7D896 /* TypeInfo.h */; settings = {ATTRIBUTES = (Private, ); }; }; 659126BD0BDD1728001921FB /* AllInOneFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 659126BC0BDD1728001921FB /* AllInOneFile.cpp */; }; @@ -82,17 +103,17 @@ 65FDE49C0BDD1D4A00E80111 /* Assertions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 65E217B808E7EECC0023E5F6 /* Assertions.cpp */; settings = {COMPILER_FLAGS = "-Wno-missing-format-attribute"; }; }; 7E2ADD8E0E79AAD500D50C51 /* CharacterClassConstructor.h in Headers */ = {isa = PBXBuildFile; fileRef = 7E2ADD8D0E79AAD500D50C51 /* CharacterClassConstructor.h */; }; 7E2ADD900E79AC1100D50C51 /* CharacterClassConstructor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7E2ADD8F0E79AC1100D50C51 /* CharacterClassConstructor.cpp */; }; - 7E4EE7090EBB7963005934AA /* StructureIDChain.h in Headers */ = {isa = PBXBuildFile; fileRef = 7E4EE7080EBB7963005934AA /* StructureIDChain.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 7E4EE70F0EBB7A5B005934AA /* StructureIDChain.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7E4EE70E0EBB7A5B005934AA /* StructureIDChain.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 */; }; - 8613F45A0E3A433E00C948FD /* SamplingTool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8613F4580E3A433E00C948FD /* SamplingTool.cpp */; }; - 8613F45B0E3A433E00C948FD /* SamplingTool.h in Headers */ = {isa = PBXBuildFile; fileRef = 8613F4590E3A433E00C948FD /* SamplingTool.h */; }; - 8683B02E0E636482004C19EE /* CTI.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8683B02B0E636482004C19EE /* CTI.cpp */; }; - 8683B02F0E636482004C19EE /* CTI.h in Headers */ = {isa = PBXBuildFile; fileRef = 8683B02C0E636482004C19EE /* CTI.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 869081410E640C89000D36ED /* X86Assembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 869081400E640C89000D36ED /* X86Assembler.h */; settings = {ATTRIBUTES = (Private, ); }; }; 869083150E6518D7000D36ED /* WREC.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 869083130E6518D7000D36ED /* WREC.cpp */; }; 869083160E6518D7000D36ED /* WREC.h in Headers */ = {isa = PBXBuildFile; fileRef = 869083140E6518D7000D36ED /* WREC.h */; settings = {ATTRIBUTES = (Private, ); }; }; 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 */; }; + 86C36EEA0EE1289D00B3DF59 /* MacroAssembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 86C36EE90EE1289D00B3DF59 /* MacroAssembler.h */; }; + 86CC85A10EE79A4700288682 /* JITInlineMethods.h in Headers */ = {isa = PBXBuildFile; fileRef = 86CC85A00EE79A4700288682 /* JITInlineMethods.h */; }; + 86CC85A30EE79B7400288682 /* JITCall.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86CC85A20EE79B7400288682 /* JITCall.cpp */; }; + 86CC85C40EE7A89400288682 /* JITPropertyAccess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86CC85C30EE7A89400288682 /* JITPropertyAccess.cpp */; }; 905B02AE0E28640F006DF882 /* RefCountedLeakCounter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 905B02AD0E28640F006DF882 /* RefCountedLeakCounter.cpp */; }; 90D3469C0E285280009492EE /* RefCountedLeakCounter.h in Headers */ = {isa = PBXBuildFile; fileRef = 90D3469B0E285280009492EE /* RefCountedLeakCounter.h */; settings = {ATTRIBUTES = (Private, ); }; }; 930754C108B0F68000AB3056 /* pcre_compile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 930754BF08B0F68000AB3056 /* pcre_compile.cpp */; }; @@ -103,7 +124,7 @@ 932F5BD50822A1C700736975 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 51F0EB6105C86C6B00E6DF1B /* Foundation.framework */; }; 932F5BD60822A1C700736975 /* libobjc.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 51F0EC0705C86C9A00E6DF1B /* libobjc.dylib */; }; 932F5BD70822A1C700736975 /* libicucore.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 9322A00306C341D3009067BB /* libicucore.dylib */; }; - 932F5BDD0822A1C700736975 /* Shell.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 45E12D8806A49B0F00E9DF84 /* Shell.cpp */; }; + 932F5BDD0822A1C700736975 /* jsc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 45E12D8806A49B0F00E9DF84 /* jsc.cpp */; }; 932F5BEA0822A1C700736975 /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 932F5BD90822A1C700736975 /* JavaScriptCore.framework */; }; 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 */; }; @@ -122,11 +143,29 @@ 95FDFA140E22998F0006FB00 /* HeavyProfile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 95FDFA130E22998F0006FB00 /* HeavyProfile.cpp */; }; 95FDFA160E2299980006FB00 /* HeavyProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 95FDFA150E2299980006FB00 /* HeavyProfile.h */; }; 960097A60EBABB58007A7297 /* LabelScope.h in Headers */ = {isa = PBXBuildFile; fileRef = 960097A50EBABB58007A7297 /* LabelScope.h */; }; + 9688CB150ED12B4E001D649F /* AssemblerBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = 9688CB130ED12B4E001D649F /* AssemblerBuffer.h */; }; + 9688CB160ED12B4E001D649F /* X86Assembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 9688CB140ED12B4E001D649F /* X86Assembler.h */; }; + 969A07230ED1CE3300F1F681 /* BytecodeGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 969A07210ED1CE3300F1F681 /* BytecodeGenerator.h */; }; + 969A072A0ED1CE6900F1F681 /* Label.h in Headers */ = {isa = PBXBuildFile; fileRef = 969A07270ED1CE6900F1F681 /* Label.h */; }; + 969A072B0ED1CE6900F1F681 /* RegisterID.h in Headers */ = {isa = PBXBuildFile; fileRef = 969A07280ED1CE6900F1F681 /* RegisterID.h */; }; + 969A072C0ED1CE6900F1F681 /* SegmentedVector.h in Headers */ = {isa = PBXBuildFile; fileRef = 969A07290ED1CE6900F1F681 /* SegmentedVector.h */; }; + 969A07960ED1D3AE00F1F681 /* CodeBlock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 969A07900ED1D3AE00F1F681 /* CodeBlock.cpp */; }; + 969A07970ED1D3AE00F1F681 /* CodeBlock.h in Headers */ = {isa = PBXBuildFile; fileRef = 969A07910ED1D3AE00F1F681 /* CodeBlock.h */; settings = {ATTRIBUTES = (); }; }; + 969A07980ED1D3AE00F1F681 /* EvalCodeCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 969A07920ED1D3AE00F1F681 /* EvalCodeCache.h */; }; + 969A07990ED1D3AE00F1F681 /* Instruction.h in Headers */ = {isa = PBXBuildFile; fileRef = 969A07930ED1D3AE00F1F681 /* Instruction.h */; }; + 969A079A0ED1D3AE00F1F681 /* Opcode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 969A07940ED1D3AE00F1F681 /* Opcode.cpp */; }; + 969A079B0ED1D3AE00F1F681 /* Opcode.h in Headers */ = {isa = PBXBuildFile; fileRef = 969A07950ED1D3AE00F1F681 /* Opcode.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 96A746410EDDF70600904779 /* Escapes.h in Headers */ = {isa = PBXBuildFile; fileRef = 96A7463F0EDDF70600904779 /* Escapes.h */; }; A72700900DAC6BBC00E548D7 /* JSNotAnObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A72700780DAC605600E548D7 /* JSNotAnObject.cpp */; }; - A72701B60DADE94900E548D7 /* ExceptionHelpers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A72701B40DADE94900E548D7 /* ExceptionHelpers.cpp */; }; A72701B90DADE94900E548D7 /* ExceptionHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = A72701B30DADE94900E548D7 /* ExceptionHelpers.h */; }; A727FF6B0DA3092200E548D7 /* JSPropertyNameIterator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A727FF660DA3053B00E548D7 /* JSPropertyNameIterator.cpp */; }; - A7C31DAA0DBEBA4300FDF8EB /* SegmentedVector.h in Headers */ = {isa = PBXBuildFile; fileRef = A7C31DA80DBEBA4300FDF8EB /* SegmentedVector.h */; }; + A766B44F0EE8DCD1009518CA /* ExecutableAllocator.h in Headers */ = {isa = PBXBuildFile; fileRef = A7B48DB50EE74CFC00DCBDB6 /* ExecutableAllocator.h */; settings = {ATTRIBUTES = (Private, ); }; }; + A782F1A50EEC9FA20036273F /* ExecutableAllocatorPosix.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A782F1A40EEC9FA20036273F /* ExecutableAllocatorPosix.cpp */; }; + 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 */; }; + A7A1F7AD0F252B3C00E184E2 /* ByteArray.h in Headers */ = {isa = PBXBuildFile; fileRef = A7A1F7AB0F252B3C00E184E2 /* ByteArray.h */; settings = {ATTRIBUTES = (Private, ); }; }; + A7B48F490EE8936F00DCBDB6 /* ExecutableAllocator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7B48DB60EE74CFC00DCBDB6 /* ExecutableAllocator.cpp */; }; 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 */; }; @@ -144,12 +183,10 @@ BC18C3EB0E16F5CD00B34460 /* AVLTree.h in Headers */ = {isa = PBXBuildFile; fileRef = E1A596370DE3E1C300C17E37 /* AVLTree.h */; }; BC18C3EC0E16F5CD00B34460 /* BooleanObject.h in Headers */ = {isa = PBXBuildFile; fileRef = 704FD35305697E6D003DBED9 /* BooleanObject.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C3ED0E16F5CD00B34460 /* CallData.h in Headers */ = {isa = PBXBuildFile; fileRef = 145C507F0D9DF63B0088F6B9 /* CallData.h */; settings = {ATTRIBUTES = (Private, ); }; }; - BC18C3EE0E16F5CD00B34460 /* CodeBlock.h in Headers */ = {isa = PBXBuildFile; fileRef = 149B1A9D0D86ED73009CB8C7 /* CodeBlock.h */; }; - BC18C3EF0E16F5CD00B34460 /* CodeGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 149B15E80D81F986009CB8C7 /* CodeGenerator.h */; }; BC18C3F00E16F5CD00B34460 /* Collator.h in Headers */ = {isa = PBXBuildFile; fileRef = E1A862AA0D7EBB7D001EC6AA /* Collator.h */; settings = {ATTRIBUTES = (Private, ); }; }; - BC18C3F10E16F5CD00B34460 /* collector.h in Headers */ = {isa = PBXBuildFile; fileRef = F692A8530255597D01FF60F7 /* collector.h */; settings = {ATTRIBUTES = (Private, ); }; }; + BC18C3F10E16F5CD00B34460 /* Collector.h in Headers */ = {isa = PBXBuildFile; fileRef = F692A8530255597D01FF60F7 /* Collector.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C3F30E16F5CD00B34460 /* CommonIdentifiers.h in Headers */ = {isa = PBXBuildFile; fileRef = 65EA73630BAE35D1001BB560 /* CommonIdentifiers.h */; settings = {ATTRIBUTES = (Private, ); }; }; - BC18C3F40E16F5CD00B34460 /* completion.h in Headers */ = {isa = PBXBuildFile; fileRef = F5BB2BC5030F772101FCFE1D /* completion.h */; settings = {ATTRIBUTES = (Private, ); }; }; + BC18C3F40E16F5CD00B34460 /* Completion.h in Headers */ = {isa = PBXBuildFile; fileRef = F5BB2BC5030F772101FCFE1D /* Completion.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C3F50E16F5CD00B34460 /* config.h in Headers */ = {isa = PBXBuildFile; fileRef = F68EBB8C0255D4C601FF60F7 /* config.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C3F60E16F5CD00B34460 /* ConstructData.h in Headers */ = {isa = PBXBuildFile; fileRef = BC8F3CCF0DAF17BA00577A80 /* ConstructData.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C3F90E16F5CD00B34460 /* DateMath.h in Headers */ = {isa = PBXBuildFile; fileRef = D21202290AD4310C00ED79B6 /* DateMath.h */; }; @@ -159,7 +196,6 @@ BC18C3FD0E16F5CD00B34460 /* DisallowCType.h in Headers */ = {isa = PBXBuildFile; fileRef = 938C4F6B0CA06BCE00D9310A /* DisallowCType.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C3FE0E16F5CD00B34460 /* dtoa.h in Headers */ = {isa = PBXBuildFile; fileRef = 651F6413039D5B5F0078395C /* dtoa.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C4000E16F5CD00B34460 /* ExceptionHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = A72701B30DADE94900E548D7 /* ExceptionHelpers.h */; }; - BC18C4010E16F5CD00B34460 /* ExecState.h in Headers */ = {isa = PBXBuildFile; fileRef = 14BD53F30A3E12D800BAF59C /* ExecState.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C4020E16F5CD00B34460 /* FastMalloc.h in Headers */ = {isa = PBXBuildFile; fileRef = 65E217BA08E7EECC0023E5F6 /* FastMalloc.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C4030E16F5CD00B34460 /* Forward.h in Headers */ = {isa = PBXBuildFile; fileRef = 935AF46909E9D9DB00ACD1D8 /* Forward.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C4040E16F5CD00B34460 /* FunctionConstructor.h in Headers */ = {isa = PBXBuildFile; fileRef = BC2680C10E16D4E900A06E92 /* FunctionConstructor.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -172,14 +208,12 @@ BC18C40C0E16F5CD00B34460 /* HashSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 65DFC92C08EA173A00F7300B /* HashSet.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C40D0E16F5CD00B34460 /* HashTable.h in Headers */ = {isa = PBXBuildFile; fileRef = 65DFC92E08EA173A00F7300B /* HashTable.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C40E0E16F5CD00B34460 /* HashTraits.h in Headers */ = {isa = PBXBuildFile; fileRef = 65DFC92F08EA173A00F7300B /* HashTraits.h */; settings = {ATTRIBUTES = (Private, ); }; }; - BC18C40F0E16F5CD00B34460 /* identifier.h in Headers */ = {isa = PBXBuildFile; fileRef = 933A349A038AE7C6008635CE /* identifier.h */; settings = {ATTRIBUTES = (Private, ); }; }; + BC18C40F0E16F5CD00B34460 /* Identifier.h in Headers */ = {isa = PBXBuildFile; fileRef = 933A349A038AE7C6008635CE /* Identifier.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C4100E16F5CD00B34460 /* InitializeThreading.h in Headers */ = {isa = PBXBuildFile; fileRef = E178633F0D9BEC0000D74E75 /* InitializeThreading.h */; settings = {ATTRIBUTES = (Private, ); }; }; - BC18C4110E16F5CD00B34460 /* Instruction.h in Headers */ = {isa = PBXBuildFile; fileRef = 149B1AA10D86ED7C009CB8C7 /* Instruction.h */; }; - BC18C4120E16F5CD00B34460 /* interpreter.h in Headers */ = {isa = PBXBuildFile; fileRef = F692A8640255597D01FF60F7 /* interpreter.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C4130E16F5CD00B34460 /* JavaScript.h in Headers */ = {isa = PBXBuildFile; fileRef = 1CAA8B4A0D32C39A0041BCFF /* JavaScript.h */; settings = {ATTRIBUTES = (Public, ); }; }; BC18C4140E16F5CD00B34460 /* JavaScriptCore.h in Headers */ = {isa = PBXBuildFile; fileRef = 1CAA8B4B0D32C39A0041BCFF /* JavaScriptCore.h */; settings = {ATTRIBUTES = (Public, ); }; }; BC18C4150E16F5CD00B34460 /* JavaScriptCorePrefix.h in Headers */ = {isa = PBXBuildFile; fileRef = F5C290E60284F98E018635CA /* JavaScriptCorePrefix.h */; }; - BC18C4160E16F5CD00B34460 /* JSActivation.h in Headers */ = {isa = PBXBuildFile; fileRef = 14DA818E0D99FD2000B0A4FB /* JSActivation.h */; }; + BC18C4160E16F5CD00B34460 /* JSActivation.h in Headers */ = {isa = PBXBuildFile; fileRef = 14DA818E0D99FD2000B0A4FB /* JSActivation.h */; settings = {ATTRIBUTES = (); }; }; BC18C4170E16F5CD00B34460 /* JSArray.h in Headers */ = {isa = PBXBuildFile; fileRef = 938772E5038BFE19008635CE /* JSArray.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C4180E16F5CD00B34460 /* JSBase.h in Headers */ = {isa = PBXBuildFile; fileRef = 142711380A460BBB0080EEEA /* JSBase.h */; settings = {ATTRIBUTES = (Public, ); }; }; BC18C4190E16F5CD00B34460 /* JSCallbackConstructor.h in Headers */ = {isa = PBXBuildFile; fileRef = 1440F8AC0A508D200005F061 /* JSCallbackConstructor.h */; }; @@ -204,19 +238,17 @@ BC18C42C0E16F5CD00B34460 /* JSValueRef.h in Headers */ = {isa = PBXBuildFile; fileRef = 1482B6EA0A4300B300517CFC /* JSValueRef.h */; settings = {ATTRIBUTES = (Public, ); }; }; BC18C42D0E16F5CD00B34460 /* JSVariableObject.h in Headers */ = {isa = PBXBuildFile; fileRef = 14F252560D08DD8D004ECFFF /* JSVariableObject.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C42E0E16F5CD00B34460 /* JSWrapperObject.h in Headers */ = {isa = PBXBuildFile; fileRef = 65C7A1720A8EAACB00FA37EA /* JSWrapperObject.h */; settings = {ATTRIBUTES = (Private, ); }; }; - BC18C42F0E16F5CD00B34460 /* LabelID.h in Headers */ = {isa = PBXBuildFile; fileRef = 149B20D70D8A0891009CB8C7 /* LabelID.h */; }; - BC18C4310E16F5CD00B34460 /* lexer.h in Headers */ = {isa = PBXBuildFile; fileRef = F692A8660255597D01FF60F7 /* lexer.h */; }; + BC18C4310E16F5CD00B34460 /* Lexer.h in Headers */ = {isa = PBXBuildFile; fileRef = F692A8660255597D01FF60F7 /* Lexer.h */; }; BC18C4340E16F5CD00B34460 /* ListHashSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 657EB7450B708F540063461B /* ListHashSet.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C4350E16F5CD00B34460 /* ListRefPtr.h in Headers */ = {isa = PBXBuildFile; fileRef = 148A1626095D16BB00666D0D /* ListRefPtr.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C4360E16F5CD00B34460 /* Locker.h in Headers */ = {isa = PBXBuildFile; fileRef = E1EE79270D6C964500FEA3BA /* Locker.h */; settings = {ATTRIBUTES = (Private, ); }; }; - BC18C4370E16F5CD00B34460 /* lookup.h in Headers */ = {isa = PBXBuildFile; fileRef = F692A8690255597D01FF60F7 /* lookup.h */; settings = {ATTRIBUTES = (Private, ); }; }; - BC18C4380E16F5CD00B34460 /* Machine.h in Headers */ = {isa = PBXBuildFile; fileRef = 149B15E60D81F986009CB8C7 /* Machine.h */; settings = {ATTRIBUTES = (Private, ); }; }; + BC18C4370E16F5CD00B34460 /* Lookup.h in Headers */ = {isa = PBXBuildFile; fileRef = F692A8690255597D01FF60F7 /* Lookup.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C4390E16F5CD00B34460 /* MainThread.h in Headers */ = {isa = PBXBuildFile; fileRef = 06D358A30DAAD9C4003B174E /* MainThread.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C43A0E16F5CD00B34460 /* MallocZoneSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = 5DBD18AF0C5401A700C15EAE /* MallocZoneSupport.h */; }; BC18C43B0E16F5CD00B34460 /* MathExtras.h in Headers */ = {isa = PBXBuildFile; fileRef = BCF6553B0A2048DE0038A194 /* MathExtras.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C43C0E16F5CD00B34460 /* MathObject.h in Headers */ = {isa = PBXBuildFile; fileRef = F692A86B0255597D01FF60F7 /* MathObject.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C43E0E16F5CD00B34460 /* MessageQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = E1EE798B0D6CA53D00FEA3BA /* MessageQueue.h */; settings = {ATTRIBUTES = (Private, ); }; }; - BC18C43F0E16F5CD00B34460 /* nodes.h in Headers */ = {isa = PBXBuildFile; fileRef = F692A86E0255597D01FF60F7 /* nodes.h */; settings = {ATTRIBUTES = (Private, ); }; }; + BC18C43F0E16F5CD00B34460 /* Nodes.h in Headers */ = {isa = PBXBuildFile; fileRef = F692A86E0255597D01FF60F7 /* Nodes.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C4400E16F5CD00B34460 /* Noncopyable.h in Headers */ = {isa = PBXBuildFile; fileRef = 9303F5690991190000AD71B8 /* Noncopyable.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C4410E16F5CD00B34460 /* NumberConstructor.h in Headers */ = {isa = PBXBuildFile; fileRef = BC2680C30E16D4E900A06E92 /* NumberConstructor.h */; }; BC18C4420E16F5CD00B34460 /* NumberConstructor.lut.h in Headers */ = {isa = PBXBuildFile; fileRef = BC2680E60E16D52300A06E92 /* NumberConstructor.lut.h */; }; @@ -224,8 +256,7 @@ BC18C4440E16F5CD00B34460 /* NumberPrototype.h in Headers */ = {isa = PBXBuildFile; fileRef = BC2680C50E16D4E900A06E92 /* NumberPrototype.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C4450E16F5CD00B34460 /* ObjectConstructor.h in Headers */ = {isa = PBXBuildFile; fileRef = BC2680C70E16D4E900A06E92 /* ObjectConstructor.h */; }; BC18C4460E16F5CD00B34460 /* ObjectPrototype.h in Headers */ = {isa = PBXBuildFile; fileRef = BC2680C90E16D4E900A06E92 /* ObjectPrototype.h */; settings = {ATTRIBUTES = (Private, ); }; }; - BC18C4470E16F5CD00B34460 /* Opcode.h in Headers */ = {isa = PBXBuildFile; fileRef = 149B15E40D81F986009CB8C7 /* Opcode.h */; settings = {ATTRIBUTES = (Private, ); }; }; - BC18C4480E16F5CD00B34460 /* operations.h in Headers */ = {isa = PBXBuildFile; fileRef = F692A8780255597D01FF60F7 /* operations.h */; settings = {ATTRIBUTES = (Private, ); }; }; + BC18C4480E16F5CD00B34460 /* Operations.h in Headers */ = {isa = PBXBuildFile; fileRef = F692A8780255597D01FF60F7 /* Operations.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C4490E16F5CD00B34460 /* OwnArrayPtr.h in Headers */ = {isa = PBXBuildFile; fileRef = 9303F5A409911A5800AD71B8 /* OwnArrayPtr.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C44A0E16F5CD00B34460 /* OwnPtr.h in Headers */ = {isa = PBXBuildFile; fileRef = 9303F567099118FA00AD71B8 /* OwnPtr.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C44B0E16F5CD00B34460 /* Parser.h in Headers */ = {isa = PBXBuildFile; fileRef = 93F0B3AA09BB4DC00068FCE3 /* Parser.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -238,18 +269,16 @@ BC18C4520E16F5CD00B34460 /* Profiler.h in Headers */ = {isa = PBXBuildFile; fileRef = 95AB832F0DA42CAD00BC83F3 /* Profiler.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C4540E16F5CD00B34460 /* PropertyNameArray.h in Headers */ = {isa = PBXBuildFile; fileRef = 65400C100A69BAF200509887 /* PropertyNameArray.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C4550E16F5CD00B34460 /* PropertySlot.h in Headers */ = {isa = PBXBuildFile; fileRef = 65621E6C089E859700760F35 /* PropertySlot.h */; settings = {ATTRIBUTES = (Private, ); }; }; - BC18C4560E16F5CD00B34460 /* protect.h in Headers */ = {isa = PBXBuildFile; fileRef = 65C02FBB0637462A003E7EE6 /* protect.h */; settings = {ATTRIBUTES = (Private, ); }; }; + BC18C4560E16F5CD00B34460 /* Protect.h in Headers */ = {isa = PBXBuildFile; fileRef = 65C02FBB0637462A003E7EE6 /* Protect.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C4570E16F5CD00B34460 /* RefCounted.h in Headers */ = {isa = PBXBuildFile; fileRef = 1419D32C0CEA7CDE00FF507A /* RefCounted.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C4580E16F5CD00B34460 /* RefPtr.h in Headers */ = {isa = PBXBuildFile; fileRef = 65C647B3093EF8D60022C380 /* RefPtr.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C4590E16F5CD00B34460 /* RefPtrHashMap.h in Headers */ = {isa = PBXBuildFile; fileRef = 148A1ECD0D10C23B0069A47C /* RefPtrHashMap.h */; settings = {ATTRIBUTES = (Private, ); }; }; - BC18C45A0E16F5CD00B34460 /* regexp.h in Headers */ = {isa = PBXBuildFile; fileRef = F692A87E0255597D01FF60F7 /* regexp.h */; settings = {ATTRIBUTES = (Private, ); }; }; + BC18C45A0E16F5CD00B34460 /* RegExp.h in Headers */ = {isa = PBXBuildFile; fileRef = F692A87E0255597D01FF60F7 /* RegExp.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C45B0E16F5CD00B34460 /* RegExpObject.h in Headers */ = {isa = PBXBuildFile; fileRef = F692A87C0255597D01FF60F7 /* RegExpObject.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C45D0E16F5CD00B34460 /* Register.h in Headers */ = {isa = PBXBuildFile; fileRef = 149B24FF0D8AF6D1009CB8C7 /* Register.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C45E0E16F5CD00B34460 /* RegisterFile.h in Headers */ = {isa = PBXBuildFile; fileRef = 14D792640DAA03FB001A9F05 /* RegisterFile.h */; settings = {ATTRIBUTES = (Private, ); }; }; - BC18C45F0E16F5CD00B34460 /* RegisterID.h in Headers */ = {isa = PBXBuildFile; fileRef = 149B16B80D82583F009CB8C7 /* RegisterID.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C4600E16F5CD00B34460 /* RetainPtr.h in Headers */ = {isa = PBXBuildFile; fileRef = 51F648D60BB4E2CA0033D760 /* RetainPtr.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C4610E16F5CD00B34460 /* ScopeChain.h in Headers */ = {isa = PBXBuildFile; fileRef = 9374D3A7038D9D74008635CE /* ScopeChain.h */; settings = {ATTRIBUTES = (Private, ); }; }; - BC18C4620E16F5CD00B34460 /* SegmentedVector.h in Headers */ = {isa = PBXBuildFile; fileRef = A7C31DA80DBEBA4300FDF8EB /* SegmentedVector.h */; }; BC18C4630E16F5CD00B34460 /* SourceProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = 65E866ED0DD59AFA00A2B2A1 /* SourceProvider.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C4640E16F5CD00B34460 /* SourceCode.h in Headers */ = {isa = PBXBuildFile; fileRef = 65E866EE0DD59AFA00A2B2A1 /* SourceCode.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C4660E16F5CD00B34460 /* StringConstructor.h in Headers */ = {isa = PBXBuildFile; fileRef = BC18C3C10E16EE3300B34460 /* StringConstructor.h */; }; @@ -268,7 +297,7 @@ BC18C4730E16F5CD00B34460 /* Unicode.h in Headers */ = {isa = PBXBuildFile; fileRef = E195679409E7CF1200B89D13 /* Unicode.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C4740E16F5CD00B34460 /* UnicodeIcu.h in Headers */ = {isa = PBXBuildFile; fileRef = E195678F09E7CF1200B89D13 /* UnicodeIcu.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C4750E16F5CD00B34460 /* UnusedParam.h in Headers */ = {isa = PBXBuildFile; fileRef = 935AF46B09E9D9DB00ACD1D8 /* UnusedParam.h */; settings = {ATTRIBUTES = (Private, ); }; }; - BC18C4760E16F5CD00B34460 /* ustring.h in Headers */ = {isa = PBXBuildFile; fileRef = F692A8860255597D01FF60F7 /* ustring.h */; settings = {ATTRIBUTES = (Private, ); }; }; + BC18C4760E16F5CD00B34460 /* UString.h in Headers */ = {isa = PBXBuildFile; fileRef = F692A8860255597D01FF60F7 /* UString.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C4770E16F5CD00B34460 /* UTF8.h in Headers */ = {isa = PBXBuildFile; fileRef = E1EF79A90CE97BA60088D500 /* UTF8.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C4780E16F5CD00B34460 /* Vector.h in Headers */ = {isa = PBXBuildFile; fileRef = 6592C316098B7DE10003D4F6 /* Vector.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C4790E16F5CD00B34460 /* VectorTraits.h in Headers */ = {isa = PBXBuildFile; fileRef = 6592C317098B7DE10003D4F6 /* VectorTraits.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -283,20 +312,26 @@ BC257DF00E1F52ED0016B6C9 /* GlobalEvalFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = BC257DEE0E1F52ED0016B6C9 /* GlobalEvalFunction.h */; }; BC257DF40E1F53740016B6C9 /* PrototypeFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = BC257DF20E1F53740016B6C9 /* PrototypeFunction.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC3046070E1F497F003232CF /* Error.h in Headers */ = {isa = PBXBuildFile; fileRef = BC3046060E1F497F003232CF /* Error.h */; settings = {ATTRIBUTES = (Private, ); }; }; + BC3135640F302FA3003DFD3A /* DebuggerActivation.h in Headers */ = {isa = PBXBuildFile; fileRef = BC3135620F302FA3003DFD3A /* DebuggerActivation.h */; settings = {ATTRIBUTES = (Private, ); }; }; + BC3135650F302FA3003DFD3A /* DebuggerActivation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC3135630F302FA3003DFD3A /* DebuggerActivation.cpp */; }; BC6AAAE50E1F426500AD87D8 /* ClassInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = BC6AAAE40E1F426500AD87D8 /* ClassInfo.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC756FC90E2031B200DE7D12 /* JSGlobalObjectFunctions.h in Headers */ = {isa = PBXBuildFile; fileRef = BC756FC70E2031B200DE7D12 /* JSGlobalObjectFunctions.h */; }; BC7F8FB90E19D1C3008632C0 /* JSNumberCell.h in Headers */ = {isa = PBXBuildFile; fileRef = BC7F8FB80E19D1C3008632C0 /* JSNumberCell.h */; settings = {ATTRIBUTES = (Private, ); }; }; - BC9041480EB9250900FE26FA /* StructureIDTransitionTable.h in Headers */ = {isa = PBXBuildFile; fileRef = BC9041470EB9250900FE26FA /* StructureIDTransitionTable.h */; settings = {ATTRIBUTES = (Private, ); }; }; + BC9041480EB9250900FE26FA /* StructureTransitionTable.h in Headers */ = {isa = PBXBuildFile; fileRef = BC9041470EB9250900FE26FA /* StructureTransitionTable.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC95437D0EBA70FD0072B6D3 /* PropertyMapHashTable.h in Headers */ = {isa = PBXBuildFile; fileRef = BC95437C0EBA70FD0072B6D3 /* PropertyMapHashTable.h */; settings = {ATTRIBUTES = (Private, ); }; }; + BCCF0D080EF0AAB900413C8F /* StructureStubInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = BCCF0D070EF0AAB900413C8F /* StructureStubInfo.h */; }; + BCCF0D0C0EF0B8A500413C8F /* StructureStubInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCCF0D0B0EF0B8A500413C8F /* StructureStubInfo.cpp */; }; BCD202C20E1706A7002C7E82 /* RegExpConstructor.h in Headers */ = {isa = PBXBuildFile; fileRef = BCD202BE0E1706A7002C7E82 /* RegExpConstructor.h */; }; BCD202C40E1706A7002C7E82 /* RegExpPrototype.h in Headers */ = {isa = PBXBuildFile; fileRef = BCD202C00E1706A7002C7E82 /* RegExpPrototype.h */; }; BCD202D60E170708002C7E82 /* RegExpConstructor.lut.h in Headers */ = {isa = PBXBuildFile; fileRef = BCD202D50E170708002C7E82 /* RegExpConstructor.lut.h */; }; BCD2034A0E17135E002C7E82 /* DateConstructor.h in Headers */ = {isa = PBXBuildFile; fileRef = BCD203460E17135E002C7E82 /* DateConstructor.h */; }; BCD2034C0E17135E002C7E82 /* DatePrototype.h in Headers */ = {isa = PBXBuildFile; fileRef = BCD203480E17135E002C7E82 /* DatePrototype.h */; }; BCD203E80E1718F4002C7E82 /* DatePrototype.lut.h in Headers */ = {isa = PBXBuildFile; fileRef = BCD203E70E1718F4002C7E82 /* DatePrototype.lut.h */; }; - BCDE3AB80E6C82F5001453A7 /* StructureID.h in Headers */ = {isa = PBXBuildFile; fileRef = BCDE3AB10E6C82CF001453A7 /* StructureID.h */; settings = {ATTRIBUTES = (Private, ); }; }; - BCDE3B430E6C832D001453A7 /* StructureID.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCDE3AB00E6C82CF001453A7 /* StructureID.cpp */; }; + BCDE3AB80E6C82F5001453A7 /* Structure.h in Headers */ = {isa = PBXBuildFile; fileRef = BCDE3AB10E6C82CF001453A7 /* Structure.h */; settings = {ATTRIBUTES = (Private, ); }; }; + BCDE3B430E6C832D001453A7 /* Structure.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCDE3AB00E6C82CF001453A7 /* Structure.cpp */; }; BCF605140E203EF800B9A64D /* ArgList.h in Headers */ = {isa = PBXBuildFile; fileRef = BCF605120E203EF800B9A64D /* ArgList.h */; settings = {ATTRIBUTES = (Private, ); }; }; + BCFD8C920EEB2EE700283848 /* JumpTable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCFD8C900EEB2EE700283848 /* JumpTable.cpp */; }; + BCFD8C930EEB2EE700283848 /* JumpTable.h in Headers */ = {isa = PBXBuildFile; fileRef = BCFD8C910EEB2EE700283848 /* JumpTable.h */; }; C0A272630E50A06300E96E15 /* NotFound.h in Headers */ = {isa = PBXBuildFile; fileRef = C0A2723F0E509F1E00E96E15 /* NotFound.h */; settings = {ATTRIBUTES = (Private, ); }; }; 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 */; }; @@ -306,6 +341,7 @@ 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 */; }; + FE1B447A0ECCD73B004F4DD1 /* StdLibExtras.h in Headers */ = {isa = PBXBuildFile; fileRef = FE1B44790ECCD73B004F4DD1 /* StdLibExtras.h */; settings = {ATTRIBUTES = (Private, ); }; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -385,6 +421,10 @@ 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>"; }; + 088FA5B90EF76D4300578E6F /* RandomNumber.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RandomNumber.cpp; sourceTree = "<group>"; }; + 088FA5BA0EF76D4300578E6F /* RandomNumber.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RandomNumber.h; sourceTree = "<group>"; }; + 08E279E80EF83B10007DB523 /* RandomNumberSeed.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RandomNumberSeed.h; sourceTree = "<group>"; }; + 0B1F921B0F17502D0036468E /* PtrAndFlags.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PtrAndFlags.h; sourceTree = "<group>"; }; 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>"; }; @@ -392,6 +432,25 @@ 1419D32C0CEA7CDE00FF507A /* RefCounted.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RefCounted.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>"; }; + 1429D77B0ED20D7300B89619 /* Interpreter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Interpreter.h; sourceTree = "<group>"; }; + 1429D7D30ED2128200B89619 /* Interpreter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Interpreter.cpp; sourceTree = "<group>"; }; + 1429D85B0ED218E900B89619 /* RegisterFile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RegisterFile.cpp; sourceTree = "<group>"; }; + 1429D8770ED21ACD00B89619 /* ExceptionHelpers.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ExceptionHelpers.cpp; sourceTree = "<group>"; }; + 1429D8830ED21C3D00B89619 /* SamplingTool.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SamplingTool.cpp; sourceTree = "<group>"; }; + 1429D8840ED21C3D00B89619 /* SamplingTool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SamplingTool.h; sourceTree = "<group>"; }; + 1429D8DB0ED2205B00B89619 /* CallFrame.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CallFrame.cpp; sourceTree = "<group>"; }; + 1429D8DC0ED2205B00B89619 /* CallFrame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CallFrame.h; sourceTree = "<group>"; }; + 1429D92D0ED22D7000B89619 /* JIT.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JIT.cpp; sourceTree = "<group>"; }; + 1429D92E0ED22D7000B89619 /* JIT.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JIT.h; sourceTree = "<group>"; }; + 1429D9C20ED23C3900B89619 /* CharacterClass.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CharacterClass.cpp; sourceTree = "<group>"; }; + 1429D9C30ED23C3900B89619 /* CharacterClass.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CharacterClass.h; sourceTree = "<group>"; }; + 1429DA490ED245EC00B89619 /* Quantifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Quantifier.h; sourceTree = "<group>"; }; + 1429DA800ED2482900B89619 /* WRECFunctors.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WRECFunctors.cpp; sourceTree = "<group>"; }; + 1429DA810ED2482900B89619 /* WRECFunctors.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WRECFunctors.h; sourceTree = "<group>"; }; + 1429DABD0ED263E700B89619 /* WRECParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WRECParser.h; sourceTree = "<group>"; }; + 1429DABE0ED263E700B89619 /* WRECParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WRECParser.cpp; sourceTree = "<group>"; }; + 1429DADE0ED2645B00B89619 /* WRECGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WRECGenerator.h; sourceTree = "<group>"; }; + 1429DADF0ED2645B00B89619 /* WRECGenerator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WRECGenerator.cpp; sourceTree = "<group>"; }; 1440051F0A531D3B0005F061 /* Node.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Node.h; path = tests/Node.h; sourceTree = "<group>"; }; 144005200A531D3B0005F061 /* Node.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = Node.c; path = tests/Node.c; sourceTree = "<group>"; }; 144007480A536CC20005F061 /* NodeList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NodeList.h; path = tests/NodeList.h; sourceTree = "<group>"; }; @@ -423,39 +482,27 @@ 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>"; }; 149559ED0DDCDDF700648087 /* DebuggerCallFrame.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DebuggerCallFrame.cpp; sourceTree = "<group>"; }; - 149B15E40D81F986009CB8C7 /* Opcode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Opcode.h; path = VM/Opcode.h; sourceTree = "<group>"; }; - 149B15E50D81F986009CB8C7 /* Opcode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Opcode.cpp; path = VM/Opcode.cpp; sourceTree = "<group>"; }; - 149B15E60D81F986009CB8C7 /* Machine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Machine.h; path = VM/Machine.h; sourceTree = "<group>"; }; - 149B15E70D81F986009CB8C7 /* Machine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Machine.cpp; path = VM/Machine.cpp; sourceTree = "<group>"; }; - 149B15E80D81F986009CB8C7 /* CodeGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CodeGenerator.h; path = VM/CodeGenerator.h; sourceTree = "<group>"; }; - 149B15E90D81F986009CB8C7 /* CodeGenerator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CodeGenerator.cpp; path = VM/CodeGenerator.cpp; sourceTree = "<group>"; }; - 149B16B80D82583F009CB8C7 /* RegisterID.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterID.h; path = VM/RegisterID.h; sourceTree = "<group>"; }; - 149B1A9D0D86ED73009CB8C7 /* CodeBlock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CodeBlock.h; path = VM/CodeBlock.h; sourceTree = "<group>"; }; - 149B1A9E0D86ED73009CB8C7 /* CodeBlock.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CodeBlock.cpp; path = VM/CodeBlock.cpp; sourceTree = "<group>"; }; - 149B1AA10D86ED7C009CB8C7 /* Instruction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Instruction.h; path = VM/Instruction.h; sourceTree = "<group>"; }; - 149B20D70D8A0891009CB8C7 /* LabelID.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LabelID.h; path = VM/LabelID.h; sourceTree = "<group>"; }; - 149B24FF0D8AF6D1009CB8C7 /* Register.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Register.h; path = VM/Register.h; sourceTree = "<group>"; }; + 149B24FF0D8AF6D1009CB8C7 /* Register.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Register.h; sourceTree = "<group>"; }; 14A396A60CD2933100B5B4FF /* SymbolTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SymbolTable.h; sourceTree = "<group>"; }; 14ABB36E099C076400E2A24F /* JSValue.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = JSValue.h; sourceTree = "<group>"; }; 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>"; }; 14B8ECA60A5653980062BE54 /* JavaScriptCore.exp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.exports; path = JavaScriptCore.exp; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; }; - 14BD53F30A3E12D800BAF59C /* ExecState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExecState.h; sourceTree = "<group>"; }; - 14BD53F40A3E12D800BAF59C /* ExecState.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ExecState.cpp; sourceTree = "<group>"; }; 14BD59BF0A3E8F9000BAF59C /* testapi */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = testapi; sourceTree = BUILT_PRODUCTS_DIR; }; 14BD5A290A3E91F600BAF59C /* JSContextRef.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = JSContextRef.cpp; sourceTree = "<group>"; }; 14BD5A2A0A3E91F600BAF59C /* JSContextRef.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = JSContextRef.h; sourceTree = "<group>"; }; 14BD5A2B0A3E91F600BAF59C /* JSValueRef.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = JSValueRef.cpp; sourceTree = "<group>"; }; 14BD5A2D0A3E91F600BAF59C /* testapi.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = testapi.c; path = API/tests/testapi.c; sourceTree = "<group>"; }; - 14D792640DAA03FB001A9F05 /* RegisterFile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterFile.h; path = VM/RegisterFile.h; sourceTree = "<group>"; }; - 14D792650DAA03FB001A9F05 /* RegisterFile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RegisterFile.cpp; path = VM/RegisterFile.cpp; sourceTree = "<group>"; }; + 14D792640DAA03FB001A9F05 /* RegisterFile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegisterFile.h; sourceTree = "<group>"; }; 14D857740A4696C80032146C /* testapi.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = testapi.js; path = API/tests/testapi.js; sourceTree = "<group>"; }; 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>"; }; 14F252560D08DD8D004ECFFF /* JSVariableObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSVariableObject.h; sourceTree = "<group>"; }; 14F3488E0E95EF8A003648BC /* CollectorHeapIterator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CollectorHeapIterator.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>"; }; 1C61516A0EBAC7A00031376F /* ProfilerServer.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = ProfilerServer.mm; path = profiler/ProfilerServer.mm; sourceTree = "<group>"; }; 1C61516B0EBAC7A00031376F /* ProfilerServer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ProfilerServer.h; path = profiler/ProfilerServer.h; sourceTree = "<group>"; }; 1C9051420BA9E8A70081E9D0 /* Version.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Version.xcconfig; sourceTree = "<group>"; }; @@ -464,15 +511,16 @@ 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>"; }; - 45E12D8806A49B0F00E9DF84 /* Shell.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Shell.cpp; path = kjs/Shell.cpp; sourceTree = "<group>"; tabWidth = 4; }; + 45E12D8806A49B0F00E9DF84 /* jsc.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = jsc.cpp; sourceTree = "<group>"; tabWidth = 4; }; 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 = sourcecode.dtrace; path = Tracing.d; 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>"; }; + 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>"; }; 5DBD18AF0C5401A700C15EAE /* MallocZoneSupport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MallocZoneSupport.h; sourceTree = "<group>"; }; 5DE3D0F40DD8DDFB00468714 /* WebKitAvailability.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebKitAvailability.h; sourceTree = "<group>"; }; @@ -498,7 +546,7 @@ 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>"; }; 65B174BE09D1000200820339 /* chartables.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.c; fileEncoding = 30; path = chartables.c; sourceTree = "<group>"; }; - 65C02FBB0637462A003E7EE6 /* protect.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = protect.h; sourceTree = "<group>"; tabWidth = 8; }; + 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>"; }; @@ -524,17 +572,17 @@ 7E2ADD8D0E79AAD500D50C51 /* CharacterClassConstructor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CharacterClassConstructor.h; sourceTree = "<group>"; }; 7E2ADD8F0E79AC1100D50C51 /* CharacterClassConstructor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CharacterClassConstructor.cpp; sourceTree = "<group>"; }; 7E2C6C980D31C6B6002D44E2 /* ScopeChainMark.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScopeChainMark.h; sourceTree = "<group>"; }; - 7E4EE7080EBB7963005934AA /* StructureIDChain.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StructureIDChain.h; sourceTree = "<group>"; }; - 7E4EE70E0EBB7A5B005934AA /* StructureIDChain.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StructureIDChain.cpp; sourceTree = "<group>"; }; - 7EFF00630EC05A9A00AA7C93 /* NodeInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NodeInfo.h; path = kjs/NodeInfo.h; sourceTree = "<group>"; }; - 8613F4580E3A433E00C948FD /* SamplingTool.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SamplingTool.cpp; path = VM/SamplingTool.cpp; sourceTree = "<group>"; }; - 8613F4590E3A433E00C948FD /* SamplingTool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SamplingTool.h; path = VM/SamplingTool.h; sourceTree = "<group>"; }; - 8683B02B0E636482004C19EE /* CTI.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CTI.cpp; path = VM/CTI.cpp; sourceTree = "<group>"; }; - 8683B02C0E636482004C19EE /* CTI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CTI.h; path = VM/CTI.h; sourceTree = "<group>"; }; - 869081400E640C89000D36ED /* X86Assembler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = X86Assembler.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>"; }; + 7EFF00630EC05A9A00AA7C93 /* NodeInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NodeInfo.h; sourceTree = "<group>"; }; 869083130E6518D7000D36ED /* WREC.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WREC.cpp; sourceTree = "<group>"; }; 869083140E6518D7000D36ED /* WREC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WREC.h; sourceTree = "<group>"; }; 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>"; }; + 86C36EE90EE1289D00B3DF59 /* MacroAssembler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MacroAssembler.h; sourceTree = "<group>"; }; + 86CC85A00EE79A4700288682 /* JITInlineMethods.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITInlineMethods.h; sourceTree = "<group>"; }; + 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>"; }; 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>"; }; 9303F567099118FA00AD71B8 /* OwnPtr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OwnPtr.h; sourceTree = "<group>"; }; @@ -549,9 +597,9 @@ 932F5BE10822A1C700736975 /* jsc */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = jsc; sourceTree = BUILT_PRODUCTS_DIR; }; 93303FE80E6A72B500786E6A /* SmallStrings.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SmallStrings.cpp; sourceTree = "<group>"; }; 93303FEA0E6A72C000786E6A /* SmallStrings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SmallStrings.h; sourceTree = "<group>"; }; - 933A3499038AE7C6008635CE /* grammar.y */ = {isa = PBXFileReference; explicitFileType = sourcecode.yacc; fileEncoding = 4; indentWidth = 4; path = grammar.y; sourceTree = "<group>"; tabWidth = 8; }; - 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; }; + 933A3499038AE7C6008635CE /* Grammar.y */ = {isa = PBXFileReference; explicitFileType = sourcecode.yacc; fileEncoding = 4; indentWidth = 4; path = Grammar.y; sourceTree = "<group>"; tabWidth = 8; }; + 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; }; 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>"; }; 937013470CA97E0E00FA14D3 /* pcre_ucp_searchfuncs.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = pcre_ucp_searchfuncs.cpp; sourceTree = "<group>"; }; @@ -568,9 +616,9 @@ 93E26BD308B1514100F85226 /* pcre_xclass.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = pcre_xclass.cpp; sourceTree = "<group>"; tabWidth = 8; }; 93E26BE508B1517100F85226 /* pcre_internal.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = pcre_internal.h; sourceTree = "<group>"; tabWidth = 8; }; 93E26BFC08B151D400F85226 /* ucpinternal.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = ucpinternal.h; sourceTree = "<group>"; tabWidth = 8; }; - 93F0B3A909BB4DC00068FCE3 /* Parser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Parser.cpp; path = kjs/Parser.cpp; sourceTree = "<group>"; }; - 93F0B3AA09BB4DC00068FCE3 /* Parser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Parser.h; path = kjs/Parser.h; sourceTree = "<group>"; }; - 93F1981A08245AAE001E9ABC /* keywords.table */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = text; path = keywords.table; sourceTree = "<group>"; tabWidth = 8; }; + 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>"; }; + 93F1981A08245AAE001E9ABC /* Keywords.table */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = text; path = Keywords.table; sourceTree = "<group>"; tabWidth = 8; }; 952C63AC0E4777D600C13936 /* JSProfilerPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSProfilerPrivate.h; sourceTree = "<group>"; }; 95742F630DD11F5A000917FB /* Profile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Profile.cpp; path = profiler/Profile.cpp; sourceTree = "<group>"; }; 95742F640DD11F5A000917FB /* Profile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Profile.h; path = profiler/Profile.h; sourceTree = "<group>"; }; @@ -587,14 +635,34 @@ 95E3BC040E1AE68200B2D1C1 /* CallIdentifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CallIdentifier.h; path = profiler/CallIdentifier.h; sourceTree = "<group>"; }; 95FDFA130E22998F0006FB00 /* HeavyProfile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = HeavyProfile.cpp; path = profiler/HeavyProfile.cpp; sourceTree = "<group>"; }; 95FDFA150E2299980006FB00 /* HeavyProfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HeavyProfile.h; path = profiler/HeavyProfile.h; sourceTree = "<group>"; }; - 960097A50EBABB58007A7297 /* LabelScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LabelScope.h; path = kjs/LabelScope.h; sourceTree = "<group>"; }; + 960097A50EBABB58007A7297 /* LabelScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LabelScope.h; sourceTree = "<group>"; }; + 9688CB130ED12B4E001D649F /* AssemblerBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AssemblerBuffer.h; sourceTree = "<group>"; }; + 9688CB140ED12B4E001D649F /* X86Assembler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = X86Assembler.h; sourceTree = "<group>"; }; + 969A07200ED1CE3300F1F681 /* BytecodeGenerator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BytecodeGenerator.cpp; sourceTree = "<group>"; }; + 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>"; }; + 969A07930ED1D3AE00F1F681 /* Instruction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Instruction.h; sourceTree = "<group>"; }; + 969A07940ED1D3AE00F1F681 /* Opcode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Opcode.cpp; sourceTree = "<group>"; }; + 969A07950ED1D3AE00F1F681 /* Opcode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Opcode.h; sourceTree = "<group>"; }; + 969A09220ED1E09C00F1F681 /* Completion.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Completion.cpp; sourceTree = "<group>"; }; + 96A7463F0EDDF70600904779 /* Escapes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Escapes.h; sourceTree = "<group>"; }; A72700770DAC605600E548D7 /* JSNotAnObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSNotAnObject.h; sourceTree = "<group>"; }; A72700780DAC605600E548D7 /* JSNotAnObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSNotAnObject.cpp; sourceTree = "<group>"; }; - A72701B30DADE94900E548D7 /* ExceptionHelpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ExceptionHelpers.h; path = VM/ExceptionHelpers.h; sourceTree = "<group>"; }; - A72701B40DADE94900E548D7 /* ExceptionHelpers.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ExceptionHelpers.cpp; path = VM/ExceptionHelpers.cpp; sourceTree = "<group>"; }; + A72701B30DADE94900E548D7 /* ExceptionHelpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExceptionHelpers.h; sourceTree = "<group>"; }; A727FF650DA3053B00E548D7 /* JSPropertyNameIterator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSPropertyNameIterator.h; sourceTree = "<group>"; }; A727FF660DA3053B00E548D7 /* JSPropertyNameIterator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSPropertyNameIterator.cpp; sourceTree = "<group>"; }; - A7C31DA80DBEBA4300FDF8EB /* SegmentedVector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SegmentedVector.h; path = VM/SegmentedVector.h; sourceTree = "<group>"; }; + A782F1A40EEC9FA20036273F /* ExecutableAllocatorPosix.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ExecutableAllocatorPosix.cpp; sourceTree = "<group>"; }; + A791EF260F11E07900AE1F68 /* JSByteArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSByteArray.h; sourceTree = "<group>"; }; + A791EF270F11E07900AE1F68 /* JSByteArray.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSByteArray.cpp; sourceTree = "<group>"; }; + A7A1F7AA0F252B3C00E184E2 /* ByteArray.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ByteArray.cpp; sourceTree = "<group>"; }; + A7A1F7AB0F252B3C00E184E2 /* ByteArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ByteArray.h; sourceTree = "<group>"; }; + A7B48DB50EE74CFC00DCBDB6 /* ExecutableAllocator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExecutableAllocator.h; sourceTree = "<group>"; }; + A7B48DB60EE74CFC00DCBDB6 /* ExecutableAllocator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ExecutableAllocator.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>"; }; A8E894310CD0602400367179 /* JSCallbackObjectFunctions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSCallbackObjectFunctions.h; sourceTree = "<group>"; }; @@ -650,6 +718,8 @@ BC2680C90E16D4E900A06E92 /* ObjectPrototype.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ObjectPrototype.h; sourceTree = "<group>"; }; BC2680E60E16D52300A06E92 /* NumberConstructor.lut.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NumberConstructor.lut.h; sourceTree = "<group>"; }; BC3046060E1F497F003232CF /* Error.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Error.h; sourceTree = "<group>"; }; + BC3135620F302FA3003DFD3A /* DebuggerActivation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DebuggerActivation.h; sourceTree = "<group>"; }; + BC3135630F302FA3003DFD3A /* DebuggerActivation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DebuggerActivation.cpp; sourceTree = "<group>"; }; 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>"; }; BC6AAAE40E1F426500AD87D8 /* ClassInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ClassInfo.h; sourceTree = "<group>"; }; @@ -664,11 +734,13 @@ BC7F8FB80E19D1C3008632C0 /* JSNumberCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSNumberCell.h; sourceTree = "<group>"; }; BC7F8FBA0E19D1EF008632C0 /* JSCell.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSCell.cpp; sourceTree = "<group>"; }; BC8F3CCF0DAF17BA00577A80 /* ConstructData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConstructData.h; sourceTree = "<group>"; }; - BC9041470EB9250900FE26FA /* StructureIDTransitionTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StructureIDTransitionTable.h; sourceTree = "<group>"; }; + BC9041470EB9250900FE26FA /* StructureTransitionTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StructureTransitionTable.h; sourceTree = "<group>"; }; BC95437C0EBA70FD0072B6D3 /* PropertyMapHashTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PropertyMapHashTable.h; sourceTree = "<group>"; }; BC9BB95B0E19680600DF8855 /* InternalFunction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InternalFunction.cpp; sourceTree = "<group>"; }; BCA62DFE0E2826230004F30D /* CallData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CallData.cpp; sourceTree = "<group>"; }; BCA62DFF0E2826310004F30D /* ConstructData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ConstructData.cpp; sourceTree = "<group>"; }; + BCCF0D070EF0AAB900413C8F /* StructureStubInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StructureStubInfo.h; sourceTree = "<group>"; }; + BCCF0D0B0EF0B8A500413C8F /* StructureStubInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StructureStubInfo.cpp; sourceTree = "<group>"; }; BCD202BD0E1706A7002C7E82 /* RegExpConstructor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RegExpConstructor.cpp; sourceTree = "<group>"; }; BCD202BE0E1706A7002C7E82 /* RegExpConstructor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegExpConstructor.h; sourceTree = "<group>"; }; BCD202BF0E1706A7002C7E82 /* RegExpPrototype.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RegExpPrototype.cpp; sourceTree = "<group>"; }; @@ -679,11 +751,13 @@ BCD203470E17135E002C7E82 /* DatePrototype.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DatePrototype.cpp; sourceTree = "<group>"; }; BCD203480E17135E002C7E82 /* DatePrototype.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DatePrototype.h; sourceTree = "<group>"; }; BCD203E70E1718F4002C7E82 /* DatePrototype.lut.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DatePrototype.lut.h; sourceTree = "<group>"; }; - BCDE3AB00E6C82CF001453A7 /* StructureID.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StructureID.cpp; sourceTree = "<group>"; }; - BCDE3AB10E6C82CF001453A7 /* StructureID.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StructureID.h; sourceTree = "<group>"; }; + BCDE3AB00E6C82CF001453A7 /* Structure.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Structure.cpp; sourceTree = "<group>"; }; + 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>"; }; + 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>"; }; D21202280AD4310C00ED79B6 /* DateMath.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = DateMath.cpp; sourceTree = "<group>"; }; D21202290AD4310C00ED79B6 /* DateMath.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DateMath.h; sourceTree = "<group>"; }; @@ -707,15 +781,14 @@ 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>"; }; - F5BB2BC5030F772101FCFE1D /* completion.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = completion.h; sourceTree = "<group>"; tabWidth = 8; }; + 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; }; - F5FFE656026B47A6018635CA /* nodes2string.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; name = nodes2string.cpp; path = kjs/nodes2string.cpp; sourceTree = "<group>"; tabWidth = 8; }; F68EBB8C0255D4C601FF60F7 /* config.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = config.h; sourceTree = "<group>"; tabWidth = 8; }; F692A84D0255597D01FF60F7 /* ArrayPrototype.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ArrayPrototype.cpp; sourceTree = "<group>"; tabWidth = 8; }; F692A84E0255597D01FF60F7 /* ArrayPrototype.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = ArrayPrototype.h; sourceTree = "<group>"; tabWidth = 8; }; F692A8500255597D01FF60F7 /* BooleanObject.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BooleanObject.cpp; sourceTree = "<group>"; tabWidth = 8; }; - F692A8520255597D01FF60F7 /* collector.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = collector.cpp; sourceTree = "<group>"; tabWidth = 8; }; - F692A8530255597D01FF60F7 /* collector.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = collector.h; sourceTree = "<group>"; tabWidth = 8; }; + F692A8520255597D01FF60F7 /* Collector.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Collector.cpp; sourceTree = "<group>"; tabWidth = 8; }; + F692A8530255597D01FF60F7 /* Collector.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = Collector.h; sourceTree = "<group>"; tabWidth = 8; }; F692A8540255597D01FF60F7 /* create_hash_table */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = text.script.perl; path = create_hash_table; sourceTree = "<group>"; tabWidth = 8; }; F692A8580255597D01FF60F7 /* Debugger.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Debugger.cpp; sourceTree = "<group>"; tabWidth = 8; }; F692A8590255597D01FF60F7 /* Debugger.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = Debugger.h; sourceTree = "<group>"; tabWidth = 8; }; @@ -724,27 +797,26 @@ F692A85E0255597D01FF60F7 /* JSFunction.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSFunction.cpp; sourceTree = "<group>"; tabWidth = 8; }; F692A85F0255597D01FF60F7 /* JSFunction.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = JSFunction.h; sourceTree = "<group>"; tabWidth = 8; }; F692A8620255597D01FF60F7 /* JSString.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = JSString.h; sourceTree = "<group>"; tabWidth = 8; }; - F692A8630255597D01FF60F7 /* interpreter.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = interpreter.cpp; sourceTree = "<group>"; tabWidth = 8; }; - F692A8640255597D01FF60F7 /* interpreter.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = interpreter.h; sourceTree = "<group>"; tabWidth = 8; }; - F692A8650255597D01FF60F7 /* lexer.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; name = lexer.cpp; path = kjs/lexer.cpp; sourceTree = "<group>"; tabWidth = 8; }; - F692A8660255597D01FF60F7 /* lexer.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; name = lexer.h; path = kjs/lexer.h; sourceTree = "<group>"; tabWidth = 8; }; - F692A8680255597D01FF60F7 /* lookup.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = lookup.cpp; sourceTree = "<group>"; tabWidth = 8; }; - F692A8690255597D01FF60F7 /* lookup.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = lookup.h; sourceTree = "<group>"; tabWidth = 8; }; + F692A8650255597D01FF60F7 /* Lexer.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Lexer.cpp; sourceTree = "<group>"; tabWidth = 8; }; + F692A8660255597D01FF60F7 /* Lexer.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = Lexer.h; sourceTree = "<group>"; tabWidth = 8; }; + F692A8680255597D01FF60F7 /* Lookup.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Lookup.cpp; sourceTree = "<group>"; tabWidth = 8; }; + F692A8690255597D01FF60F7 /* Lookup.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = Lookup.h; sourceTree = "<group>"; tabWidth = 8; }; F692A86A0255597D01FF60F7 /* MathObject.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MathObject.cpp; sourceTree = "<group>"; tabWidth = 8; }; F692A86B0255597D01FF60F7 /* MathObject.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = MathObject.h; sourceTree = "<group>"; tabWidth = 8; }; - F692A86D0255597D01FF60F7 /* nodes.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; name = nodes.cpp; path = kjs/nodes.cpp; sourceTree = "<group>"; tabWidth = 8; }; - F692A86E0255597D01FF60F7 /* nodes.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; name = nodes.h; path = kjs/nodes.h; sourceTree = "<group>"; tabWidth = 8; }; + F692A86D0255597D01FF60F7 /* Nodes.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Nodes.cpp; sourceTree = "<group>"; tabWidth = 8; }; + F692A86E0255597D01FF60F7 /* Nodes.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = Nodes.h; sourceTree = "<group>"; tabWidth = 8; }; F692A8700255597D01FF60F7 /* NumberObject.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NumberObject.cpp; sourceTree = "<group>"; tabWidth = 8; }; F692A8710255597D01FF60F7 /* NumberObject.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = NumberObject.h; sourceTree = "<group>"; tabWidth = 8; }; - F692A8770255597D01FF60F7 /* operations.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = operations.cpp; sourceTree = "<group>"; tabWidth = 8; }; - F692A8780255597D01FF60F7 /* operations.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = operations.h; sourceTree = "<group>"; tabWidth = 8; }; + F692A8770255597D01FF60F7 /* Operations.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Operations.cpp; sourceTree = "<group>"; tabWidth = 8; }; + F692A8780255597D01FF60F7 /* Operations.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = Operations.h; sourceTree = "<group>"; tabWidth = 8; }; F692A87B0255597D01FF60F7 /* RegExpObject.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RegExpObject.cpp; sourceTree = "<group>"; tabWidth = 8; }; F692A87C0255597D01FF60F7 /* RegExpObject.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = RegExpObject.h; sourceTree = "<group>"; tabWidth = 8; }; - F692A87D0255597D01FF60F7 /* regexp.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = regexp.cpp; sourceTree = "<group>"; tabWidth = 8; }; - F692A87E0255597D01FF60F7 /* regexp.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = regexp.h; sourceTree = "<group>"; tabWidth = 8; }; - 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; }; + F692A87D0255597D01FF60F7 /* RegExp.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RegExp.cpp; sourceTree = "<group>"; tabWidth = 8; }; + F692A87E0255597D01FF60F7 /* RegExp.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = RegExp.h; sourceTree = "<group>"; tabWidth = 8; }; + 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; }; + FE1B44790ECCD73B004F4DD1 /* StdLibExtras.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StdLibExtras.h; sourceTree = "<group>"; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -795,8 +867,8 @@ children = ( 932F5BD90822A1C700736975 /* JavaScriptCore.framework */, 932F5BE10822A1C700736975 /* jsc */, - 14BD59BF0A3E8F9000BAF59C /* testapi */, 141211200A48793C00480255 /* minidom */, + 14BD59BF0A3E8F9000BAF59C /* testapi */, ); name = Products; sourceTree = "<group>"; @@ -815,19 +887,24 @@ isa = PBXGroup; children = ( 937B63CC09E766D200A671DD /* DerivedSources.make */, + F692A8540255597D01FF60F7 /* create_hash_table */, 14B8ECA60A5653980062BE54 /* JavaScriptCore.exp */, F5C290E60284F98E018635CA /* JavaScriptCorePrefix.h */, 659126BC0BDD1728001921FB /* AllInOneFile.cpp */, + 45E12D8806A49B0F00E9DF84 /* jsc.cpp */, + F68EBB8C0255D4C601FF60F7 /* config.h */, 1432EBD70A34CAD400717B9F /* API */, - 149B15DF0D81F887009CB8C7 /* compiler */, + 9688CB120ED12B4E001D649F /* assembler */, + 969A078F0ED1D3AE00F1F681 /* bytecode */, + 7E39D81D0EC38EFA003AF11A /* bytecompiler */, 1480DB9A0DDC2231003CFDF2 /* debugger */, - 65417200039E01BA0058BFEB /* kjs */, - 8690813F0E640C89000D36ED /* masm */, + 1429D77A0ED20D7300B89619 /* interpreter */, + 1429D92C0ED22D7000B89619 /* jit */, + 7E39D8370EC3A388003AF11A /* parser */, 65417203039E01F90058BFEB /* pcre */, 95AB831A0DA42C6900BC83F3 /* profiler */, 7EF6E0BB0EB7A1EC0079AFAF /* runtime */, 141211000A48772600480255 /* tests */, - 149B15E00D81F88D009CB8C7 /* vm */, 869083120E6518D7000D36ED /* wrec */, 65162EF108E6A21C007556CD /* wtf */, 1C90513E0BA9E8830081E9D0 /* Configurations */, @@ -845,9 +922,9 @@ 6560A4CF04B3B3E7008AE952 /* CoreFoundation.framework */, 6560A63D04B3B69F008AE952 /* CoreServices.framework */, 51F0EB6105C86C6B00E6DF1B /* Foundation.framework */, + 5D5D8AD00E0D0EBE00F9C692 /* libedit.dylib */, 9322A00306C341D3009067BB /* libicucore.dylib */, 51F0EC0705C86C9A00E6DF1B /* libobjc.dylib */, - 5D5D8AD00E0D0EBE00F9C692 /* libedit.dylib */, ); name = Frameworks; sourceTree = "<group>"; @@ -860,22 +937,49 @@ 144005170A531CB50005F061 /* minidom */, 14BD5A2D0A3E91F600BAF59C /* testapi.c */, 14D857740A4696C80032146C /* testapi.js */, - 45E12D8806A49B0F00E9DF84 /* Shell.cpp */, ); name = tests; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; }; + 1429D77A0ED20D7300B89619 /* interpreter */ = { + isa = PBXGroup; + children = ( + 1429D8DB0ED2205B00B89619 /* CallFrame.cpp */, + 1429D8DC0ED2205B00B89619 /* CallFrame.h */, + 1429D7D30ED2128200B89619 /* Interpreter.cpp */, + 1429D77B0ED20D7300B89619 /* Interpreter.h */, + 149B24FF0D8AF6D1009CB8C7 /* Register.h */, + 1429D85B0ED218E900B89619 /* RegisterFile.cpp */, + 14D792640DAA03FB001A9F05 /* RegisterFile.h */, + ); + path = interpreter; + sourceTree = "<group>"; + }; + 1429D92C0ED22D7000B89619 /* jit */ = { + isa = PBXGroup; + children = ( + A7B48DB60EE74CFC00DCBDB6 /* ExecutableAllocator.cpp */, + A7B48DB50EE74CFC00DCBDB6 /* ExecutableAllocator.h */, + A782F1A40EEC9FA20036273F /* ExecutableAllocatorPosix.cpp */, + 1429D92D0ED22D7000B89619 /* JIT.cpp */, + 1429D92E0ED22D7000B89619 /* JIT.h */, + 86A90ECF0EE7D51F00AB350D /* JITArithmetic.cpp */, + 86CC85A20EE79B7400288682 /* JITCall.cpp */, + 86CC85A00EE79A4700288682 /* JITInlineMethods.h */, + 86CC85C30EE7A89400288682 /* JITPropertyAccess.cpp */, + ); + path = jit; + sourceTree = "<group>"; + }; 1432EBD70A34CAD400717B9F /* API */ = { isa = PBXGroup; children = ( - 140D17D60E8AD4A9000CD17D /* JSBasePrivate.h */, 1482B78A0A4305AB00517CFC /* APICast.h */, - 1CAA8B4A0D32C39A0041BCFF /* JavaScript.h */, - 1CAA8B4B0D32C39A0041BCFF /* JavaScriptCore.h */, 1421359A0A677F4F00A8195E /* JSBase.cpp */, 142711380A460BBB0080EEEA /* JSBase.h */, + 140D17D60E8AD4A9000CD17D /* JSBasePrivate.h */, 1440F8AD0A508D200005F061 /* JSCallbackConstructor.cpp */, 1440F8AC0A508D200005F061 /* JSCallbackConstructor.h */, 1440F8900A508B100005F061 /* JSCallbackFunction.cpp */, @@ -898,6 +1002,8 @@ 146AAB2A0B66A84900E55F16 /* JSStringRefCF.h */, 14BD5A2B0A3E91F600BAF59C /* JSValueRef.cpp */, 1482B6EA0A4300B300517CFC /* JSValueRef.h */, + 1CAA8B4A0D32C39A0041BCFF /* JavaScript.h */, + 1CAA8B4B0D32C39A0041BCFF /* JavaScriptCore.h */, E124A8F60E555775003091F1 /* OpaqueJSString.cpp */, E124A8F50E555775003091F1 /* OpaqueJSString.h */, 5DE3D0F40DD8DDFB00468714 /* WebKitAvailability.h */, @@ -914,12 +1020,12 @@ 1440F6410A4F8B6A0005F061 /* JSNode.h */, 144007560A5370D20005F061 /* JSNodeList.c */, 144007550A5370D20005F061 /* JSNodeList.h */, - 141211020A48780900480255 /* minidom.c */, - 1412110D0A48788700480255 /* minidom.js */, 144005200A531D3B0005F061 /* Node.c */, 1440051F0A531D3B0005F061 /* Node.h */, 144007490A536CC20005F061 /* NodeList.c */, 144007480A536CC20005F061 /* NodeList.h */, + 141211020A48780900480255 /* minidom.c */, + 1412110D0A48788700480255 /* minidom.js */, ); name = minidom; path = API; @@ -932,54 +1038,12 @@ F692A8590255597D01FF60F7 /* Debugger.h */, 149559ED0DDCDDF700648087 /* DebuggerCallFrame.cpp */, 1480DB9B0DDC227F003CFDF2 /* DebuggerCallFrame.h */, + BC3135630F302FA3003DFD3A /* DebuggerActivation.cpp */, + BC3135620F302FA3003DFD3A /* DebuggerActivation.h */, ); path = debugger; sourceTree = "<group>"; }; - 149B15DF0D81F887009CB8C7 /* compiler */ = { - isa = PBXGroup; - children = ( - 960097A50EBABB58007A7297 /* LabelScope.h */, - 149B15E90D81F986009CB8C7 /* CodeGenerator.cpp */, - 149B15E80D81F986009CB8C7 /* CodeGenerator.h */, - 149B20D70D8A0891009CB8C7 /* LabelID.h */, - F692A8650255597D01FF60F7 /* lexer.cpp */, - F692A8660255597D01FF60F7 /* lexer.h */, - 7EFF00630EC05A9A00AA7C93 /* NodeInfo.h */, - F692A86D0255597D01FF60F7 /* nodes.cpp */, - F692A86E0255597D01FF60F7 /* nodes.h */, - F5FFE656026B47A6018635CA /* nodes2string.cpp */, - 93F0B3A909BB4DC00068FCE3 /* Parser.cpp */, - 93F0B3AA09BB4DC00068FCE3 /* Parser.h */, - 149B16B80D82583F009CB8C7 /* RegisterID.h */, - A7C31DA80DBEBA4300FDF8EB /* SegmentedVector.h */, - ); - name = compiler; - sourceTree = "<group>"; - }; - 149B15E00D81F88D009CB8C7 /* vm */ = { - isa = PBXGroup; - children = ( - 8683B02B0E636482004C19EE /* CTI.cpp */, - 8683B02C0E636482004C19EE /* CTI.h */, - 8613F4580E3A433E00C948FD /* SamplingTool.cpp */, - 8613F4590E3A433E00C948FD /* SamplingTool.h */, - 149B1A9E0D86ED73009CB8C7 /* CodeBlock.cpp */, - 149B1A9D0D86ED73009CB8C7 /* CodeBlock.h */, - A72701B40DADE94900E548D7 /* ExceptionHelpers.cpp */, - A72701B30DADE94900E548D7 /* ExceptionHelpers.h */, - 149B1AA10D86ED7C009CB8C7 /* Instruction.h */, - 149B15E70D81F986009CB8C7 /* Machine.cpp */, - 149B15E60D81F986009CB8C7 /* Machine.h */, - 149B15E50D81F986009CB8C7 /* Opcode.cpp */, - 149B15E40D81F986009CB8C7 /* Opcode.h */, - 149B24FF0D8AF6D1009CB8C7 /* Register.h */, - 14D792650DAA03FB001A9F05 /* RegisterFile.cpp */, - 14D792640DAA03FB001A9F05 /* RegisterFile.h */, - ); - name = vm; - sourceTree = "<group>"; - }; 1C90513E0BA9E8830081E9D0 /* Configurations */ = { isa = PBXGroup; children = ( @@ -997,17 +1061,17 @@ isa = PBXGroup; children = ( BC18C5230E16FC8A00B34460 /* ArrayPrototype.lut.h */, - 65B174BE09D1000200820339 /* chartables.c */, BCD203E70E1718F4002C7E82 /* DatePrototype.lut.h */, - 65FB3F4809D11B2400F49DEB /* grammar.cpp */, - BC18C52F0E16FCEB00B34460 /* grammar.h */, - BC18C52D0E16FCE100B34460 /* lexer.lut.h */, BC18C5290E16FCC200B34460 /* MathObject.lut.h */, BC2680E60E16D52300A06E92 /* NumberConstructor.lut.h */, BCD202D50E170708002C7E82 /* RegExpConstructor.lut.h */, BC18C52B0E16FCD200B34460 /* RegExpObject.lut.h */, BC18C5250E16FCA700B34460 /* StringPrototype.lut.h */, 5D53727D0E1C55EC0021E549 /* TracingDtrace.h */, + 65B174BE09D1000200820339 /* chartables.c */, + 65FB3F4809D11B2400F49DEB /* grammar.cpp */, + BC18C52F0E16FCEB00B34460 /* grammar.h */, + BC18C52D0E16FCE100B34460 /* lexer.lut.h */, ); name = "Derived Sources"; path = DerivedSources/JavaScriptCore; @@ -1020,11 +1084,15 @@ children = ( 06D358A00DAAD9C4003B174E /* mac */, E195678D09E7CF1200B89D13 /* unicode */, - 93AA4F770957251F0084B3A7 /* AlwaysInline.h */, 938C4F690CA06BC700D9310A /* ASCIICType.h */, + E1A596370DE3E1C300C17E37 /* AVLTree.h */, + 93AA4F770957251F0084B3A7 /* AlwaysInline.h */, 65E217B808E7EECC0023E5F6 /* Assertions.cpp */, 65E217B708E7EECC0023E5F6 /* Assertions.h */, - E1A596370DE3E1C300C17E37 /* AVLTree.h */, + A7A1F7AA0F252B3C00E184E2 /* ByteArray.cpp */, + A7A1F7AB0F252B3C00E184E2 /* ByteArray.h */, + 180B9AEF0F16C569009BDBC5 /* CurrentTime.cpp */, + 180B9AF00F16C569009BDBC5 /* CurrentTime.h */, 5186111D0CC824830081412B /* Deque.h */, 938C4F6B0CA06BCE00D9310A /* DisallowCType.h */, 65E217B908E7EECC0023E5F6 /* FastMalloc.cpp */, @@ -1053,61 +1121,34 @@ 9303F567099118FA00AD71B8 /* OwnPtr.h */, 6580F795094070560082C219 /* PassRefPtr.h */, 65D6D87E09B5A32E0002E4D7 /* Platform.h */, + 0B1F921B0F17502D0036468E /* PtrAndFlags.h */, + 088FA5B90EF76D4300578E6F /* RandomNumber.cpp */, + 088FA5BA0EF76D4300578E6F /* RandomNumber.h */, + 08E279E80EF83B10007DB523 /* RandomNumberSeed.h */, 1419D32C0CEA7CDE00FF507A /* RefCounted.h */, - 90D3469B0E285280009492EE /* RefCountedLeakCounter.h */, 905B02AD0E28640F006DF882 /* RefCountedLeakCounter.cpp */, + 90D3469B0E285280009492EE /* RefCountedLeakCounter.h */, 65C647B3093EF8D60022C380 /* RefPtr.h */, 148A1ECD0D10C23B0069A47C /* RefPtrHashMap.h */, 51F648D60BB4E2CA0033D760 /* RetainPtr.h */, + FE1B44790ECCD73B004F4DD1 /* StdLibExtras.h */, E11D51750B2E798D0056C188 /* StringExtras.h */, 5DA479650CFBCF56009328A0 /* TCPackedCache.h */, 6541BD6E08E80A17002CBEE7 /* TCPageMap.h */, 6541BD6F08E80A17002CBEE7 /* TCSpinLock.h */, 6541BD7008E80A17002CBEE7 /* TCSystemAlloc.cpp */, 6541BD7108E80A17002CBEE7 /* TCSystemAlloc.h */, + E1B7C8BD0DA3A3360074B0DC /* ThreadSpecific.h */, + 5D6A566A0F05995500266145 /* Threading.cpp */, E1EE79220D6C95CD00FEA3BA /* Threading.h */, E1EE793C0D6C9B9200FEA3BA /* ThreadingPthreads.cpp */, - E1B7C8BD0DA3A3360074B0DC /* ThreadSpecific.h */, 935AF46B09E9D9DB00ACD1D8 /* UnusedParam.h */, 6592C316098B7DE10003D4F6 /* Vector.h */, 6592C317098B7DE10003D4F6 /* VectorTraits.h */, - ); - path = wtf; - sourceTree = "<group>"; - tabWidth = 4; - usesTabs = 0; - }; - 65417200039E01BA0058BFEB /* kjs */ = { - isa = PBXGroup; - children = ( - 6507D2970E871E4A00D7D896 /* TypeInfo.h */, - F692A8520255597D01FF60F7 /* collector.cpp */, - F692A8530255597D01FF60F7 /* collector.h */, - F5BB2BC5030F772101FCFE1D /* completion.h */, - F68EBB8C0255D4C601FF60F7 /* config.h */, - F692A8540255597D01FF60F7 /* create_hash_table */, 651F6412039D5B5F0078395C /* dtoa.cpp */, 651F6413039D5B5F0078395C /* dtoa.h */, - 933A3499038AE7C6008635CE /* grammar.y */, - 933A349D038AE80F008635CE /* identifier.cpp */, - 933A349A038AE7C6008635CE /* identifier.h */, - F692A8630255597D01FF60F7 /* interpreter.cpp */, - F692A8640255597D01FF60F7 /* interpreter.h */, - 93F1981A08245AAE001E9ABC /* keywords.table */, - F692A8680255597D01FF60F7 /* lookup.cpp */, - F692A8690255597D01FF60F7 /* lookup.h */, - F692A8770255597D01FF60F7 /* operations.cpp */, - F692A8780255597D01FF60F7 /* operations.h */, - 65C02FBB0637462A003E7EE6 /* protect.h */, - F692A87D0255597D01FF60F7 /* regexp.cpp */, - F692A87E0255597D01FF60F7 /* regexp.h */, - 869EBCB60E8C6D4A008722CC /* ResultType.h */, - 65E866ED0DD59AFA00A2B2A1 /* SourceProvider.h */, - 65E866EE0DD59AFA00A2B2A1 /* SourceCode.h */, - F692A8850255597D01FF60F7 /* ustring.cpp */, - F692A8860255597D01FF60F7 /* ustring.h */, ); - path = kjs; + path = wtf; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; @@ -1129,6 +1170,38 @@ tabWidth = 4; usesTabs = 0; }; + 7E39D81D0EC38EFA003AF11A /* bytecompiler */ = { + isa = PBXGroup; + children = ( + 969A07200ED1CE3300F1F681 /* BytecodeGenerator.cpp */, + 969A07210ED1CE3300F1F681 /* BytecodeGenerator.h */, + 969A07270ED1CE6900F1F681 /* Label.h */, + 960097A50EBABB58007A7297 /* LabelScope.h */, + 969A07280ED1CE6900F1F681 /* RegisterID.h */, + 969A07290ED1CE6900F1F681 /* SegmentedVector.h */, + ); + path = bytecompiler; + sourceTree = "<group>"; + }; + 7E39D8370EC3A388003AF11A /* parser */ = { + isa = PBXGroup; + children = ( + 933A3499038AE7C6008635CE /* Grammar.y */, + 93F1981A08245AAE001E9ABC /* Keywords.table */, + F692A8650255597D01FF60F7 /* Lexer.cpp */, + F692A8660255597D01FF60F7 /* Lexer.h */, + 7EFF00630EC05A9A00AA7C93 /* NodeInfo.h */, + F692A86D0255597D01FF60F7 /* Nodes.cpp */, + F692A86E0255597D01FF60F7 /* Nodes.h */, + 93F0B3A909BB4DC00068FCE3 /* Parser.cpp */, + 93F0B3AA09BB4DC00068FCE3 /* Parser.h */, + 869EBCB60E8C6D4A008722CC /* ResultType.h */, + 65E866EE0DD59AFA00A2B2A1 /* SourceCode.h */, + 65E866ED0DD59AFA00A2B2A1 /* SourceProvider.h */, + ); + path = parser; + sourceTree = "<group>"; + }; 7EF6E0BB0EB7A1EC0079AFAF /* runtime */ = { isa = PBXGroup; children = ( @@ -1150,9 +1223,13 @@ BCA62DFE0E2826230004F30D /* CallData.cpp */, 145C507F0D9DF63B0088F6B9 /* CallData.h */, BC6AAAE40E1F426500AD87D8 /* ClassInfo.h */, + F692A8520255597D01FF60F7 /* Collector.cpp */, + F692A8530255597D01FF60F7 /* Collector.h */, 14F3488E0E95EF8A003648BC /* CollectorHeapIterator.h */, 65EA73620BAE35D1001BB560 /* CommonIdentifiers.cpp */, 65EA73630BAE35D1001BB560 /* CommonIdentifiers.h */, + 969A09220ED1E09C00F1F681 /* Completion.cpp */, + F5BB2BC5030F772101FCFE1D /* Completion.h */, BCA62DFF0E2826310004F30D /* ConstructData.cpp */, BC8F3CCF0DAF17BA00577A80 /* ConstructData.h */, BCD203450E17135E002C7E82 /* DateConstructor.cpp */, @@ -1171,8 +1248,8 @@ BC02E98B0E183E38000F9297 /* ErrorInstance.h */, BC02E9060E1839DB000F9297 /* ErrorPrototype.cpp */, BC02E9070E1839DB000F9297 /* ErrorPrototype.h */, - 14BD53F40A3E12D800BAF59C /* ExecState.cpp */, - 14BD53F30A3E12D800BAF59C /* ExecState.h */, + 1429D8770ED21ACD00B89619 /* ExceptionHelpers.cpp */, + A72701B30DADE94900E548D7 /* ExceptionHelpers.h */, BC2680C00E16D4E900A06E92 /* FunctionConstructor.cpp */, BC2680C10E16D4E900A06E92 /* FunctionConstructor.h */, F692A85C0255597D01FF60F7 /* FunctionPrototype.cpp */, @@ -1181,6 +1258,8 @@ BC337BDE0E1AF0B80076918A /* GetterSetter.h */, BC257DED0E1F52ED0016B6C9 /* GlobalEvalFunction.cpp */, BC257DEE0E1F52ED0016B6C9 /* GlobalEvalFunction.h */, + 933A349D038AE80F008635CE /* Identifier.cpp */, + 933A349A038AE7C6008635CE /* Identifier.h */, E178636C0D9BEEC300D74E75 /* InitializeThreading.cpp */, E178633F0D9BEC0000D74E75 /* InitializeThreading.h */, BC9BB95B0E19680600DF8855 /* InternalFunction.cpp */, @@ -1189,6 +1268,8 @@ 14DA818E0D99FD2000B0A4FB /* JSActivation.h */, 93ADFCE60CCBD7AC00D30B08 /* JSArray.cpp */, 938772E5038BFE19008635CE /* JSArray.h */, + A791EF270F11E07900AE1F68 /* JSByteArray.cpp */, + A791EF260F11E07900AE1F68 /* JSByteArray.h */, BC7F8FBA0E19D1EF008632C0 /* JSCell.cpp */, BC1167D80E19BCC9008066DD /* JSCell.h */, F692A85E0255597D01FF60F7 /* JSFunction.cpp */, @@ -1222,6 +1303,8 @@ 14F252560D08DD8D004ECFFF /* JSVariableObject.h */, 65C7A1710A8EAACB00FA37EA /* JSWrapperObject.cpp */, 65C7A1720A8EAACB00FA37EA /* JSWrapperObject.h */, + F692A8680255597D01FF60F7 /* Lookup.cpp */, + F692A8690255597D01FF60F7 /* Lookup.h */, F692A86A0255597D01FF60F7 /* MathObject.cpp */, F692A86B0255597D01FF60F7 /* MathObject.h */, BC02E9080E1839DB000F9297 /* NativeErrorConstructor.cpp */, @@ -1238,14 +1321,19 @@ BC2680C70E16D4E900A06E92 /* ObjectConstructor.h */, BC2680C80E16D4E900A06E92 /* ObjectPrototype.cpp */, BC2680C90E16D4E900A06E92 /* ObjectPrototype.h */, + F692A8770255597D01FF60F7 /* Operations.cpp */, + F692A8780255597D01FF60F7 /* Operations.h */, BC95437C0EBA70FD0072B6D3 /* PropertyMapHashTable.h */, 65400C0F0A69BAF200509887 /* PropertyNameArray.cpp */, 65400C100A69BAF200509887 /* PropertyNameArray.h */, 65621E6B089E859700760F35 /* PropertySlot.cpp */, 65621E6C089E859700760F35 /* PropertySlot.h */, + 65C02FBB0637462A003E7EE6 /* Protect.h */, BC257DF10E1F53740016B6C9 /* PrototypeFunction.cpp */, BC257DF20E1F53740016B6C9 /* PrototypeFunction.h */, 147B84620E6DE6B1004775A4 /* PutPropertySlot.h */, + F692A87D0255597D01FF60F7 /* RegExp.cpp */, + F692A87E0255597D01FF60F7 /* RegExp.h */, BCD202BD0E1706A7002C7E82 /* RegExpConstructor.cpp */, BCD202BE0E1706A7002C7E82 /* RegExpConstructor.h */, 93CEDDFB0EA91EE600258EBE /* RegExpMatchesArray.h */, @@ -1265,33 +1353,38 @@ BC18C3C40E16EE3300B34460 /* StringObjectThatMasqueradesAsUndefined.h */, BC18C3C50E16EE3300B34460 /* StringPrototype.cpp */, BC18C3C60E16EE3300B34460 /* StringPrototype.h */, - BCDE3AB00E6C82CF001453A7 /* StructureID.cpp */, - BCDE3AB10E6C82CF001453A7 /* StructureID.h */, - 7E4EE70E0EBB7A5B005934AA /* StructureIDChain.cpp */, - 7E4EE7080EBB7963005934AA /* StructureIDChain.h */, - BC9041470EB9250900FE26FA /* StructureIDTransitionTable.h */, + BCDE3AB00E6C82CF001453A7 /* Structure.cpp */, + BCDE3AB10E6C82CF001453A7 /* Structure.h */, + 7E4EE70E0EBB7A5B005934AA /* StructureChain.cpp */, + 7E4EE7080EBB7963005934AA /* StructureChain.h */, + BC9041470EB9250900FE26FA /* StructureTransitionTable.h */, 14A396A60CD2933100B5B4FF /* SymbolTable.h */, 5D53726D0E1C546B0021E549 /* Tracing.d */, 5D53726E0E1C54880021E549 /* Tracing.h */, + 6507D2970E871E4A00D7D896 /* TypeInfo.h */, + F692A8850255597D01FF60F7 /* UString.cpp */, + F692A8860255597D01FF60F7 /* UString.h */, ); path = runtime; sourceTree = "<group>"; }; - 8690813F0E640C89000D36ED /* masm */ = { - isa = PBXGroup; - children = ( - 869081400E640C89000D36ED /* X86Assembler.h */, - ); - path = masm; - sourceTree = "<group>"; - }; 869083120E6518D7000D36ED /* wrec */ = { isa = PBXGroup; children = ( + 1429D9C20ED23C3900B89619 /* CharacterClass.cpp */, + 1429D9C30ED23C3900B89619 /* CharacterClass.h */, 7E2ADD8F0E79AC1100D50C51 /* CharacterClassConstructor.cpp */, 7E2ADD8D0E79AAD500D50C51 /* CharacterClassConstructor.h */, + 96A7463F0EDDF70600904779 /* Escapes.h */, + 1429DA490ED245EC00B89619 /* Quantifier.h */, 869083130E6518D7000D36ED /* WREC.cpp */, 869083140E6518D7000D36ED /* WREC.h */, + 1429DA800ED2482900B89619 /* WRECFunctors.cpp */, + 1429DA810ED2482900B89619 /* WRECFunctors.h */, + 1429DADF0ED2645B00B89619 /* WRECGenerator.cpp */, + 1429DADE0ED2645B00B89619 /* WRECGenerator.h */, + 1429DABE0ED263E700B89619 /* WRECParser.cpp */, + 1429DABD0ED263E700B89619 /* WRECParser.h */, ); path = wrec; sourceTree = "<group>"; @@ -1320,8 +1413,8 @@ 95AB83550DA43B4400BC83F3 /* ProfileNode.h */, 95AB832E0DA42CAD00BC83F3 /* Profiler.cpp */, 95AB832F0DA42CAD00BC83F3 /* Profiler.h */, - 1C61516A0EBAC7A00031376F /* ProfilerServer.mm */, 1C61516B0EBAC7A00031376F /* ProfilerServer.h */, + 1C61516A0EBAC7A00031376F /* ProfilerServer.mm */, 95CD41B10E1BF6560085358E /* TreeProfile.cpp */, 95CD41B20E1BF6560085358E /* TreeProfile.h */, ); @@ -1329,15 +1422,44 @@ sourceTree = "<group>"; usesTabs = 0; }; + 9688CB120ED12B4E001D649F /* assembler */ = { + isa = PBXGroup; + children = ( + 9688CB130ED12B4E001D649F /* AssemblerBuffer.h */, + 86C36EE90EE1289D00B3DF59 /* MacroAssembler.h */, + 9688CB140ED12B4E001D649F /* X86Assembler.h */, + ); + path = assembler; + sourceTree = "<group>"; + }; + 969A078F0ED1D3AE00F1F681 /* bytecode */ = { + isa = PBXGroup; + children = ( + 969A07900ED1D3AE00F1F681 /* CodeBlock.cpp */, + 969A07910ED1D3AE00F1F681 /* CodeBlock.h */, + 969A07920ED1D3AE00F1F681 /* EvalCodeCache.h */, + 969A07930ED1D3AE00F1F681 /* Instruction.h */, + BCFD8C900EEB2EE700283848 /* JumpTable.cpp */, + BCFD8C910EEB2EE700283848 /* JumpTable.h */, + 969A07940ED1D3AE00F1F681 /* Opcode.cpp */, + 969A07950ED1D3AE00F1F681 /* Opcode.h */, + 1429D8830ED21C3D00B89619 /* SamplingTool.cpp */, + 1429D8840ED21C3D00B89619 /* SamplingTool.h */, + BCCF0D0B0EF0B8A500413C8F /* StructureStubInfo.cpp */, + BCCF0D070EF0AAB900413C8F /* StructureStubInfo.h */, + ); + path = bytecode; + sourceTree = "<group>"; + }; E195678D09E7CF1200B89D13 /* unicode */ = { isa = PBXGroup; children = ( E195678E09E7CF1200B89D13 /* icu */, E1A862AA0D7EBB7D001EC6AA /* Collator.h */, E1A862D50D7F2B5C001EC6AA /* CollatorDefault.cpp */, - E195679409E7CF1200B89D13 /* Unicode.h */, E1EF79A80CE97BA60088D500 /* UTF8.cpp */, E1EF79A90CE97BA60088D500 /* UTF8.h */, + E195679409E7CF1200B89D13 /* Unicode.h */, ); path = unicode; sourceTree = "<group>"; @@ -1358,12 +1480,11 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( + A72701B90DADE94900E548D7 /* ExceptionHelpers.h in Headers */, 144005CB0A5338D10005F061 /* JSNode.h in Headers */, 144007570A5370D20005F061 /* JSNodeList.h in Headers */, 144005CC0A5338F80005F061 /* Node.h in Headers */, 1440074A0A536CC20005F061 /* NodeList.h in Headers */, - A72701B90DADE94900E548D7 /* ExceptionHelpers.h in Headers */, - A7C31DAA0DBEBA4300FDF8EB /* SegmentedVector.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1371,37 +1492,57 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - BC18C3E40E16F5CD00B34460 /* AlwaysInline.h in Headers */, BC18C3E50E16F5CD00B34460 /* APICast.h in Headers */, + BC18C3E90E16F5CD00B34460 /* ASCIICType.h in Headers */, + BC18C3EB0E16F5CD00B34460 /* AVLTree.h in Headers */, + BC18C3E40E16F5CD00B34460 /* AlwaysInline.h in Headers */, + BCF605140E203EF800B9A64D /* ArgList.h in Headers */, + BC257DE80E1F51C50016B6C9 /* Arguments.h in Headers */, BC18C3E60E16F5CD00B34460 /* ArrayConstructor.h in Headers */, BC18C3E70E16F5CD00B34460 /* ArrayPrototype.h in Headers */, - BC18C3E90E16F5CD00B34460 /* ASCIICType.h in Headers */, + BC18C5240E16FC8A00B34460 /* ArrayPrototype.lut.h in Headers */, + 9688CB150ED12B4E001D649F /* AssemblerBuffer.h in Headers */, BC18C3EA0E16F5CD00B34460 /* Assertions.h in Headers */, - BC18C3EB0E16F5CD00B34460 /* AVLTree.h in Headers */, + 147B83AC0E6DB8C9004775A4 /* BatchedTransitionOptimizer.h in Headers */, BC18C3EC0E16F5CD00B34460 /* BooleanObject.h in Headers */, + 969A07230ED1CE3300F1F681 /* BytecodeGenerator.h in Headers */, BC18C3ED0E16F5CD00B34460 /* CallData.h in Headers */, - BC18C3EE0E16F5CD00B34460 /* CodeBlock.h in Headers */, - BC18C3EF0E16F5CD00B34460 /* CodeGenerator.h in Headers */, + 1429D8DE0ED2205B00B89619 /* CallFrame.h in Headers */, + 95E3BC050E1AE68200B2D1C1 /* CallIdentifier.h in Headers */, + 1429D9C50ED23C3900B89619 /* CharacterClass.h in Headers */, + 7E2ADD8E0E79AAD500D50C51 /* CharacterClassConstructor.h in Headers */, + BC6AAAE50E1F426500AD87D8 /* ClassInfo.h in Headers */, + 969A07970ED1D3AE00F1F681 /* CodeBlock.h in Headers */, BC18C3F00E16F5CD00B34460 /* Collator.h in Headers */, - BC18C3F10E16F5CD00B34460 /* collector.h in Headers */, + BC18C3F10E16F5CD00B34460 /* Collector.h in Headers */, + 14F3488F0E95EF8A003648BC /* CollectorHeapIterator.h in Headers */, BC18C3F30E16F5CD00B34460 /* CommonIdentifiers.h in Headers */, - BC18C3F40E16F5CD00B34460 /* completion.h in Headers */, - BC18C3F50E16F5CD00B34460 /* config.h in Headers */, + BC18C3F40E16F5CD00B34460 /* Completion.h in Headers */, BC18C3F60E16F5CD00B34460 /* ConstructData.h in Headers */, - 5DE6E5B30E1728EC00180407 /* create_hash_table in Headers */, + 180B9B080F16D94F009BDBC5 /* CurrentTime.h in Headers */, + BCD2034A0E17135E002C7E82 /* DateConstructor.h in Headers */, + BC1166020E1997B4008066DD /* DateInstance.h in Headers */, BC18C3F90E16F5CD00B34460 /* DateMath.h in Headers */, + BCD2034C0E17135E002C7E82 /* DatePrototype.h in Headers */, + BCD203E80E1718F4002C7E82 /* DatePrototype.lut.h in Headers */, BC18C3FA0E16F5CD00B34460 /* Debugger.h in Headers */, BC18C3FB0E16F5CD00B34460 /* DebuggerCallFrame.h in Headers */, BC18C3FC0E16F5CD00B34460 /* Deque.h in Headers */, BC18C3FD0E16F5CD00B34460 /* DisallowCType.h in Headers */, - BC18C3FE0E16F5CD00B34460 /* dtoa.h in Headers */, + BC3046070E1F497F003232CF /* Error.h in Headers */, + BC02E90D0E1839DB000F9297 /* ErrorConstructor.h in Headers */, + BC02E98D0E183E38000F9297 /* ErrorInstance.h in Headers */, + BC02E90F0E1839DB000F9297 /* ErrorPrototype.h in Headers */, + 96A746410EDDF70600904779 /* Escapes.h in Headers */, + 969A07980ED1D3AE00F1F681 /* EvalCodeCache.h in Headers */, BC18C4000E16F5CD00B34460 /* ExceptionHelpers.h in Headers */, - BC18C4010E16F5CD00B34460 /* ExecState.h in Headers */, + A766B44F0EE8DCD1009518CA /* ExecutableAllocator.h in Headers */, BC18C4020E16F5CD00B34460 /* FastMalloc.h in Headers */, BC18C4030E16F5CD00B34460 /* Forward.h in Headers */, BC18C4040E16F5CD00B34460 /* FunctionConstructor.h in Headers */, BC18C4050E16F5CD00B34460 /* FunctionPrototype.h in Headers */, BC18C4060E16F5CD00B34460 /* GetPtr.h in Headers */, + BC257DF00E1F52ED0016B6C9 /* GlobalEvalFunction.h in Headers */, BC18C4080E16F5CD00B34460 /* HashCountedSet.h in Headers */, BC18C4090E16F5CD00B34460 /* HashFunctions.h in Headers */, BC18C40A0E16F5CD00B34460 /* HashIterators.h in Headers */, @@ -1409,29 +1550,36 @@ BC18C40C0E16F5CD00B34460 /* HashSet.h in Headers */, BC18C40D0E16F5CD00B34460 /* HashTable.h in Headers */, BC18C40E0E16F5CD00B34460 /* HashTraits.h in Headers */, - BC18C40F0E16F5CD00B34460 /* identifier.h in Headers */, + 95FDFA160E2299980006FB00 /* HeavyProfile.h in Headers */, + BC18C40F0E16F5CD00B34460 /* Identifier.h in Headers */, BC18C4100E16F5CD00B34460 /* InitializeThreading.h in Headers */, - BC18C4110E16F5CD00B34460 /* Instruction.h in Headers */, - BC18C4120E16F5CD00B34460 /* interpreter.h in Headers */, - BC18C4130E16F5CD00B34460 /* JavaScript.h in Headers */, - BC18C4140E16F5CD00B34460 /* JavaScriptCore.h in Headers */, - BC18C4150E16F5CD00B34460 /* JavaScriptCorePrefix.h in Headers */, + 969A07990ED1D3AE00F1F681 /* Instruction.h in Headers */, + BC11667B0E199C05008066DD /* InternalFunction.h in Headers */, + 1429D77C0ED20D7300B89619 /* Interpreter.h in Headers */, + 1429D9300ED22D7000B89619 /* JIT.h in Headers */, + 86CC85A10EE79A4700288682 /* JITInlineMethods.h in Headers */, BC18C4160E16F5CD00B34460 /* JSActivation.h in Headers */, BC18C4170E16F5CD00B34460 /* JSArray.h in Headers */, BC18C4180E16F5CD00B34460 /* JSBase.h in Headers */, + 140D17D70E8AD4A9000CD17D /* JSBasePrivate.h in Headers */, + A791EF280F11E07900AE1F68 /* JSByteArray.h in Headers */, BC18C4190E16F5CD00B34460 /* JSCallbackConstructor.h in Headers */, BC18C41A0E16F5CD00B34460 /* JSCallbackFunction.h in Headers */, BC18C41B0E16F5CD00B34460 /* JSCallbackObject.h in Headers */, BC18C41C0E16F5CD00B34460 /* JSCallbackObjectFunctions.h in Headers */, + BC1167DA0E19BCC9008066DD /* JSCell.h in Headers */, BC18C41D0E16F5CD00B34460 /* JSClassRef.h in Headers */, BC18C41E0E16F5CD00B34460 /* JSContextRef.h in Headers */, BC18C41F0E16F5CD00B34460 /* JSFunction.h in Headers */, BC18C4200E16F5CD00B34460 /* JSGlobalData.h in Headers */, BC18C4210E16F5CD00B34460 /* JSGlobalObject.h in Headers */, + BC756FC90E2031B200DE7D12 /* JSGlobalObjectFunctions.h in Headers */, BC18C4220E16F5CD00B34460 /* JSImmediate.h in Headers */, BC18C4230E16F5CD00B34460 /* JSLock.h in Headers */, + BC7F8FB90E19D1C3008632C0 /* JSNumberCell.h in Headers */, BC18C4240E16F5CD00B34460 /* JSObject.h in Headers */, BC18C4250E16F5CD00B34460 /* JSObjectRef.h in Headers */, + 9534AAFB0E5B7A9600B8A45B /* JSProfilerPrivate.h in Headers */, BC18C4260E16F5CD00B34460 /* JSRetainPtr.h in Headers */, BC18C4270E16F5CD00B34460 /* JSString.h in Headers */, BC18C4280E16F5CD00B34460 /* JSStringRef.h in Headers */, @@ -1441,131 +1589,124 @@ BC18C42C0E16F5CD00B34460 /* JSValueRef.h in Headers */, BC18C42D0E16F5CD00B34460 /* JSVariableObject.h in Headers */, BC18C42E0E16F5CD00B34460 /* JSWrapperObject.h in Headers */, - BC18C42F0E16F5CD00B34460 /* LabelID.h in Headers */, - BC18C4310E16F5CD00B34460 /* lexer.h in Headers */, + BC18C4130E16F5CD00B34460 /* JavaScript.h in Headers */, + BC18C4140E16F5CD00B34460 /* JavaScriptCore.h in Headers */, + BC18C4150E16F5CD00B34460 /* JavaScriptCorePrefix.h in Headers */, + BCFD8C930EEB2EE700283848 /* JumpTable.h in Headers */, + 969A072A0ED1CE6900F1F681 /* Label.h in Headers */, + 960097A60EBABB58007A7297 /* LabelScope.h in Headers */, + BC18C4310E16F5CD00B34460 /* Lexer.h in Headers */, BC18C4340E16F5CD00B34460 /* ListHashSet.h in Headers */, BC18C4350E16F5CD00B34460 /* ListRefPtr.h in Headers */, BC18C4360E16F5CD00B34460 /* Locker.h in Headers */, - BC18C4370E16F5CD00B34460 /* lookup.h in Headers */, - BC18C4380E16F5CD00B34460 /* Machine.h in Headers */, + BC18C4370E16F5CD00B34460 /* Lookup.h in Headers */, + 86C36EEA0EE1289D00B3DF59 /* MacroAssembler.h in Headers */, BC18C4390E16F5CD00B34460 /* MainThread.h in Headers */, BC18C43A0E16F5CD00B34460 /* MallocZoneSupport.h in Headers */, BC18C43B0E16F5CD00B34460 /* MathExtras.h in Headers */, BC18C43C0E16F5CD00B34460 /* MathObject.h in Headers */, + BC18C52A0E16FCC200B34460 /* MathObject.lut.h in Headers */, BC18C43E0E16F5CD00B34460 /* MessageQueue.h in Headers */, - BC18C43F0E16F5CD00B34460 /* nodes.h in Headers */, + BC02E9110E1839DB000F9297 /* NativeErrorConstructor.h in Headers */, + BC02E9130E1839DB000F9297 /* NativeErrorPrototype.h in Headers */, + 7EFF00640EC05A9A00AA7C93 /* NodeInfo.h in Headers */, + BC18C43F0E16F5CD00B34460 /* Nodes.h in Headers */, BC18C4400E16F5CD00B34460 /* Noncopyable.h in Headers */, + C0A272630E50A06300E96E15 /* NotFound.h in Headers */, BC18C4410E16F5CD00B34460 /* NumberConstructor.h in Headers */, BC18C4420E16F5CD00B34460 /* NumberConstructor.lut.h in Headers */, BC18C4430E16F5CD00B34460 /* NumberObject.h in Headers */, BC18C4440E16F5CD00B34460 /* NumberPrototype.h in Headers */, BC18C4450E16F5CD00B34460 /* ObjectConstructor.h in Headers */, BC18C4460E16F5CD00B34460 /* ObjectPrototype.h in Headers */, - BC18C4470E16F5CD00B34460 /* Opcode.h in Headers */, - BC18C4480E16F5CD00B34460 /* operations.h in Headers */, + E124A8F70E555775003091F1 /* OpaqueJSString.h in Headers */, + 969A079B0ED1D3AE00F1F681 /* Opcode.h in Headers */, + BC18C4480E16F5CD00B34460 /* Operations.h in Headers */, BC18C4490E16F5CD00B34460 /* OwnArrayPtr.h in Headers */, BC18C44A0E16F5CD00B34460 /* OwnPtr.h in Headers */, BC18C44B0E16F5CD00B34460 /* Parser.h in Headers */, BC18C44C0E16F5CD00B34460 /* PassRefPtr.h in Headers */, - BC18C44D0E16F5CD00B34460 /* pcre.h in Headers */, - BC18C44E0E16F5CD00B34460 /* pcre_internal.h in Headers */, BC18C44F0E16F5CD00B34460 /* Platform.h in Headers */, BC18C4500E16F5CD00B34460 /* Profile.h in Headers */, + 95CD45770E1C4FDD0085358E /* ProfileGenerator.h in Headers */, BC18C4510E16F5CD00B34460 /* ProfileNode.h in Headers */, BC18C4520E16F5CD00B34460 /* Profiler.h in Headers */, + 1C61516D0EBAC7A00031376F /* ProfilerServer.h in Headers */, + BC95437D0EBA70FD0072B6D3 /* PropertyMapHashTable.h in Headers */, BC18C4540E16F5CD00B34460 /* PropertyNameArray.h in Headers */, BC18C4550E16F5CD00B34460 /* PropertySlot.h in Headers */, - BC18C4560E16F5CD00B34460 /* protect.h in Headers */, + BC18C4560E16F5CD00B34460 /* Protect.h in Headers */, + BC257DF40E1F53740016B6C9 /* PrototypeFunction.h in Headers */, + 0B1F921D0F1753500036468E /* PtrAndFlags.h in Headers */, + 147B84630E6DE6B1004775A4 /* PutPropertySlot.h in Headers */, + 1429DA4A0ED245EC00B89619 /* Quantifier.h in Headers */, + 088FA5BC0EF76D4300578E6F /* RandomNumber.h in Headers */, + 08E279E90EF83B10007DB523 /* RandomNumberSeed.h in Headers */, BC18C4570E16F5CD00B34460 /* RefCounted.h in Headers */, 90D3469C0E285280009492EE /* RefCountedLeakCounter.h in Headers */, BC18C4580E16F5CD00B34460 /* RefPtr.h in Headers */, BC18C4590E16F5CD00B34460 /* RefPtrHashMap.h in Headers */, - BC18C45A0E16F5CD00B34460 /* regexp.h in Headers */, + BC18C45A0E16F5CD00B34460 /* RegExp.h in Headers */, + BCD202C20E1706A7002C7E82 /* RegExpConstructor.h in Headers */, + BCD202D60E170708002C7E82 /* RegExpConstructor.lut.h in Headers */, BC18C45B0E16F5CD00B34460 /* RegExpObject.h in Headers */, + BC18C52C0E16FCD200B34460 /* RegExpObject.lut.h in Headers */, + BCD202C40E1706A7002C7E82 /* RegExpPrototype.h in Headers */, BC18C45D0E16F5CD00B34460 /* Register.h in Headers */, BC18C45E0E16F5CD00B34460 /* RegisterFile.h in Headers */, - BC18C45F0E16F5CD00B34460 /* RegisterID.h in Headers */, + 969A072B0ED1CE6900F1F681 /* RegisterID.h in Headers */, + 869EBCB70E8C6D4A008722CC /* ResultType.h in Headers */, BC18C4600E16F5CD00B34460 /* RetainPtr.h in Headers */, + 1429D8860ED21C3D00B89619 /* SamplingTool.h in Headers */, BC18C4610E16F5CD00B34460 /* ScopeChain.h in Headers */, - BC18C4620E16F5CD00B34460 /* SegmentedVector.h in Headers */, - BC18C4630E16F5CD00B34460 /* SourceProvider.h in Headers */, + 969A072C0ED1CE6900F1F681 /* SegmentedVector.h in Headers */, + 933040040E6A749400786E6A /* SmallStrings.h in Headers */, BC18C4640E16F5CD00B34460 /* SourceCode.h in Headers */, + BC18C4630E16F5CD00B34460 /* SourceProvider.h in Headers */, + FE1B447A0ECCD73B004F4DD1 /* StdLibExtras.h in Headers */, BC18C4660E16F5CD00B34460 /* StringConstructor.h in Headers */, BC18C4670E16F5CD00B34460 /* StringExtras.h in Headers */, BC18C4680E16F5CD00B34460 /* StringObject.h in Headers */, BC18C4690E16F5CD00B34460 /* StringObjectThatMasqueradesAsUndefined.h in Headers */, BC18C46A0E16F5CD00B34460 /* StringPrototype.h in Headers */, + BC18C5260E16FCA700B34460 /* StringPrototype.lut.h in Headers */, + BCDE3AB80E6C82F5001453A7 /* Structure.h in Headers */, + 7E4EE7090EBB7963005934AA /* StructureChain.h in Headers */, + BCCF0D080EF0AAB900413C8F /* StructureStubInfo.h in Headers */, + BC9041480EB9250900FE26FA /* StructureTransitionTable.h in Headers */, BC18C46B0E16F5CD00B34460 /* SymbolTable.h in Headers */, - 6507D29E0E871E5E00D7D896 /* TypeInfo.h in Headers */, BC18C46C0E16F5CD00B34460 /* TCPackedCache.h in Headers */, BC18C46D0E16F5CD00B34460 /* TCPageMap.h in Headers */, BC18C46E0E16F5CD00B34460 /* TCSpinLock.h in Headers */, BC18C46F0E16F5CD00B34460 /* TCSystemAlloc.h in Headers */, - BC18C4700E16F5CD00B34460 /* Threading.h in Headers */, BC18C4710E16F5CD00B34460 /* ThreadSpecific.h in Headers */, - BC18C4720E16F5CD00B34460 /* ucpinternal.h in Headers */, + BC18C4700E16F5CD00B34460 /* Threading.h in Headers */, + 5D53726F0E1C54880021E549 /* Tracing.h in Headers */, + 95CD41B40E1BF6560085358E /* TreeProfile.h in Headers */, + 6507D29E0E871E5E00D7D896 /* TypeInfo.h in Headers */, + BC18C4760E16F5CD00B34460 /* UString.h in Headers */, + BC18C4770E16F5CD00B34460 /* UTF8.h in Headers */, BC18C4730E16F5CD00B34460 /* Unicode.h in Headers */, BC18C4740E16F5CD00B34460 /* UnicodeIcu.h in Headers */, BC18C4750E16F5CD00B34460 /* UnusedParam.h in Headers */, - BC18C4760E16F5CD00B34460 /* ustring.h in Headers */, - BC18C4770E16F5CD00B34460 /* UTF8.h in Headers */, BC18C4780E16F5CD00B34460 /* Vector.h in Headers */, BC18C4790E16F5CD00B34460 /* VectorTraits.h in Headers */, + 869083160E6518D7000D36ED /* WREC.h in Headers */, + 1429DA830ED2482900B89619 /* WRECFunctors.h in Headers */, + 1429DAE00ED2645B00B89619 /* WRECGenerator.h in Headers */, + 1429DABF0ED263E700B89619 /* WRECParser.h in Headers */, BC18C47A0E16F5CD00B34460 /* WebKitAvailability.h in Headers */, - BC18C5240E16FC8A00B34460 /* ArrayPrototype.lut.h in Headers */, - BC18C5260E16FCA700B34460 /* StringPrototype.lut.h in Headers */, - BC18C52A0E16FCC200B34460 /* MathObject.lut.h in Headers */, - BC18C52C0E16FCD200B34460 /* RegExpObject.lut.h in Headers */, - BC18C52E0E16FCE100B34460 /* lexer.lut.h in Headers */, + 9688CB160ED12B4E001D649F /* X86Assembler.h in Headers */, + BC18C3F50E16F5CD00B34460 /* config.h in Headers */, + 5DE6E5B30E1728EC00180407 /* create_hash_table in Headers */, + BC18C3FE0E16F5CD00B34460 /* dtoa.h in Headers */, BC18C5300E16FCEB00B34460 /* grammar.h in Headers */, - BCD202C20E1706A7002C7E82 /* RegExpConstructor.h in Headers */, - BCD202C40E1706A7002C7E82 /* RegExpPrototype.h in Headers */, - BCD202D60E170708002C7E82 /* RegExpConstructor.lut.h in Headers */, - BCD2034A0E17135E002C7E82 /* DateConstructor.h in Headers */, - BCD2034C0E17135E002C7E82 /* DatePrototype.h in Headers */, - BCD203E80E1718F4002C7E82 /* DatePrototype.lut.h in Headers */, - BC02E90D0E1839DB000F9297 /* ErrorConstructor.h in Headers */, - BC02E90F0E1839DB000F9297 /* ErrorPrototype.h in Headers */, - BC02E9110E1839DB000F9297 /* NativeErrorConstructor.h in Headers */, - BC02E9130E1839DB000F9297 /* NativeErrorPrototype.h in Headers */, - BC02E98D0E183E38000F9297 /* ErrorInstance.h in Headers */, - BC1166020E1997B4008066DD /* DateInstance.h in Headers */, - 95E3BC050E1AE68200B2D1C1 /* CallIdentifier.h in Headers */, - BC11667B0E199C05008066DD /* InternalFunction.h in Headers */, - BC1167DA0E19BCC9008066DD /* JSCell.h in Headers */, - BC7F8FB90E19D1C3008632C0 /* JSNumberCell.h in Headers */, - 95CD41B40E1BF6560085358E /* TreeProfile.h in Headers */, - 95CD45770E1C4FDD0085358E /* ProfileGenerator.h in Headers */, - 5D53726F0E1C54880021E549 /* Tracing.h in Headers */, - BC6AAAE50E1F426500AD87D8 /* ClassInfo.h in Headers */, - BC3046070E1F497F003232CF /* Error.h in Headers */, - BC257DE80E1F51C50016B6C9 /* Arguments.h in Headers */, - BC257DF00E1F52ED0016B6C9 /* GlobalEvalFunction.h in Headers */, - BC257DF40E1F53740016B6C9 /* PrototypeFunction.h in Headers */, - BC756FC90E2031B200DE7D12 /* JSGlobalObjectFunctions.h in Headers */, - BCF605140E203EF800B9A64D /* ArgList.h in Headers */, - 95FDFA160E2299980006FB00 /* HeavyProfile.h in Headers */, - 8613F45B0E3A433E00C948FD /* SamplingTool.h in Headers */, - C0A272630E50A06300E96E15 /* NotFound.h in Headers */, - E124A8F70E555775003091F1 /* OpaqueJSString.h in Headers */, - 9534AAFB0E5B7A9600B8A45B /* JSProfilerPrivate.h in Headers */, - 8683B02F0E636482004C19EE /* CTI.h in Headers */, - 869081410E640C89000D36ED /* X86Assembler.h in Headers */, - 869083160E6518D7000D36ED /* WREC.h in Headers */, - 933040040E6A749400786E6A /* SmallStrings.h in Headers */, - BCDE3AB80E6C82F5001453A7 /* StructureID.h in Headers */, - 147B83AC0E6DB8C9004775A4 /* BatchedTransitionOptimizer.h in Headers */, - 147B84630E6DE6B1004775A4 /* PutPropertySlot.h in Headers */, - 7E2ADD8E0E79AAD500D50C51 /* CharacterClassConstructor.h in Headers */, - 140D17D70E8AD4A9000CD17D /* JSBasePrivate.h in Headers */, - 869EBCB70E8C6D4A008722CC /* ResultType.h in Headers */, - 14F3488F0E95EF8A003648BC /* CollectorHeapIterator.h in Headers */, - BC9041480EB9250900FE26FA /* StructureIDTransitionTable.h in Headers */, - 960097A60EBABB58007A7297 /* LabelScope.h in Headers */, - BC95437D0EBA70FD0072B6D3 /* PropertyMapHashTable.h in Headers */, - 1C61516D0EBAC7A00031376F /* ProfilerServer.h in Headers */, - 7E4EE7090EBB7963005934AA /* StructureIDChain.h in Headers */, - 7EFF00640EC05A9A00AA7C93 /* NodeInfo.h in Headers */, + BC18C52E0E16FCE100B34460 /* lexer.lut.h in Headers */, + BC18C44D0E16F5CD00B34460 /* pcre.h in Headers */, + BC18C44E0E16F5CD00B34460 /* pcre_internal.h in Headers */, + BC18C4720E16F5CD00B34460 /* ucpinternal.h in Headers */, + A7A1F7AD0F252B3C00E184E2 /* ByteArray.h in Headers */, + BC3135640F302FA3003DFD3A /* DebuggerActivation.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1617,6 +1758,7 @@ 932F5B3F0822A1C700736975 /* Headers */, 932F5B910822A1C700736975 /* Sources */, 9319586B09D9F91A00A56FD4 /* Check For Global Initializers */, + 933457200EBFDC3F00B80894 /* Check For Exit Time Destructors */, 5D29D8BE0E9860B400C3D2D0 /* Check For Weak VTables */, 932F5BD20822A1C700736975 /* Frameworks */, 1C395CBC0C6BCC16000D1E52 /* Generate 64-bit Export File */, @@ -1754,7 +1896,7 @@ files = ( ); inputPaths = ( - "$(SRCROOT)/kjs/Tracing.d", + "$(SRCROOT)/runtime/Tracing.d", ); name = "Generate DTrace header"; outputPaths = ( @@ -1762,7 +1904,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "TRACING_D=\"$SRCROOT/kjs/Tracing.d\";\nTRACING_H=\"$BUILT_PRODUCTS_DIR/DerivedSources/JavaScriptCore/TracingDtrace.h\";\n\nif [[ \"$MACOSX_DEPLOYMENT_TARGET\" > \"10.5\" ]];\nthen\n\tdtrace -h -o \"$TRACING_H\" -s \"$TRACING_D\";\nfi;\n"; + shellScript = "TRACING_D=\"$SRCROOT/runtime/Tracing.d\";\nTRACING_H=\"$BUILT_PRODUCTS_DIR/DerivedSources/JavaScriptCore/TracingDtrace.h\";\n\nif [[ \"$MACOSX_DEPLOYMENT_TARGET\" > \"10.5\" ]];\nthen\n\tdtrace -h -o \"$TRACING_H\" -s \"$TRACING_D\";\nfi;\n"; }; 5D5D8ABF0E0D0B0300F9C692 /* Fix Framework Reference */ = { isa = PBXShellScriptBuildPhase; @@ -1791,7 +1933,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "mkdir -p \"${BUILT_PRODUCTS_DIR}/DerivedSources/JavaScriptCore\"\ncd \"${BUILT_PRODUCTS_DIR}/DerivedSources/JavaScriptCore\"\n\nln -sfh \"${SRCROOT}\" JavaScriptCore\nexport JavaScriptCore=\"JavaScriptCore\"\nexport BUILT_PRODUCTS_DIR=\"../..\"\n\nmake -f \"JavaScriptCore/DerivedSources.make\" -j `/usr/sbin/sysctl -n hw.ncpu`\n"; + shellScript = "mkdir -p \"${BUILT_PRODUCTS_DIR}/DerivedSources/JavaScriptCore/docs\"\ncd \"${BUILT_PRODUCTS_DIR}/DerivedSources/JavaScriptCore\"\n\nln -sfh \"${SRCROOT}\" JavaScriptCore\nexport JavaScriptCore=\"JavaScriptCore\"\nexport BUILT_PRODUCTS_DIR=\"../..\"\n\nmake -f \"JavaScriptCore/DerivedSources.make\" -j `/usr/sbin/sysctl -n hw.ncpu`\n"; }; 9319586B09D9F91A00A56FD4 /* Check For Global Initializers */ = { isa = PBXShellScriptBuildPhase; @@ -1807,6 +1949,20 @@ shellPath = /bin/sh; shellScript = "if [ -f ../WebKitTools/Scripts/check-for-global-initializers ]; then\n ../WebKitTools/Scripts/check-for-global-initializers || exit $?\nfi"; }; + 933457200EBFDC3F00B80894 /* Check For Exit Time Destructors */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Check For Exit Time Destructors"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "if [ -f ../WebKitTools/Scripts/check-for-exit-time-destructors ]; then\n ../WebKitTools/Scripts/check-for-exit-time-destructors || exit $?\nfi"; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -1836,56 +1992,73 @@ files = ( 659126BD0BDD1728001921FB /* AllInOneFile.cpp in Sources */, 65FDE49C0BDD1D4A00E80111 /* Assertions.cpp in Sources */, + 1429D8DD0ED2205B00B89619 /* CallFrame.cpp in Sources */, + 1429D9C40ED23C3900B89619 /* CharacterClass.cpp in Sources */, + 7E2ADD900E79AC1100D50C51 /* CharacterClassConstructor.cpp in Sources */, + 969A07960ED1D3AE00F1F681 /* CodeBlock.cpp in Sources */, + E1A862D60D7F2B5C001EC6AA /* CollatorDefault.cpp in Sources */, + E1A862A90D7EBB76001EC6AA /* CollatorICU.cpp in Sources */, + 180B9BFE0F16E94D009BDBC5 /* CurrentTime.cpp in Sources */, + 149559EE0DDCDDF700648087 /* DebuggerCallFrame.cpp in Sources */, + 1429D8780ED21ACD00B89619 /* ExceptionHelpers.cpp in Sources */, + A7B48F490EE8936F00DCBDB6 /* ExecutableAllocator.cpp in Sources */, + A782F1A50EEC9FA20036273F /* ExecutableAllocatorPosix.cpp in Sources */, 65DFC93308EA173A00F7300B /* HashTable.cpp in Sources */, + 95FDFA140E22998F0006FB00 /* HeavyProfile.cpp in Sources */, + E178636D0D9BEEC300D74E75 /* InitializeThreading.cpp in Sources */, + 1429D7D40ED2128200B89619 /* Interpreter.cpp in Sources */, + 1429D92F0ED22D7000B89619 /* JIT.cpp in Sources */, + 86A90ED00EE7D51F00AB350D /* JITArithmetic.cpp in Sources */, + 86CC85A30EE79B7400288682 /* JITCall.cpp in Sources */, + 86CC85C40EE7A89400288682 /* JITPropertyAccess.cpp in Sources */, + 140B7D1D0DC69AF7009C42B8 /* JSActivation.cpp in Sources */, 1421359B0A677F4F00A8195E /* JSBase.cpp in Sources */, + A791EF290F11E07900AE1F68 /* JSByteArray.cpp in Sources */, 1440F8AF0A508D200005F061 /* JSCallbackConstructor.cpp in Sources */, 1440F8920A508B100005F061 /* JSCallbackFunction.cpp in Sources */, - 14909A2D0DCAF6CD00B29EB3 /* ExecState.cpp in Sources */, 14ABDF600A437FEF00ECCA01 /* JSCallbackObject.cpp in Sources */, - 140B7D1D0DC69AF7009C42B8 /* JSActivation.cpp in Sources */, 1440FCE40A51E46B0005F061 /* JSClassRef.cpp in Sources */, 14BD5A300A3E91F600BAF59C /* JSContextRef.cpp in Sources */, + E18E3A590DF9278C00D90B34 /* JSGlobalData.cpp in Sources */, + A72700900DAC6BBC00E548D7 /* JSNotAnObject.cpp in Sources */, 1482B7E40A43076000517CFC /* JSObjectRef.cpp in Sources */, + 95F6E6950E5B5F970091E860 /* JSProfilerPrivate.cpp in Sources */, + A727FF6B0DA3092200E548D7 /* JSPropertyNameIterator.cpp in Sources */, 1482B74E0A43032800517CFC /* JSStringRef.cpp in Sources */, 146AAB380B66A94400E55F16 /* JSStringRefCF.cpp in Sources */, 14BD5A320A3E91F600BAF59C /* JSValueRef.cpp in Sources */, - 14E0FF120DBAAED00007C0AB /* Machine.cpp in Sources */, - E1EF79AA0CE97BA60088D500 /* UTF8.cpp in Sources */, - 930754C108B0F68000AB3056 /* pcre_compile.cpp in Sources */, - 930754EB08B0F78500AB3056 /* pcre_exec.cpp in Sources */, - 930754D008B0F74600AB3056 /* pcre_tables.cpp in Sources */, - 937013480CA97E0E00FA14D3 /* pcre_ucp_searchfuncs.cpp in Sources */, - 93E26BD408B1514100F85226 /* pcre_xclass.cpp in Sources */, - E1EE793D0D6C9B9200FEA3BA /* ThreadingPthreads.cpp in Sources */, - E1A862A90D7EBB76001EC6AA /* CollatorICU.cpp in Sources */, - E1A862D60D7F2B5C001EC6AA /* CollatorDefault.cpp in Sources */, - E178636D0D9BEEC300D74E75 /* InitializeThreading.cpp in Sources */, - 95AB83420DA4322500BC83F3 /* Profiler.cpp in Sources */, - 95AB83560DA43C3000BC83F3 /* ProfileNode.cpp in Sources */, + BCFD8C920EEB2EE700283848 /* JumpTable.cpp in Sources */, 06D358B30DAADAA4003B174E /* MainThread.cpp in Sources */, 06D358B40DAADAAA003B174E /* MainThreadMac.mm in Sources */, + E124A8F80E555775003091F1 /* OpaqueJSString.cpp in Sources */, + 969A079A0ED1D3AE00F1F681 /* Opcode.cpp in Sources */, 95742F650DD11F5A000917FB /* Profile.cpp in Sources */, - 149B15EB0D81F986009CB8C7 /* Opcode.cpp in Sources */, - 149B1AA00D86ED73009CB8C7 /* CodeBlock.cpp in Sources */, - A727FF6B0DA3092200E548D7 /* JSPropertyNameIterator.cpp in Sources */, - A72700900DAC6BBC00E548D7 /* JSNotAnObject.cpp in Sources */, - A72701B60DADE94900E548D7 /* ExceptionHelpers.cpp in Sources */, - 149559EE0DDCDDF700648087 /* DebuggerCallFrame.cpp in Sources */, - E18E3A590DF9278C00D90B34 /* JSGlobalData.cpp in Sources */, - 95CD41B30E1BF6560085358E /* TreeProfile.cpp in Sources */, 95CD45760E1C4FDD0085358E /* ProfileGenerator.cpp in Sources */, - 95FDFA140E22998F0006FB00 /* HeavyProfile.cpp in Sources */, + 95AB83560DA43C3000BC83F3 /* ProfileNode.cpp in Sources */, + 95AB83420DA4322500BC83F3 /* Profiler.cpp in Sources */, + 1C61516C0EBAC7A00031376F /* ProfilerServer.mm in Sources */, + 088FA5BB0EF76D4300578E6F /* RandomNumber.cpp in Sources */, 905B02AE0E28640F006DF882 /* RefCountedLeakCounter.cpp in Sources */, - 8613F45A0E3A433E00C948FD /* SamplingTool.cpp in Sources */, - E124A8F80E555775003091F1 /* OpaqueJSString.cpp in Sources */, - 95F6E6950E5B5F970091E860 /* JSProfilerPrivate.cpp in Sources */, - 8683B02E0E636482004C19EE /* CTI.cpp in Sources */, - 869083150E6518D7000D36ED /* WREC.cpp in Sources */, + 1429D8850ED21C3D00B89619 /* SamplingTool.cpp in Sources */, 9330402C0E6A764000786E6A /* SmallStrings.cpp in Sources */, - BCDE3B430E6C832D001453A7 /* StructureID.cpp in Sources */, - 7E2ADD900E79AC1100D50C51 /* CharacterClassConstructor.cpp in Sources */, - 1C61516C0EBAC7A00031376F /* ProfilerServer.mm in Sources */, - 7E4EE70F0EBB7A5B005934AA /* StructureIDChain.cpp in Sources */, + BCDE3B430E6C832D001453A7 /* Structure.cpp in Sources */, + 7E4EE70F0EBB7A5B005934AA /* StructureChain.cpp in Sources */, + BCCF0D0C0EF0B8A500413C8F /* StructureStubInfo.cpp in Sources */, + 5D6A566B0F05995500266145 /* Threading.cpp in Sources */, + E1EE793D0D6C9B9200FEA3BA /* ThreadingPthreads.cpp in Sources */, + 95CD41B30E1BF6560085358E /* TreeProfile.cpp in Sources */, + E1EF79AA0CE97BA60088D500 /* UTF8.cpp in Sources */, + 869083150E6518D7000D36ED /* WREC.cpp in Sources */, + 1429DA820ED2482900B89619 /* WRECFunctors.cpp in Sources */, + 1429DAE10ED2645B00B89619 /* WRECGenerator.cpp in Sources */, + 1429DAC00ED263E700B89619 /* WRECParser.cpp in Sources */, + 930754C108B0F68000AB3056 /* pcre_compile.cpp in Sources */, + 930754EB08B0F78500AB3056 /* pcre_exec.cpp in Sources */, + 930754D008B0F74600AB3056 /* pcre_tables.cpp in Sources */, + 937013480CA97E0E00FA14D3 /* pcre_ucp_searchfuncs.cpp in Sources */, + 93E26BD408B1514100F85226 /* pcre_xclass.cpp in Sources */, + A7A1F7AC0F252B3C00E184E2 /* ByteArray.cpp in Sources */, + BC3135650F302FA3003DFD3A /* DebuggerActivation.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1893,7 +2066,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 932F5BDD0822A1C700736975 /* Shell.cpp in Sources */, + 932F5BDD0822A1C700736975 /* jsc.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/JavaScriptCore/JavaScriptCoreSources.bkl b/JavaScriptCore/JavaScriptCoreSources.bkl index f328d8d..7ba3e09 100644 --- a/JavaScriptCore/JavaScriptCoreSources.bkl +++ b/JavaScriptCore/JavaScriptCoreSources.bkl @@ -29,7 +29,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Source files for JSCore. --> <makefile> - <set append="1" var="JSCORE_SOURCES_API"> + <set append="1" var="JSCORE_API_SOURCES"> API/JSBase.cpp API/JSCallbackConstructor.cpp API/JSCallbackFunction.cpp @@ -41,32 +41,30 @@ Source files for JSCore. API/JSValueRef.cpp API/OpaqueJSString.cpp </set> + <set append="1" var="JSCORE_BYTECOMPILER_SOURCES"> + bytecompiler/BytecodeGenerator.cpp + </set> <set append="1" var="JSCORE_DEBUGGER_SOURCES"> debugger/Debugger.cpp + debugger/DebuggerActivation.cpp debugger/DebuggerCallFrame.cpp </set> - <set append="1" var="JSCORE_SOURCES_KJS"> - DerivedSources/JavaScriptCore/grammar.cpp - kjs/collector.cpp - kjs/dtoa.cpp - kjs/identifier.cpp - kjs/interpreter.cpp - kjs/lexer.cpp - kjs/lookup.cpp - kjs/nodes.cpp - kjs/nodes2string.cpp - kjs/operations.cpp - kjs/Parser.cpp - kjs/regexp.cpp - kjs/ustring.cpp + <set append="1" var="JSCORE_JSC_SOURCES"> + DerivedSources/JavaScriptCore/Grammar.cpp + wtf/dtoa.cpp </set> - <set append="1" var="JSCORE_SOURCES_PCRE"> + <set append="1" var="JSCORE_PCRE_SOURCES"> pcre/pcre_compile.cpp pcre/pcre_exec.cpp pcre/pcre_tables.cpp pcre/pcre_ucp_searchfuncs.cpp pcre/pcre_xclass.cpp </set> + <set append="1" var="JSCORE_PARSER_SOURCES"> + parser/Lexer.cpp + parser/Nodes.cpp + parser/Parser.cpp + </set> <set append="1" var="JSCORE_PROFILER_SOURCES"> profiler/HeavyProfile.cpp profiler/ProfileGenerator.cpp @@ -84,6 +82,7 @@ Source files for JSCore. runtime/BooleanObject.cpp runtime/BooleanPrototype.cpp runtime/CallData.cpp + runtime/Collector.cpp runtime/CommonIdentifiers.cpp runtime/ConstructData.cpp runtime/DateConstructor.cpp @@ -94,15 +93,18 @@ Source files for JSCore. runtime/ErrorConstructor.cpp runtime/ErrorInstance.cpp runtime/ErrorPrototype.cpp - runtime/ExecState.cpp + interpreter/CallFrame.cpp runtime/FunctionConstructor.cpp runtime/FunctionPrototype.cpp runtime/GetterSetter.cpp runtime/GlobalEvalFunction.cpp + runtime/Identifier.cpp runtime/InitializeThreading.cpp runtime/InternalFunction.cpp + runtime/Completion.cpp runtime/JSActivation.cpp runtime/JSArray.cpp + runtime/JSByteArray.cpp runtime/JSCell.cpp runtime/JSFunction.cpp runtime/JSGlobalData.cpp @@ -119,6 +121,7 @@ Source files for JSCore. runtime/JSValue.cpp runtime/JSVariableObject.cpp runtime/JSWrapperObject.cpp + runtime/Lookup.cpp runtime/MathObject.cpp runtime/NativeErrorConstructor.cpp runtime/NativeErrorPrototype.cpp @@ -127,9 +130,11 @@ Source files for JSCore. runtime/NumberPrototype.cpp runtime/ObjectConstructor.cpp runtime/ObjectPrototype.cpp + runtime/Operations.cpp runtime/PropertyNameArray.cpp runtime/PropertySlot.cpp runtime/PrototypeFunction.cpp + runtime/RegExp.cpp runtime/RegExpConstructor.cpp runtime/RegExpObject.cpp runtime/RegExpPrototype.cpp @@ -138,25 +143,31 @@ Source files for JSCore. runtime/StringConstructor.cpp runtime/StringObject.cpp runtime/StringPrototype.cpp - runtime/StructureID.cpp - runtime/StructureIDChain.cpp + runtime/Structure.cpp + runtime/StructureChain.cpp + runtime/UString.cpp </set> <set append="1" var="JSCORE_VM_SOURCES"> - VM/CodeBlock.cpp - VM/CodeGenerator.cpp - VM/ExceptionHelpers.cpp - VM/Machine.cpp - VM/Opcode.cpp - VM/SamplingTool.cpp - VM/RegisterFile.cpp + bytecode/CodeBlock.cpp + bytecode/StructureStubInfo.cpp + bytecode/JumpTable.cpp + runtime/ExceptionHelpers.cpp + interpreter/Interpreter.cpp + bytecode/Opcode.cpp + bytecode/SamplingTool.cpp + interpreter/RegisterFile.cpp </set> <set append="1" var="JSCORE_WTF_SOURCES"> wtf/Assertions.cpp + wtf/ByteArray.cpp + wtf/CurrentTime.cpp wtf/FastMalloc.cpp wtf/HashTable.cpp wtf/MainThread.cpp + wtf/RandomNumber.cpp wtf/RefCountedLeakCounter.cpp wtf/TCSystemAlloc.cpp + wtf/Threading.cpp wtf/ThreadingNone.cpp wtf/wx/MainThreadWx.cpp wtf/unicode/CollatorDefault.cpp diff --git a/JavaScriptCore/SConstruct b/JavaScriptCore/SConstruct new file mode 100644 index 0000000..b77d202 --- /dev/null +++ b/JavaScriptCore/SConstruct @@ -0,0 +1 @@ +SConscript(['JavaScriptCore.scons']) diff --git a/JavaScriptCore/VM/CTI.cpp b/JavaScriptCore/VM/CTI.cpp deleted file mode 100644 index 1ece843..0000000 --- a/JavaScriptCore/VM/CTI.cpp +++ /dev/null @@ -1,3532 +0,0 @@ -/* - * Copyright (C) 2008 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "CTI.h" - -#if ENABLE(CTI) - -#include "CodeBlock.h" -#include "JSArray.h" -#include "JSFunction.h" -#include "Machine.h" -#include "wrec/WREC.h" -#include "ResultType.h" -#include "SamplingTool.h" - -#ifndef NDEBUG -#include <stdio.h> -#endif - -using namespace std; - -namespace JSC { - -#if PLATFORM(MAC) - -static inline bool isSSE2Present() -{ - return true; // All X86 Macs are guaranteed to support at least SSE2 -} - -#else - -static bool isSSE2Present() -{ - static const int SSE2FeatureBit = 1 << 26; - struct SSE2Check { - SSE2Check() - { - int flags; -#if COMPILER(MSVC) - _asm { - mov eax, 1 // cpuid function 1 gives us the standard feature set - cpuid; - mov flags, edx; - } -#else - flags = 0; - // FIXME: Add GCC code to do above asm -#endif - present = (flags & SSE2FeatureBit) != 0; - } - bool present; - }; - static SSE2Check check; - return check.present; -} - -#endif - -COMPILE_ASSERT(CTI_ARGS_code == 0xC, CTI_ARGS_code_is_C); -COMPILE_ASSERT(CTI_ARGS_callFrame == 0xE, CTI_ARGS_callFrame_is_E); - -#if COMPILER(GCC) && PLATFORM(X86) - -#if PLATFORM(DARWIN) -#define SYMBOL_STRING(name) "_" #name -#else -#define SYMBOL_STRING(name) #name -#endif - -asm( -".globl " SYMBOL_STRING(ctiTrampoline) "\n" -SYMBOL_STRING(ctiTrampoline) ":" "\n" - "pushl %esi" "\n" - "pushl %edi" "\n" - "pushl %ebx" "\n" - "subl $0x20, %esp" "\n" - "movl $512, %esi" "\n" - "movl 0x38(%esp), %edi" "\n" // Ox38 = 0x0E * 4, 0x0E = CTI_ARGS_callFrame (see assertion above) - "call *0x30(%esp)" "\n" // Ox30 = 0x0C * 4, 0x0C = CTI_ARGS_code (see assertion above) - "addl $0x20, %esp" "\n" - "popl %ebx" "\n" - "popl %edi" "\n" - "popl %esi" "\n" - "ret" "\n" -); - -asm( -".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n" -SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n" -#if USE(CTI_ARGUMENT) -#if USE(FAST_CALL_CTI_ARGUMENT) - "movl %esp, %ecx" "\n" -#else - "movl %esp, 0(%esp)" "\n" -#endif - "call " SYMBOL_STRING(_ZN3JSC7Machine12cti_vm_throwEPPv) "\n" -#else - "call " SYMBOL_STRING(_ZN3JSC7Machine12cti_vm_throwEPvz) "\n" -#endif - "addl $0x20, %esp" "\n" - "popl %ebx" "\n" - "popl %edi" "\n" - "popl %esi" "\n" - "ret" "\n" -); - -#elif COMPILER(MSVC) - -extern "C" { - - __declspec(naked) JSValue* ctiTrampoline(void* code, RegisterFile*, CallFrame*, JSValue** exception, Profiler**, JSGlobalData*) - { - __asm { - push esi; - push edi; - push ebx; - sub esp, 0x20; - mov esi, 512; - mov ecx, esp; - mov edi, [esp + 0x38]; - call [esp + 0x30]; // Ox30 = 0x0C * 4, 0x0C = CTI_ARGS_code (see assertion above) - add esp, 0x20; - pop ebx; - pop edi; - pop esi; - ret; - } - } - - __declspec(naked) void ctiVMThrowTrampoline() - { - __asm { - mov ecx, esp; - call JSC::Machine::cti_vm_throw; - add esp, 0x20; - pop ebx; - pop edi; - pop esi; - ret; - } - } - -} - -#endif - -ALWAYS_INLINE bool CTI::isConstant(int src) -{ - return src >= m_codeBlock->numVars && src < m_codeBlock->numVars + m_codeBlock->numConstants; -} - -ALWAYS_INLINE JSValue* CTI::getConstant(CallFrame* callFrame, int src) -{ - return m_codeBlock->constantRegisters[src - m_codeBlock->numVars].jsValue(callFrame); -} - -inline uintptr_t CTI::asInteger(JSValue* value) -{ - return reinterpret_cast<uintptr_t>(value); -} - -// get arg puts an arg from the SF register array into a h/w register -ALWAYS_INLINE void CTI::emitGetArg(int src, X86Assembler::RegisterID dst) -{ - // TODO: we want to reuse values that are already in registers if we can - add a register allocator! - if (isConstant(src)) { - JSValue* js = getConstant(m_callFrame, src); - m_jit.movl_i32r(asInteger(js), dst); - } else - m_jit.movl_mr(src * sizeof(Register), X86::edi, dst); -} - -// get arg puts an arg from the SF register array onto the stack, as an arg to a context threaded function. -ALWAYS_INLINE void CTI::emitGetPutArg(unsigned src, unsigned offset, X86Assembler::RegisterID scratch) -{ - if (isConstant(src)) { - JSValue* js = getConstant(m_callFrame, src); - m_jit.movl_i32m(asInteger(js), offset + sizeof(void*), X86::esp); - } else { - m_jit.movl_mr(src * sizeof(Register), X86::edi, scratch); - m_jit.movl_rm(scratch, offset + sizeof(void*), X86::esp); - } -} - -// puts an arg onto the stack, as an arg to a context threaded function. -ALWAYS_INLINE void CTI::emitPutArg(X86Assembler::RegisterID src, unsigned offset) -{ - m_jit.movl_rm(src, offset + sizeof(void*), X86::esp); -} - -ALWAYS_INLINE void CTI::emitPutArgConstant(unsigned value, unsigned offset) -{ - m_jit.movl_i32m(value, offset + sizeof(void*), X86::esp); -} - -ALWAYS_INLINE JSValue* CTI::getConstantImmediateNumericArg(unsigned src) -{ - if (isConstant(src)) { - JSValue* js = getConstant(m_callFrame, src); - return JSImmediate::isNumber(js) ? js : noValue(); - } - return noValue(); -} - -ALWAYS_INLINE void CTI::emitPutCTIParam(void* value, unsigned name) -{ - m_jit.movl_i32m(reinterpret_cast<intptr_t>(value), name * sizeof(void*), X86::esp); -} - -ALWAYS_INLINE void CTI::emitPutCTIParam(X86Assembler::RegisterID from, unsigned name) -{ - m_jit.movl_rm(from, name * sizeof(void*), X86::esp); -} - -ALWAYS_INLINE void CTI::emitGetCTIParam(unsigned name, X86Assembler::RegisterID to) -{ - m_jit.movl_mr(name * sizeof(void*), X86::esp, to); -} - -ALWAYS_INLINE void CTI::emitPutToCallFrameHeader(X86Assembler::RegisterID from, RegisterFile::CallFrameHeaderEntry entry) -{ - m_jit.movl_rm(from, entry * sizeof(Register), X86::edi); -} - -ALWAYS_INLINE void CTI::emitGetFromCallFrameHeader(RegisterFile::CallFrameHeaderEntry entry, X86Assembler::RegisterID to) -{ - m_jit.movl_mr(entry * sizeof(Register), X86::edi, to); -} - -ALWAYS_INLINE void CTI::emitPutResult(unsigned dst, X86Assembler::RegisterID from) -{ - m_jit.movl_rm(from, dst * sizeof(Register), X86::edi); - // FIXME: #ifndef NDEBUG, Write the correct m_type to the register. -} - -ALWAYS_INLINE void CTI::emitInitRegister(unsigned dst) -{ - m_jit.movl_i32m(asInteger(jsUndefined()), dst * sizeof(Register), X86::edi); - // FIXME: #ifndef NDEBUG, Write the correct m_type to the register. -} - -void ctiSetReturnAddress(void** where, void* what) -{ - *where = what; -} - -void ctiRepatchCallByReturnAddress(void* where, void* what) -{ - (static_cast<void**>(where))[-1] = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(what) - reinterpret_cast<uintptr_t>(where)); -} - -#ifndef NDEBUG - -void CTI::printOpcodeOperandTypes(unsigned src1, unsigned src2) -{ - char which1 = '*'; - if (isConstant(src1)) { - JSValue* js = getConstant(m_callFrame, src1); - which1 = - JSImmediate::isImmediate(js) ? - (JSImmediate::isNumber(js) ? 'i' : - JSImmediate::isBoolean(js) ? 'b' : - js->isUndefined() ? 'u' : - js->isNull() ? 'n' : '?') - : - (js->isString() ? 's' : - js->isObject() ? 'o' : - 'k'); - } - char which2 = '*'; - if (isConstant(src2)) { - JSValue* js = getConstant(m_callFrame, src2); - which2 = - JSImmediate::isImmediate(js) ? - (JSImmediate::isNumber(js) ? 'i' : - JSImmediate::isBoolean(js) ? 'b' : - js->isUndefined() ? 'u' : - js->isNull() ? 'n' : '?') - : - (js->isString() ? 's' : - js->isObject() ? 'o' : - 'k'); - } - if ((which1 != '*') | (which2 != '*')) - fprintf(stderr, "Types %c %c\n", which1, which2); -} - -#endif - -extern "C" { - static JSValue* FASTCALL allocateNumber(JSGlobalData* globalData) { - JSValue* result = new (globalData) JSNumberCell(globalData); - ASSERT(result); - return result; - } -} - -ALWAYS_INLINE void CTI::emitAllocateNumber(JSGlobalData* globalData, unsigned opcodeIndex) -{ - m_jit.movl_i32r(reinterpret_cast<intptr_t>(globalData), X86::ecx); - emitNakedFastCall(opcodeIndex, (void*)allocateNumber); -} - -ALWAYS_INLINE X86Assembler::JmpSrc CTI::emitNakedCall(unsigned opcodeIndex, X86::RegisterID r) -{ - X86Assembler::JmpSrc call = m_jit.emitCall(r); - m_calls.append(CallRecord(call, opcodeIndex)); - - return call; -} - -ALWAYS_INLINE X86Assembler::JmpSrc CTI::emitNakedCall(unsigned opcodeIndex, void(*function)()) -{ - X86Assembler::JmpSrc call = m_jit.emitCall(); - m_calls.append(CallRecord(call, reinterpret_cast<CTIHelper_v>(function), opcodeIndex)); - return call; -} - -ALWAYS_INLINE X86Assembler::JmpSrc CTI::emitNakedFastCall(unsigned opcodeIndex, void* function) -{ - X86Assembler::JmpSrc call = m_jit.emitCall(); - m_calls.append(CallRecord(call, reinterpret_cast<CTIHelper_v>(function), opcodeIndex)); - return call; -} - -ALWAYS_INLINE X86Assembler::JmpSrc CTI::emitCTICall(Instruction* vPC, unsigned opcodeIndex, CTIHelper_j helper) -{ -#if ENABLE(OPCODE_SAMPLING) - m_jit.movl_i32m(m_machine->sampler()->encodeSample(vPC, true), m_machine->sampler()->sampleSlot()); -#else - UNUSED_PARAM(vPC); -#endif - m_jit.emitRestoreArgumentReference(); - emitPutCTIParam(X86::edi, CTI_ARGS_callFrame); - X86Assembler::JmpSrc call = m_jit.emitCall(); - m_calls.append(CallRecord(call, helper, opcodeIndex)); -#if ENABLE(OPCODE_SAMPLING) - m_jit.movl_i32m(m_machine->sampler()->encodeSample(vPC, false), m_machine->sampler()->sampleSlot()); -#endif - - return call; -} - -ALWAYS_INLINE X86Assembler::JmpSrc CTI::emitCTICall(Instruction* vPC, unsigned opcodeIndex, CTIHelper_o helper) -{ -#if ENABLE(OPCODE_SAMPLING) - m_jit.movl_i32m(m_machine->sampler()->encodeSample(vPC, true), m_machine->sampler()->sampleSlot()); -#else - UNUSED_PARAM(vPC); -#endif - m_jit.emitRestoreArgumentReference(); - emitPutCTIParam(X86::edi, CTI_ARGS_callFrame); - X86Assembler::JmpSrc call = m_jit.emitCall(); - m_calls.append(CallRecord(call, helper, opcodeIndex)); -#if ENABLE(OPCODE_SAMPLING) - m_jit.movl_i32m(m_machine->sampler()->encodeSample(vPC, false), m_machine->sampler()->sampleSlot()); -#endif - - return call; -} - -ALWAYS_INLINE X86Assembler::JmpSrc CTI::emitCTICall(Instruction* vPC, unsigned opcodeIndex, CTIHelper_p helper) -{ -#if ENABLE(OPCODE_SAMPLING) - m_jit.movl_i32m(m_machine->sampler()->encodeSample(vPC, true), m_machine->sampler()->sampleSlot()); -#else - UNUSED_PARAM(vPC); -#endif - m_jit.emitRestoreArgumentReference(); - emitPutCTIParam(X86::edi, CTI_ARGS_callFrame); - X86Assembler::JmpSrc call = m_jit.emitCall(); - m_calls.append(CallRecord(call, helper, opcodeIndex)); -#if ENABLE(OPCODE_SAMPLING) - m_jit.movl_i32m(m_machine->sampler()->encodeSample(vPC, false), m_machine->sampler()->sampleSlot()); -#endif - - return call; -} - -ALWAYS_INLINE X86Assembler::JmpSrc CTI::emitCTICall(Instruction* vPC, unsigned opcodeIndex, CTIHelper_b helper) -{ -#if ENABLE(OPCODE_SAMPLING) - m_jit.movl_i32m(m_machine->sampler()->encodeSample(vPC, true), m_machine->sampler()->sampleSlot()); -#else - UNUSED_PARAM(vPC); -#endif - m_jit.emitRestoreArgumentReference(); - emitPutCTIParam(X86::edi, CTI_ARGS_callFrame); - X86Assembler::JmpSrc call = m_jit.emitCall(); - m_calls.append(CallRecord(call, helper, opcodeIndex)); -#if ENABLE(OPCODE_SAMPLING) - m_jit.movl_i32m(m_machine->sampler()->encodeSample(vPC, false), m_machine->sampler()->sampleSlot()); -#endif - - return call; -} - -ALWAYS_INLINE X86Assembler::JmpSrc CTI::emitCTICall(Instruction* vPC, unsigned opcodeIndex, CTIHelper_v helper) -{ -#if ENABLE(OPCODE_SAMPLING) - m_jit.movl_i32m(m_machine->sampler()->encodeSample(vPC, true), m_machine->sampler()->sampleSlot()); -#else - UNUSED_PARAM(vPC); -#endif - m_jit.emitRestoreArgumentReference(); - emitPutCTIParam(X86::edi, CTI_ARGS_callFrame); - X86Assembler::JmpSrc call = m_jit.emitCall(); - m_calls.append(CallRecord(call, helper, opcodeIndex)); -#if ENABLE(OPCODE_SAMPLING) - m_jit.movl_i32m(m_machine->sampler()->encodeSample(vPC, false), m_machine->sampler()->sampleSlot()); -#endif - - return call; -} - -ALWAYS_INLINE X86Assembler::JmpSrc CTI::emitCTICall(Instruction* vPC, unsigned opcodeIndex, CTIHelper_s helper) -{ -#if ENABLE(OPCODE_SAMPLING) - m_jit.movl_i32m(m_machine->sampler()->encodeSample(vPC, true), m_machine->sampler()->sampleSlot()); -#else - UNUSED_PARAM(vPC); -#endif - m_jit.emitRestoreArgumentReference(); - emitPutCTIParam(X86::edi, CTI_ARGS_callFrame); - X86Assembler::JmpSrc call = m_jit.emitCall(); - m_calls.append(CallRecord(call, helper, opcodeIndex)); -#if ENABLE(OPCODE_SAMPLING) - m_jit.movl_i32m(m_machine->sampler()->encodeSample(vPC, false), m_machine->sampler()->sampleSlot()); -#endif - - return call; -} - -ALWAYS_INLINE X86Assembler::JmpSrc CTI::emitCTICall(Instruction* vPC, unsigned opcodeIndex, CTIHelper_2 helper) -{ -#if ENABLE(OPCODE_SAMPLING) - m_jit.movl_i32m(m_machine->sampler()->encodeSample(vPC, true), m_machine->sampler()->sampleSlot()); -#else - UNUSED_PARAM(vPC); -#endif - m_jit.emitRestoreArgumentReference(); - emitPutCTIParam(X86::edi, CTI_ARGS_callFrame); - X86Assembler::JmpSrc call = m_jit.emitCall(); - m_calls.append(CallRecord(call, helper, opcodeIndex)); -#if ENABLE(OPCODE_SAMPLING) - m_jit.movl_i32m(m_machine->sampler()->encodeSample(vPC, false), m_machine->sampler()->sampleSlot()); -#endif - - return call; -} - -ALWAYS_INLINE void CTI::emitJumpSlowCaseIfNotJSCell(X86Assembler::RegisterID reg, unsigned opcodeIndex) -{ - m_jit.testl_i32r(JSImmediate::TagMask, reg); - m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJne(), opcodeIndex)); -} - -ALWAYS_INLINE void CTI::emitJumpSlowCaseIfNotImmNum(X86Assembler::RegisterID reg, unsigned opcodeIndex) -{ - m_jit.testl_i32r(JSImmediate::TagBitTypeInteger, reg); - m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJe(), opcodeIndex)); -} - -ALWAYS_INLINE void CTI::emitJumpSlowCaseIfNotImmNums(X86Assembler::RegisterID reg1, X86Assembler::RegisterID reg2, unsigned opcodeIndex) -{ - m_jit.movl_rr(reg1, X86::ecx); - m_jit.andl_rr(reg2, X86::ecx); - emitJumpSlowCaseIfNotImmNum(X86::ecx, opcodeIndex); -} - -ALWAYS_INLINE unsigned CTI::getDeTaggedConstantImmediate(JSValue* imm) -{ - ASSERT(JSImmediate::isNumber(imm)); - return asInteger(imm) & ~JSImmediate::TagBitTypeInteger; -} - -ALWAYS_INLINE void CTI::emitFastArithDeTagImmediate(X86Assembler::RegisterID reg) -{ - m_jit.subl_i8r(JSImmediate::TagBitTypeInteger, reg); -} - -ALWAYS_INLINE X86Assembler::JmpSrc CTI::emitFastArithDeTagImmediateJumpIfZero(X86Assembler::RegisterID reg) -{ - m_jit.subl_i8r(JSImmediate::TagBitTypeInteger, reg); - return m_jit.emitUnlinkedJe(); -} - -ALWAYS_INLINE void CTI::emitFastArithReTagImmediate(X86Assembler::RegisterID reg) -{ - m_jit.addl_i8r(JSImmediate::TagBitTypeInteger, reg); -} - -ALWAYS_INLINE void CTI::emitFastArithPotentiallyReTagImmediate(X86Assembler::RegisterID reg) -{ - m_jit.orl_i32r(JSImmediate::TagBitTypeInteger, reg); -} - -ALWAYS_INLINE void CTI::emitFastArithImmToInt(X86Assembler::RegisterID reg) -{ - m_jit.sarl_i8r(1, reg); -} - -ALWAYS_INLINE void CTI::emitFastArithIntToImmOrSlowCase(X86Assembler::RegisterID reg, unsigned opcodeIndex) -{ - m_jit.addl_rr(reg, reg); - m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJo(), opcodeIndex)); - emitFastArithReTagImmediate(reg); -} - -ALWAYS_INLINE void CTI::emitFastArithIntToImmNoCheck(X86Assembler::RegisterID reg) -{ - m_jit.addl_rr(reg, reg); - emitFastArithReTagImmediate(reg); -} - -ALWAYS_INLINE X86Assembler::JmpSrc CTI::emitArithIntToImmWithJump(X86Assembler::RegisterID reg) -{ - m_jit.addl_rr(reg, reg); - X86Assembler::JmpSrc jmp = m_jit.emitUnlinkedJo(); - emitFastArithReTagImmediate(reg); - return jmp; -} - -ALWAYS_INLINE void CTI::emitTagAsBoolImmediate(X86Assembler::RegisterID reg) -{ - m_jit.shl_i8r(JSImmediate::ExtendedPayloadShift, reg); - m_jit.orl_i32r(JSImmediate::FullTagTypeBool, reg); -} - -CTI::CTI(Machine* machine, CallFrame* callFrame, CodeBlock* codeBlock) - : m_jit(machine->jitCodeBuffer()) - , m_machine(machine) - , m_callFrame(callFrame) - , m_codeBlock(codeBlock) - , m_labels(codeBlock ? codeBlock->instructions.size() : 0) - , m_propertyAccessCompilationInfo(codeBlock ? codeBlock->propertyAccessInstructions.size() : 0) - , m_callStructureStubCompilationInfo(codeBlock ? codeBlock->callLinkInfos.size() : 0) -{ -} - -#define CTI_COMPILE_BINARY_OP(name) \ - case name: { \ - emitGetPutArg(instruction[i + 2].u.operand, 0, X86::ecx); \ - emitGetPutArg(instruction[i + 3].u.operand, 4, X86::ecx); \ - emitCTICall(instruction + i, i, Machine::cti_##name); \ - emitPutResult(instruction[i + 1].u.operand); \ - i += 4; \ - break; \ - } - -#define CTI_COMPILE_UNARY_OP(name) \ - case name: { \ - emitGetPutArg(instruction[i + 2].u.operand, 0, X86::ecx); \ - emitCTICall(instruction + i, i, Machine::cti_##name); \ - emitPutResult(instruction[i + 1].u.operand); \ - i += 3; \ - break; \ - } - -static void unreachable() -{ - ASSERT_NOT_REACHED(); - exit(1); -} - -void CTI::compileOpCallInitializeCallFrame(unsigned callee, unsigned argCount) -{ - emitGetArg(callee, X86::ecx); // Load callee JSFunction into ecx - m_jit.movl_rm(X86::eax, RegisterFile::CodeBlock * static_cast<int>(sizeof(Register)), X86::edx); // callee CodeBlock was returned in eax - m_jit.movl_i32m(asInteger(noValue()), RegisterFile::OptionalCalleeArguments * static_cast<int>(sizeof(Register)), X86::edx); - m_jit.movl_rm(X86::ecx, RegisterFile::Callee * static_cast<int>(sizeof(Register)), X86::edx); - - m_jit.movl_mr(OBJECT_OFFSET(JSFunction, m_scopeChain) + OBJECT_OFFSET(ScopeChain, m_node), X86::ecx, X86::ebx); // newScopeChain - m_jit.movl_i32m(argCount, RegisterFile::ArgumentCount * static_cast<int>(sizeof(Register)), X86::edx); - m_jit.movl_rm(X86::edi, RegisterFile::CallerFrame * static_cast<int>(sizeof(Register)), X86::edx); - m_jit.movl_rm(X86::ebx, RegisterFile::ScopeChain * static_cast<int>(sizeof(Register)), X86::edx); -} - -void CTI::compileOpCallSetupArgs(Instruction* instruction, bool isConstruct, bool isEval) -{ - int firstArg = instruction[4].u.operand; - int argCount = instruction[5].u.operand; - int registerOffset = instruction[6].u.operand; - - emitPutArg(X86::ecx, 0); - emitPutArgConstant(registerOffset, 4); - emitPutArgConstant(argCount, 8); - emitPutArgConstant(reinterpret_cast<unsigned>(instruction), 12); - if (isConstruct) { - emitGetPutArg(instruction[3].u.operand, 16, X86::eax); - emitPutArgConstant(firstArg, 20); - } else if (isEval) - emitGetPutArg(instruction[3].u.operand, 16, X86::eax); -} - -void CTI::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned i, unsigned callLinkInfoIndex) -{ - int dst = instruction[1].u.operand; - int callee = instruction[2].u.operand; - int firstArg = instruction[4].u.operand; - int argCount = instruction[5].u.operand; - int registerOffset = instruction[6].u.operand; - - // Setup this value as the first argument (does not apply to constructors) - if (opcodeID != op_construct) { - int thisVal = instruction[3].u.operand; - if (thisVal == missingThisObjectMarker()) { - // FIXME: should this be loaded dynamically off m_callFrame? - m_jit.movl_i32m(asInteger(m_callFrame->globalThisValue()), firstArg * sizeof(Register), X86::edi); - } else { - emitGetArg(thisVal, X86::eax); - emitPutResult(firstArg); - } - } - - // Handle eval - X86Assembler::JmpSrc wasEval; - if (opcodeID == op_call_eval) { - emitGetArg(callee, X86::ecx); - compileOpCallSetupArgs(instruction, false, true); - - emitCTICall(instruction, i, Machine::cti_op_call_eval); - m_jit.cmpl_i32r(asInteger(JSImmediate::impossibleValue()), X86::eax); - wasEval = m_jit.emitUnlinkedJne(); - } - - // This plants a check for a cached JSFunction value, so we can plant a fast link to the callee. - // This deliberately leaves the callee in ecx, used when setting up the stack frame below - emitGetArg(callee, X86::ecx); - m_jit.cmpl_i32r(asInteger(JSImmediate::impossibleValue()), X86::ecx); - X86Assembler::JmpDst addressOfLinkedFunctionCheck = m_jit.label(); - m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJne(), i)); - ASSERT(X86Assembler::getDifferenceBetweenLabels(addressOfLinkedFunctionCheck, m_jit.label()) == repatchOffsetOpCallCall); - m_callStructureStubCompilationInfo[callLinkInfoIndex].hotPathBegin = addressOfLinkedFunctionCheck; - - // The following is the fast case, only used whan a callee can be linked. - - // In the case of OpConstruct, call oout to a cti_ function to create the new object. - if (opcodeID == op_construct) { - emitPutArg(X86::ecx, 0); - emitGetPutArg(instruction[3].u.operand, 4, X86::eax); - emitCTICall(instruction, i, Machine::cti_op_construct_JSConstructFast); - emitPutResult(instruction[4].u.operand); - emitGetArg(callee, X86::ecx); - } - - // Fast version of stack frame initialization, directly relative to edi. - // Note that this omits to set up RegisterFile::CodeBlock, which is set in the callee - m_jit.movl_i32m(asInteger(noValue()), (registerOffset + RegisterFile::OptionalCalleeArguments) * static_cast<int>(sizeof(Register)), X86::edi); - m_jit.movl_rm(X86::ecx, (registerOffset + RegisterFile::Callee) * static_cast<int>(sizeof(Register)), X86::edi); - m_jit.movl_mr(OBJECT_OFFSET(JSFunction, m_scopeChain) + OBJECT_OFFSET(ScopeChain, m_node), X86::ecx, X86::edx); // newScopeChain - m_jit.movl_i32m(argCount, (registerOffset + RegisterFile::ArgumentCount) * static_cast<int>(sizeof(Register)), X86::edi); - m_jit.movl_rm(X86::edi, (registerOffset + RegisterFile::CallerFrame) * static_cast<int>(sizeof(Register)), X86::edi); - m_jit.movl_rm(X86::edx, (registerOffset + RegisterFile::ScopeChain) * static_cast<int>(sizeof(Register)), X86::edi); - m_jit.addl_i32r(registerOffset * sizeof(Register), X86::edi); - - // Call to the callee - m_callStructureStubCompilationInfo[callLinkInfoIndex].hotPathOther = emitNakedCall(i, unreachable); - - if (opcodeID == op_call_eval) - m_jit.link(wasEval, m_jit.label()); - - // Put the return value in dst. In the interpreter, op_ret does this. - emitPutResult(dst); - -#if ENABLE(CODEBLOCK_SAMPLING) - m_jit.movl_i32m(reinterpret_cast<unsigned>(m_codeBlock), m_machine->sampler()->codeBlockSlot()); -#endif -} - -void CTI::compileOpStrictEq(Instruction* instruction, unsigned i, CompileOpStrictEqType type) -{ - bool negated = (type == OpNStrictEq); - - unsigned dst = instruction[1].u.operand; - unsigned src1 = instruction[2].u.operand; - unsigned src2 = instruction[3].u.operand; - - emitGetArg(src1, X86::eax); - emitGetArg(src2, X86::edx); - - m_jit.testl_i32r(JSImmediate::TagMask, X86::eax); - X86Assembler::JmpSrc firstNotImmediate = m_jit.emitUnlinkedJe(); - m_jit.testl_i32r(JSImmediate::TagMask, X86::edx); - X86Assembler::JmpSrc secondNotImmediate = m_jit.emitUnlinkedJe(); - - m_jit.cmpl_rr(X86::edx, X86::eax); - if (negated) - m_jit.setne_r(X86::eax); - else - m_jit.sete_r(X86::eax); - m_jit.movzbl_rr(X86::eax, X86::eax); - emitTagAsBoolImmediate(X86::eax); - - X86Assembler::JmpSrc bothWereImmediates = m_jit.emitUnlinkedJmp(); - - m_jit.link(firstNotImmediate, m_jit.label()); - - // check that edx is immediate but not the zero immediate - m_jit.testl_i32r(JSImmediate::TagMask, X86::edx); - m_jit.setz_r(X86::ecx); - m_jit.movzbl_rr(X86::ecx, X86::ecx); // ecx is now 1 if edx was nonimmediate - m_jit.cmpl_i32r(asInteger(JSImmediate::zeroImmediate()), X86::edx); - m_jit.sete_r(X86::edx); - m_jit.movzbl_rr(X86::edx, X86::edx); // edx is now 1 if edx was the 0 immediate - m_jit.orl_rr(X86::ecx, X86::edx); - - m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJnz(), i)); - - m_jit.movl_i32r(asInteger(jsBoolean(negated)), X86::eax); - - X86Assembler::JmpSrc firstWasNotImmediate = m_jit.emitUnlinkedJmp(); - - m_jit.link(secondNotImmediate, m_jit.label()); - // check that eax is not the zero immediate (we know it must be immediate) - m_jit.cmpl_i32r(asInteger(JSImmediate::zeroImmediate()), X86::eax); - m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJe(), i)); - - m_jit.movl_i32r(asInteger(jsBoolean(negated)), X86::eax); - - m_jit.link(bothWereImmediates, m_jit.label()); - m_jit.link(firstWasNotImmediate, m_jit.label()); - - emitPutResult(dst); -} - -void CTI::emitSlowScriptCheck(Instruction* vPC, unsigned opcodeIndex) -{ - m_jit.subl_i8r(1, X86::esi); - X86Assembler::JmpSrc skipTimeout = m_jit.emitUnlinkedJne(); - emitCTICall(vPC, opcodeIndex, Machine::cti_timeout_check); - - emitGetCTIParam(CTI_ARGS_globalData, X86::ecx); - m_jit.movl_mr(OBJECT_OFFSET(JSGlobalData, machine), X86::ecx, X86::ecx); - m_jit.movl_mr(OBJECT_OFFSET(Machine, m_ticksUntilNextTimeoutCheck), X86::ecx, X86::esi); - m_jit.link(skipTimeout, m_jit.label()); -} - -/* - This is required since number representation is canonical - values representable as a JSImmediate should not be stored in a JSNumberCell. - - In the common case, the double value from 'xmmSource' is written to the reusable JSNumberCell pointed to by 'jsNumberCell', then 'jsNumberCell' - is written to the output SF Register 'dst', and then a jump is planted (stored into *wroteJSNumberCell). - - However if the value from xmmSource is representable as a JSImmediate, then the JSImmediate value will be written to the output, and flow - control will fall through from the code planted. -*/ -void CTI::putDoubleResultToJSNumberCellOrJSImmediate(X86::XMMRegisterID xmmSource, X86::RegisterID jsNumberCell, unsigned dst, X86Assembler::JmpSrc* wroteJSNumberCell, X86::XMMRegisterID tempXmm, X86::RegisterID tempReg1, X86::RegisterID tempReg2) -{ - // convert (double -> JSImmediate -> double), and check if the value is unchanged - in which case the value is representable as a JSImmediate. - m_jit.cvttsd2si_rr(xmmSource, tempReg1); - m_jit.addl_rr(tempReg1, tempReg1); - m_jit.sarl_i8r(1, tempReg1); - m_jit.cvtsi2sd_rr(tempReg1, tempXmm); - // Compare & branch if immediate. - m_jit.ucomis_rr(tempXmm, xmmSource); - X86Assembler::JmpSrc resultIsImm = m_jit.emitUnlinkedJe(); - X86Assembler::JmpDst resultLookedLikeImmButActuallyIsnt = m_jit.label(); - - // Store the result to the JSNumberCell and jump. - m_jit.movsd_rm(xmmSource, OBJECT_OFFSET(JSNumberCell, m_value), jsNumberCell); - emitPutResult(dst, jsNumberCell); - *wroteJSNumberCell = m_jit.emitUnlinkedJmp(); - - m_jit.link(resultIsImm, m_jit.label()); - // value == (double)(JSImmediate)value... or at least, it looks that way... - // ucomi will report that (0 == -0), and will report true if either input in NaN (result is unordered). - m_jit.link(m_jit.emitUnlinkedJp(), resultLookedLikeImmButActuallyIsnt); // Actually was a NaN - m_jit.pextrw_irr(3, xmmSource, tempReg2); - m_jit.cmpl_i32r(0x8000, tempReg2); - m_jit.link(m_jit.emitUnlinkedJe(), resultLookedLikeImmButActuallyIsnt); // Actually was -0 - // Yes it really really really is representable as a JSImmediate. - emitFastArithIntToImmNoCheck(tempReg1); - emitPutResult(dst, tempReg1); -} - -void CTI::compileBinaryArithOp(OpcodeID opcodeID, unsigned dst, unsigned src1, unsigned src2, OperandTypes types, unsigned i) -{ - StructureID* numberStructureID = m_callFrame->globalData().numberStructureID.get(); - X86Assembler::JmpSrc wasJSNumberCell1, wasJSNumberCell1b, wasJSNumberCell2, wasJSNumberCell2b; - - emitGetArg(src1, X86::eax); - emitGetArg(src2, X86::edx); - - if (types.second().isReusable() && isSSE2Present()) { - ASSERT(types.second().mightBeNumber()); - - // Check op2 is a number - m_jit.testl_i32r(JSImmediate::TagBitTypeInteger, X86::edx); - X86Assembler::JmpSrc op2imm = m_jit.emitUnlinkedJne(); - if (!types.second().definitelyIsNumber()) { - emitJumpSlowCaseIfNotJSCell(X86::edx, i); - m_jit.cmpl_i32m(reinterpret_cast<unsigned>(numberStructureID), OBJECT_OFFSET(JSCell, m_structureID), X86::edx); - m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJne(), i)); - } - - // (1) In this case src2 is a reusable number cell. - // Slow case if src1 is not a number type. - m_jit.testl_i32r(JSImmediate::TagBitTypeInteger, X86::eax); - X86Assembler::JmpSrc op1imm = m_jit.emitUnlinkedJne(); - if (!types.first().definitelyIsNumber()) { - emitJumpSlowCaseIfNotJSCell(X86::eax, i); - m_jit.cmpl_i32m(reinterpret_cast<unsigned>(numberStructureID), OBJECT_OFFSET(JSCell, m_structureID), X86::eax); - m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJne(), i)); - } - - // (1a) if we get here, src1 is also a number cell - m_jit.movsd_mr(OBJECT_OFFSET(JSNumberCell, m_value), X86::eax, X86::xmm0); - X86Assembler::JmpSrc loadedDouble = m_jit.emitUnlinkedJmp(); - // (1b) if we get here, src1 is an immediate - m_jit.link(op1imm, m_jit.label()); - emitFastArithImmToInt(X86::eax); - m_jit.cvtsi2sd_rr(X86::eax, X86::xmm0); - // (1c) - m_jit.link(loadedDouble, m_jit.label()); - if (opcodeID == op_add) - m_jit.addsd_mr(OBJECT_OFFSET(JSNumberCell, m_value), X86::edx, X86::xmm0); - else if (opcodeID == op_sub) - m_jit.subsd_mr(OBJECT_OFFSET(JSNumberCell, m_value), X86::edx, X86::xmm0); - else { - ASSERT(opcodeID == op_mul); - m_jit.mulsd_mr(OBJECT_OFFSET(JSNumberCell, m_value), X86::edx, X86::xmm0); - } - - putDoubleResultToJSNumberCellOrJSImmediate(X86::xmm0, X86::edx, dst, &wasJSNumberCell2, X86::xmm1, X86::ecx, X86::eax); - wasJSNumberCell2b = m_jit.emitUnlinkedJmp(); - - // (2) This handles cases where src2 is an immediate number. - // Two slow cases - either src1 isn't an immediate, or the subtract overflows. - m_jit.link(op2imm, m_jit.label()); - emitJumpSlowCaseIfNotImmNum(X86::eax, i); - } else if (types.first().isReusable() && isSSE2Present()) { - ASSERT(types.first().mightBeNumber()); - - // Check op1 is a number - m_jit.testl_i32r(JSImmediate::TagBitTypeInteger, X86::eax); - X86Assembler::JmpSrc op1imm = m_jit.emitUnlinkedJne(); - if (!types.first().definitelyIsNumber()) { - emitJumpSlowCaseIfNotJSCell(X86::eax, i); - m_jit.cmpl_i32m(reinterpret_cast<unsigned>(numberStructureID), OBJECT_OFFSET(JSCell, m_structureID), X86::eax); - m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJne(), i)); - } - - // (1) In this case src1 is a reusable number cell. - // Slow case if src2 is not a number type. - m_jit.testl_i32r(JSImmediate::TagBitTypeInteger, X86::edx); - X86Assembler::JmpSrc op2imm = m_jit.emitUnlinkedJne(); - if (!types.second().definitelyIsNumber()) { - emitJumpSlowCaseIfNotJSCell(X86::edx, i); - m_jit.cmpl_i32m(reinterpret_cast<unsigned>(numberStructureID), OBJECT_OFFSET(JSCell, m_structureID), X86::edx); - m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJne(), i)); - } - - // (1a) if we get here, src2 is also a number cell - m_jit.movsd_mr(OBJECT_OFFSET(JSNumberCell, m_value), X86::edx, X86::xmm1); - X86Assembler::JmpSrc loadedDouble = m_jit.emitUnlinkedJmp(); - // (1b) if we get here, src2 is an immediate - m_jit.link(op2imm, m_jit.label()); - emitFastArithImmToInt(X86::edx); - m_jit.cvtsi2sd_rr(X86::edx, X86::xmm1); - // (1c) - m_jit.link(loadedDouble, m_jit.label()); - m_jit.movsd_mr(OBJECT_OFFSET(JSNumberCell, m_value), X86::eax, X86::xmm0); - if (opcodeID == op_add) - m_jit.addsd_rr(X86::xmm1, X86::xmm0); - else if (opcodeID == op_sub) - m_jit.subsd_rr(X86::xmm1, X86::xmm0); - else { - ASSERT(opcodeID == op_mul); - m_jit.mulsd_rr(X86::xmm1, X86::xmm0); - } - m_jit.movsd_rm(X86::xmm0, OBJECT_OFFSET(JSNumberCell, m_value), X86::eax); - emitPutResult(dst); - - putDoubleResultToJSNumberCellOrJSImmediate(X86::xmm0, X86::eax, dst, &wasJSNumberCell1, X86::xmm1, X86::ecx, X86::edx); - wasJSNumberCell1b = m_jit.emitUnlinkedJmp(); - - // (2) This handles cases where src1 is an immediate number. - // Two slow cases - either src2 isn't an immediate, or the subtract overflows. - m_jit.link(op1imm, m_jit.label()); - emitJumpSlowCaseIfNotImmNum(X86::edx, i); - } else - emitJumpSlowCaseIfNotImmNums(X86::eax, X86::edx, i); - - if (opcodeID == op_add) { - emitFastArithDeTagImmediate(X86::eax); - m_jit.addl_rr(X86::edx, X86::eax); - m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJo(), i)); - } else if (opcodeID == op_sub) { - m_jit.subl_rr(X86::edx, X86::eax); - m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJo(), i)); - emitFastArithReTagImmediate(X86::eax); - } else { - ASSERT(opcodeID == op_mul); - // convert eax & edx from JSImmediates to ints, and check if either are zero - emitFastArithImmToInt(X86::edx); - X86Assembler::JmpSrc op1Zero = emitFastArithDeTagImmediateJumpIfZero(X86::eax); - m_jit.testl_rr(X86::edx, X86::edx); - X86Assembler::JmpSrc op2NonZero = m_jit.emitUnlinkedJne(); - m_jit.link(op1Zero, m_jit.label()); - // if either input is zero, add the two together, and check if the result is < 0. - // If it is, we have a problem (N < 0), (N * 0) == -0, not representatble as a JSImmediate. - m_jit.movl_rr(X86::eax, X86::ecx); - m_jit.addl_rr(X86::edx, X86::ecx); - m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJs(), i)); - // Skip the above check if neither input is zero - m_jit.link(op2NonZero, m_jit.label()); - m_jit.imull_rr(X86::edx, X86::eax); - m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJo(), i)); - emitFastArithReTagImmediate(X86::eax); - } - emitPutResult(dst); - - if (types.second().isReusable() && isSSE2Present()) { - m_jit.link(wasJSNumberCell2, m_jit.label()); - m_jit.link(wasJSNumberCell2b, m_jit.label()); - } - else if (types.first().isReusable() && isSSE2Present()) { - m_jit.link(wasJSNumberCell1, m_jit.label()); - m_jit.link(wasJSNumberCell1b, m_jit.label()); - } -} - -void CTI::compileBinaryArithOpSlowCase(Instruction* vPC, OpcodeID opcodeID, Vector<SlowCaseEntry>::iterator& iter, unsigned dst, unsigned src1, unsigned src2, OperandTypes types, unsigned i) -{ - X86Assembler::JmpDst here = m_jit.label(); - m_jit.link(iter->from, here); - if (types.second().isReusable() && isSSE2Present()) { - if (!types.first().definitelyIsNumber()) { - m_jit.link((++iter)->from, here); - m_jit.link((++iter)->from, here); - } - if (!types.second().definitelyIsNumber()) { - m_jit.link((++iter)->from, here); - m_jit.link((++iter)->from, here); - } - m_jit.link((++iter)->from, here); - } else if (types.first().isReusable() && isSSE2Present()) { - if (!types.first().definitelyIsNumber()) { - m_jit.link((++iter)->from, here); - m_jit.link((++iter)->from, here); - } - if (!types.second().definitelyIsNumber()) { - m_jit.link((++iter)->from, here); - m_jit.link((++iter)->from, here); - } - m_jit.link((++iter)->from, here); - } else - m_jit.link((++iter)->from, here); - - // additional entry point to handle -0 cases. - if (opcodeID == op_mul) - m_jit.link((++iter)->from, here); - - emitGetPutArg(src1, 0, X86::ecx); - emitGetPutArg(src2, 4, X86::ecx); - if (opcodeID == op_add) - emitCTICall(vPC, i, Machine::cti_op_add); - else if (opcodeID == op_sub) - emitCTICall(vPC, i, Machine::cti_op_sub); - else { - ASSERT(opcodeID == op_mul); - emitCTICall(vPC, i, Machine::cti_op_mul); - } - emitPutResult(dst); -} - -void CTI::privateCompileMainPass() -{ - Instruction* instruction = m_codeBlock->instructions.begin(); - unsigned instructionCount = m_codeBlock->instructions.size(); - - unsigned propertyAccessInstructionIndex = 0; - unsigned callLinkInfoIndex = 0; - - for (unsigned i = 0; i < instructionCount; ) { - ASSERT_WITH_MESSAGE(m_machine->isOpcode(instruction[i].u.opcode), "privateCompileMainPass gone bad @ %d", i); - -#if ENABLE(OPCODE_SAMPLING) - if (i > 0) // Avoid the overhead of sampling op_enter twice. - m_jit.movl_i32m(m_machine->sampler()->encodeSample(instruction + i), m_machine->sampler()->sampleSlot()); -#endif - - m_labels[i] = m_jit.label(); - OpcodeID opcodeID = m_machine->getOpcodeID(instruction[i].u.opcode); - switch (opcodeID) { - case op_mov: { - unsigned src = instruction[i + 2].u.operand; - if (isConstant(src)) - m_jit.movl_i32r(asInteger(getConstant(m_callFrame, src)), X86::eax); - else - emitGetArg(src, X86::eax); - emitPutResult(instruction[i + 1].u.operand); - i += 3; - break; - } - case op_add: { - unsigned dst = instruction[i + 1].u.operand; - unsigned src1 = instruction[i + 2].u.operand; - unsigned src2 = instruction[i + 3].u.operand; - - if (JSValue* value = getConstantImmediateNumericArg(src1)) { - emitGetArg(src2, X86::edx); - emitJumpSlowCaseIfNotImmNum(X86::edx, i); - m_jit.addl_i32r(getDeTaggedConstantImmediate(value), X86::edx); - m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJo(), i)); - emitPutResult(dst, X86::edx); - } else if (JSValue* value = getConstantImmediateNumericArg(src2)) { - emitGetArg(src1, X86::eax); - emitJumpSlowCaseIfNotImmNum(X86::eax, i); - m_jit.addl_i32r(getDeTaggedConstantImmediate(value), X86::eax); - m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJo(), i)); - emitPutResult(dst); - } else { - OperandTypes types = OperandTypes::fromInt(instruction[i + 4].u.operand); - if (types.first().mightBeNumber() && types.second().mightBeNumber()) - compileBinaryArithOp(op_add, instruction[i + 1].u.operand, instruction[i + 2].u.operand, instruction[i + 3].u.operand, OperandTypes::fromInt(instruction[i + 4].u.operand), i); - else { - emitGetPutArg(instruction[i + 2].u.operand, 0, X86::ecx); - emitGetPutArg(instruction[i + 3].u.operand, 4, X86::ecx); - emitCTICall(instruction + i, i, Machine::cti_op_add); - emitPutResult(instruction[i + 1].u.operand); - } - } - - i += 5; - break; - } - case op_end: { - if (m_codeBlock->needsFullScopeChain) - emitCTICall(instruction + i, i, Machine::cti_op_end); - emitGetArg(instruction[i + 1].u.operand, X86::eax); - m_jit.pushl_m(RegisterFile::ReturnPC * static_cast<int>(sizeof(Register)), X86::edi); - m_jit.ret(); - i += 2; - break; - } - case op_jmp: { - unsigned target = instruction[i + 1].u.operand; - m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJmp(), i + 1 + target)); - i += 2; - break; - } - case op_pre_inc: { - int srcDst = instruction[i + 1].u.operand; - emitGetArg(srcDst, X86::eax); - emitJumpSlowCaseIfNotImmNum(X86::eax, i); - m_jit.addl_i8r(getDeTaggedConstantImmediate(JSImmediate::oneImmediate()), X86::eax); - m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJo(), i)); - emitPutResult(srcDst); - i += 2; - break; - } - case op_loop: { - emitSlowScriptCheck(instruction + i, i); - - unsigned target = instruction[i + 1].u.operand; - m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJmp(), i + 1 + target)); - i += 2; - break; - } - case op_loop_if_less: { - emitSlowScriptCheck(instruction + i, i); - - unsigned target = instruction[i + 3].u.operand; - JSValue* src2imm = getConstantImmediateNumericArg(instruction[i + 2].u.operand); - if (src2imm) { - emitGetArg(instruction[i + 1].u.operand, X86::edx); - emitJumpSlowCaseIfNotImmNum(X86::edx, i); - m_jit.cmpl_i32r(asInteger(src2imm), X86::edx); - m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJl(), i + 3 + target)); - } else { - emitGetArg(instruction[i + 1].u.operand, X86::eax); - emitGetArg(instruction[i + 2].u.operand, X86::edx); - emitJumpSlowCaseIfNotImmNum(X86::eax, i); - emitJumpSlowCaseIfNotImmNum(X86::edx, i); - m_jit.cmpl_rr(X86::edx, X86::eax); - m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJl(), i + 3 + target)); - } - i += 4; - break; - } - case op_loop_if_lesseq: { - emitSlowScriptCheck(instruction + i, i); - - unsigned target = instruction[i + 3].u.operand; - JSValue* src2imm = getConstantImmediateNumericArg(instruction[i + 2].u.operand); - if (src2imm) { - emitGetArg(instruction[i + 1].u.operand, X86::edx); - emitJumpSlowCaseIfNotImmNum(X86::edx, i); - m_jit.cmpl_i32r(asInteger(src2imm), X86::edx); - m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJle(), i + 3 + target)); - } else { - emitGetArg(instruction[i + 1].u.operand, X86::eax); - emitGetArg(instruction[i + 2].u.operand, X86::edx); - emitJumpSlowCaseIfNotImmNum(X86::eax, i); - emitJumpSlowCaseIfNotImmNum(X86::edx, i); - m_jit.cmpl_rr(X86::edx, X86::eax); - m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJle(), i + 3 + target)); - } - i += 4; - break; - } - case op_new_object: { - emitCTICall(instruction + i, i, Machine::cti_op_new_object); - emitPutResult(instruction[i + 1].u.operand); - i += 2; - break; - } - case op_put_by_id: { - // In order to be able to repatch both the StructureID, and the object offset, we store one pointer, - // to just after the arguments have been loaded into registers 'hotPathBegin', and we generate code - // such that the StructureID & offset are always at the same distance from this. - - emitGetArg(instruction[i + 1].u.operand, X86::eax); - emitGetArg(instruction[i + 3].u.operand, X86::edx); - - ASSERT(m_codeBlock->propertyAccessInstructions[propertyAccessInstructionIndex].opcodeIndex == i); - X86Assembler::JmpDst hotPathBegin = m_jit.label(); - m_propertyAccessCompilationInfo[propertyAccessInstructionIndex].hotPathBegin = hotPathBegin; - ++propertyAccessInstructionIndex; - - // Jump to a slow case if either the base object is an immediate, or if the StructureID does not match. - emitJumpSlowCaseIfNotJSCell(X86::eax, i); - // It is important that the following instruction plants a 32bit immediate, in order that it can be patched over. - m_jit.cmpl_i32m(repatchGetByIdDefaultStructureID, OBJECT_OFFSET(JSCell, m_structureID), X86::eax); - ASSERT(X86Assembler::getDifferenceBetweenLabels(hotPathBegin, m_jit.label()) == repatchOffsetPutByIdStructureID); - m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJne(), i)); - - // Plant a load from a bogus ofset in the object's property map; we will patch this later, if it is to be used. - m_jit.movl_mr(OBJECT_OFFSET(JSObject, m_propertyStorage), X86::eax, X86::eax); - m_jit.movl_rm(X86::edx, repatchGetByIdDefaultOffset, X86::eax); - ASSERT(X86Assembler::getDifferenceBetweenLabels(hotPathBegin, m_jit.label()) == repatchOffsetPutByIdPropertyMapOffset); - - i += 8; - break; - } - case op_get_by_id: { - // As for put_by_id, get_by_id requires the offset of the StructureID and the offset of the access to be repatched. - // Additionally, for get_by_id we need repatch the offset of the branch to the slow case (we repatch this to jump - // to array-length / prototype access tranpolines, and finally we also the the property-map access offset as a label - // to jump back to if one of these trampolies finds a match. - - emitGetArg(instruction[i + 2].u.operand, X86::eax); - - ASSERT(m_codeBlock->propertyAccessInstructions[propertyAccessInstructionIndex].opcodeIndex == i); - - X86Assembler::JmpDst hotPathBegin = m_jit.label(); - m_propertyAccessCompilationInfo[propertyAccessInstructionIndex].hotPathBegin = hotPathBegin; - ++propertyAccessInstructionIndex; - - emitJumpSlowCaseIfNotJSCell(X86::eax, i); - m_jit.cmpl_i32m(repatchGetByIdDefaultStructureID, OBJECT_OFFSET(JSCell, m_structureID), X86::eax); - ASSERT(X86Assembler::getDifferenceBetweenLabels(hotPathBegin, m_jit.label()) == repatchOffsetGetByIdStructureID); - m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJne(), i)); - ASSERT(X86Assembler::getDifferenceBetweenLabels(hotPathBegin, m_jit.label()) == repatchOffsetGetByIdBranchToSlowCase); - - m_jit.movl_mr(OBJECT_OFFSET(JSObject, m_propertyStorage), X86::eax, X86::eax); - m_jit.movl_mr(repatchGetByIdDefaultOffset, X86::eax, X86::ecx); - ASSERT(X86Assembler::getDifferenceBetweenLabels(hotPathBegin, m_jit.label()) == repatchOffsetGetByIdPropertyMapOffset); - emitPutResult(instruction[i + 1].u.operand, X86::ecx); - - i += 8; - break; - } - case op_instanceof: { - emitGetArg(instruction[i + 2].u.operand, X86::eax); // value - emitGetArg(instruction[i + 3].u.operand, X86::ecx); // baseVal - emitGetArg(instruction[i + 4].u.operand, X86::edx); // proto - - // check if any are immediates - m_jit.orl_rr(X86::eax, X86::ecx); - m_jit.orl_rr(X86::edx, X86::ecx); - m_jit.testl_i32r(JSImmediate::TagMask, X86::ecx); - - m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJnz(), i)); - - // check that all are object type - this is a bit of a bithack to avoid excess branching; - // we check that the sum of the three type codes from StructureIDs is exactly 3 * ObjectType, - // this works because NumberType and StringType are smaller - m_jit.movl_i32r(3 * ObjectType, X86::ecx); - m_jit.movl_mr(OBJECT_OFFSET(JSCell, m_structureID), X86::eax, X86::eax); - m_jit.movl_mr(OBJECT_OFFSET(JSCell, m_structureID), X86::edx, X86::edx); - m_jit.subl_mr(OBJECT_OFFSET(StructureID, m_typeInfo.m_type), X86::eax, X86::ecx); - m_jit.subl_mr(OBJECT_OFFSET(StructureID, m_typeInfo.m_type), X86::edx, X86::ecx); - emitGetArg(instruction[i + 3].u.operand, X86::edx); // reload baseVal - m_jit.movl_mr(OBJECT_OFFSET(JSCell, m_structureID), X86::edx, X86::edx); - m_jit.cmpl_rm(X86::ecx, OBJECT_OFFSET(StructureID, m_typeInfo.m_type), X86::edx); - - m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJne(), i)); - - // check that baseVal's flags include ImplementsHasInstance but not OverridesHasInstance - m_jit.movl_mr(OBJECT_OFFSET(StructureID, m_typeInfo.m_flags), X86::edx, X86::ecx); - m_jit.andl_i32r(ImplementsHasInstance | OverridesHasInstance, X86::ecx); - m_jit.cmpl_i32r(ImplementsHasInstance, X86::ecx); - - m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJne(), i)); - - emitGetArg(instruction[i + 2].u.operand, X86::ecx); // reload value - emitGetArg(instruction[i + 4].u.operand, X86::edx); // reload proto - - // optimistically load true result - m_jit.movl_i32r(asInteger(jsBoolean(true)), X86::eax); - - X86Assembler::JmpDst loop = m_jit.label(); - - // load value's prototype - m_jit.movl_mr(OBJECT_OFFSET(JSCell, m_structureID), X86::ecx, X86::ecx); - m_jit.movl_mr(OBJECT_OFFSET(StructureID, m_prototype), X86::ecx, X86::ecx); - - m_jit.cmpl_rr(X86::ecx, X86::edx); - X86Assembler::JmpSrc exit = m_jit.emitUnlinkedJe(); - - m_jit.cmpl_i32r(asInteger(jsNull()), X86::ecx); - X86Assembler::JmpSrc goToLoop = m_jit.emitUnlinkedJne(); - m_jit.link(goToLoop, loop); - - m_jit.movl_i32r(asInteger(jsBoolean(false)), X86::eax); - - m_jit.link(exit, m_jit.label()); - - emitPutResult(instruction[i + 1].u.operand); - - i += 5; - break; - } - case op_del_by_id: { - emitGetPutArg(instruction[i + 2].u.operand, 0, X86::ecx); - Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 3].u.operand]); - emitPutArgConstant(reinterpret_cast<unsigned>(ident), 4); - emitCTICall(instruction + i, i, Machine::cti_op_del_by_id); - emitPutResult(instruction[i + 1].u.operand); - i += 4; - break; - } - case op_mul: { - unsigned dst = instruction[i + 1].u.operand; - unsigned src1 = instruction[i + 2].u.operand; - unsigned src2 = instruction[i + 3].u.operand; - - // For now, only plant a fast int case if the constant operand is greater than zero. - JSValue* src1Value = getConstantImmediateNumericArg(src1); - JSValue* src2Value = getConstantImmediateNumericArg(src2); - int32_t value; - if (src1Value && ((value = JSImmediate::intValue(src1Value)) > 0)) { - emitGetArg(src2, X86::eax); - emitJumpSlowCaseIfNotImmNum(X86::eax, i); - emitFastArithDeTagImmediate(X86::eax); - m_jit.imull_i32r(X86::eax, value, X86::eax); - m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJo(), i)); - emitFastArithReTagImmediate(X86::eax); - emitPutResult(dst); - } else if (src2Value && ((value = JSImmediate::intValue(src2Value)) > 0)) { - emitGetArg(src1, X86::eax); - emitJumpSlowCaseIfNotImmNum(X86::eax, i); - emitFastArithDeTagImmediate(X86::eax); - m_jit.imull_i32r(X86::eax, value, X86::eax); - m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJo(), i)); - emitFastArithReTagImmediate(X86::eax); - emitPutResult(dst); - } else - compileBinaryArithOp(op_mul, instruction[i + 1].u.operand, instruction[i + 2].u.operand, instruction[i + 3].u.operand, OperandTypes::fromInt(instruction[i + 4].u.operand), i); - - i += 5; - break; - } - case op_new_func: { - FuncDeclNode* func = (m_codeBlock->functions[instruction[i + 2].u.operand]).get(); - emitPutArgConstant(reinterpret_cast<unsigned>(func), 0); - emitCTICall(instruction + i, i, Machine::cti_op_new_func); - emitPutResult(instruction[i + 1].u.operand); - i += 3; - break; - } - case op_call: { - compileOpCall(opcodeID, instruction + i, i, callLinkInfoIndex++); - i += 7; - break; - } - case op_get_global_var: { - JSVariableObject* globalObject = static_cast<JSVariableObject*>(instruction[i + 2].u.jsCell); - m_jit.movl_i32r(asInteger(globalObject), X86::eax); - emitGetVariableObjectRegister(X86::eax, instruction[i + 3].u.operand, X86::eax); - emitPutResult(instruction[i + 1].u.operand); - i += 4; - break; - } - case op_put_global_var: { - JSVariableObject* globalObject = static_cast<JSVariableObject*>(instruction[i + 1].u.jsCell); - m_jit.movl_i32r(asInteger(globalObject), X86::eax); - emitGetArg(instruction[i + 3].u.operand, X86::edx); - emitPutVariableObjectRegister(X86::edx, X86::eax, instruction[i + 2].u.operand); - i += 4; - break; - } - case op_get_scoped_var: { - int skip = instruction[i + 3].u.operand + m_codeBlock->needsFullScopeChain; - - emitGetArg(RegisterFile::ScopeChain, X86::eax); - while (skip--) - m_jit.movl_mr(OBJECT_OFFSET(ScopeChainNode, next), X86::eax, X86::eax); - - m_jit.movl_mr(OBJECT_OFFSET(ScopeChainNode, object), X86::eax, X86::eax); - emitGetVariableObjectRegister(X86::eax, instruction[i + 2].u.operand, X86::eax); - emitPutResult(instruction[i + 1].u.operand); - i += 4; - break; - } - case op_put_scoped_var: { - int skip = instruction[i + 2].u.operand + m_codeBlock->needsFullScopeChain; - - emitGetArg(RegisterFile::ScopeChain, X86::edx); - emitGetArg(instruction[i + 3].u.operand, X86::eax); - while (skip--) - m_jit.movl_mr(OBJECT_OFFSET(ScopeChainNode, next), X86::edx, X86::edx); - - m_jit.movl_mr(OBJECT_OFFSET(ScopeChainNode, object), X86::edx, X86::edx); - emitPutVariableObjectRegister(X86::eax, X86::edx, instruction[i + 1].u.operand); - i += 4; - break; - } - case op_tear_off_activation: { - emitGetPutArg(instruction[i + 1].u.operand, 0, X86::ecx); - emitCTICall(instruction + i, i, Machine::cti_op_tear_off_activation); - i += 2; - break; - } - case op_tear_off_arguments: { - emitCTICall(instruction + i, i, Machine::cti_op_tear_off_arguments); - i += 1; - break; - } - case op_ret: { - // We could JIT generate the deref, only calling out to C when the refcount hits zero. - if (m_codeBlock->needsFullScopeChain) - emitCTICall(instruction + i, i, Machine::cti_op_ret_scopeChain); - - // Return the result in %eax. - emitGetArg(instruction[i + 1].u.operand, X86::eax); - - // Grab the return address. - emitGetArg(RegisterFile::ReturnPC, X86::edx); - - // Restore our caller's "r". - emitGetArg(RegisterFile::CallerFrame, X86::edi); - - // Return. - m_jit.pushl_r(X86::edx); - m_jit.ret(); - - i += 2; - break; - } - case op_new_array: { - m_jit.leal_mr(sizeof(Register) * instruction[i + 2].u.operand, X86::edi, X86::edx); - emitPutArg(X86::edx, 0); - emitPutArgConstant(instruction[i + 3].u.operand, 4); - emitCTICall(instruction + i, i, Machine::cti_op_new_array); - emitPutResult(instruction[i + 1].u.operand); - i += 4; - break; - } - case op_resolve: { - Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 2].u.operand]); - emitPutArgConstant(reinterpret_cast<unsigned>(ident), 0); - emitCTICall(instruction + i, i, Machine::cti_op_resolve); - emitPutResult(instruction[i + 1].u.operand); - i += 3; - break; - } - case op_construct: { - compileOpCall(opcodeID, instruction + i, i, callLinkInfoIndex++); - i += 7; - break; - } - case op_construct_verify: { - emitGetArg(instruction[i + 1].u.operand, X86::eax); - - m_jit.testl_i32r(JSImmediate::TagMask, X86::eax); - X86Assembler::JmpSrc isImmediate = m_jit.emitUnlinkedJne(); - m_jit.movl_mr(OBJECT_OFFSET(JSCell, m_structureID), X86::eax, X86::ecx); - m_jit.cmpl_i32m(ObjectType, OBJECT_OFFSET(StructureID, m_typeInfo) + OBJECT_OFFSET(TypeInfo, m_type), X86::ecx); - X86Assembler::JmpSrc isObject = m_jit.emitUnlinkedJe(); - - m_jit.link(isImmediate, m_jit.label()); - emitGetArg(instruction[i + 2].u.operand, X86::eax); - emitPutResult(instruction[i + 1].u.operand); - m_jit.link(isObject, m_jit.label()); - - i += 3; - break; - } - case op_get_by_val: { - emitGetArg(instruction[i + 2].u.operand, X86::eax); - emitGetArg(instruction[i + 3].u.operand, X86::edx); - emitJumpSlowCaseIfNotImmNum(X86::edx, i); - emitFastArithImmToInt(X86::edx); - m_jit.testl_i32r(JSImmediate::TagMask, X86::eax); - m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJne(), i)); - m_jit.cmpl_i32m(reinterpret_cast<unsigned>(m_machine->m_jsArrayVptr), X86::eax); - m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJne(), i)); - - // This is an array; get the m_storage pointer into ecx, then check if the index is below the fast cutoff - m_jit.movl_mr(OBJECT_OFFSET(JSArray, m_storage), X86::eax, X86::ecx); - m_jit.cmpl_rm(X86::edx, OBJECT_OFFSET(JSArray, m_fastAccessCutoff), X86::eax); - m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJbe(), i)); - - // Get the value from the vector - m_jit.movl_mr(OBJECT_OFFSET(ArrayStorage, m_vector[0]), X86::ecx, X86::edx, sizeof(JSValue*), X86::eax); - emitPutResult(instruction[i + 1].u.operand); - i += 4; - break; - } - case op_resolve_func: { - Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 3].u.operand]); - emitPutArgConstant(reinterpret_cast<unsigned>(ident), 0); - emitCTICall(instruction + i, i, Machine::cti_op_resolve_func); - emitPutResult(instruction[i + 1].u.operand); - emitPutResult(instruction[i + 2].u.operand, X86::edx); - i += 4; - break; - } - case op_sub: { - compileBinaryArithOp(op_sub, instruction[i + 1].u.operand, instruction[i + 2].u.operand, instruction[i + 3].u.operand, OperandTypes::fromInt(instruction[i + 4].u.operand), i); - i += 5; - break; - } - case op_put_by_val: { - emitGetArg(instruction[i + 1].u.operand, X86::eax); - emitGetArg(instruction[i + 2].u.operand, X86::edx); - emitJumpSlowCaseIfNotImmNum(X86::edx, i); - emitFastArithImmToInt(X86::edx); - m_jit.testl_i32r(JSImmediate::TagMask, X86::eax); - m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJne(), i)); - m_jit.cmpl_i32m(reinterpret_cast<unsigned>(m_machine->m_jsArrayVptr), X86::eax); - m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJne(), i)); - - // This is an array; get the m_storage pointer into ecx, then check if the index is below the fast cutoff - m_jit.movl_mr(OBJECT_OFFSET(JSArray, m_storage), X86::eax, X86::ecx); - m_jit.cmpl_rm(X86::edx, OBJECT_OFFSET(JSArray, m_fastAccessCutoff), X86::eax); - X86Assembler::JmpSrc inFastVector = m_jit.emitUnlinkedJa(); - // No; oh well, check if the access if within the vector - if so, we may still be okay. - m_jit.cmpl_rm(X86::edx, OBJECT_OFFSET(ArrayStorage, m_vectorLength), X86::ecx); - m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJbe(), i)); - - // This is a write to the slow part of the vector; first, we have to check if this would be the first write to this location. - // FIXME: should be able to handle initial write to array; increment the the number of items in the array, and potentially update fast access cutoff. - m_jit.cmpl_i8m(0, OBJECT_OFFSET(ArrayStorage, m_vector[0]), X86::ecx, X86::edx, sizeof(JSValue*)); - m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJe(), i)); - - // All good - put the value into the array. - m_jit.link(inFastVector, m_jit.label()); - emitGetArg(instruction[i + 3].u.operand, X86::eax); - m_jit.movl_rm(X86::eax, OBJECT_OFFSET(ArrayStorage, m_vector[0]), X86::ecx, X86::edx, sizeof(JSValue*)); - i += 4; - break; - } - CTI_COMPILE_BINARY_OP(op_lesseq) - case op_loop_if_true: { - emitSlowScriptCheck(instruction + i, i); - - unsigned target = instruction[i + 2].u.operand; - emitGetArg(instruction[i + 1].u.operand, X86::eax); - - m_jit.cmpl_i32r(asInteger(JSImmediate::zeroImmediate()), X86::eax); - X86Assembler::JmpSrc isZero = m_jit.emitUnlinkedJe(); - m_jit.testl_i32r(JSImmediate::TagBitTypeInteger, X86::eax); - m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJne(), i + 2 + target)); - - m_jit.cmpl_i32r(asInteger(JSImmediate::trueImmediate()), X86::eax); - m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJe(), i + 2 + target)); - m_jit.cmpl_i32r(asInteger(JSImmediate::falseImmediate()), X86::eax); - m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJne(), i)); - - m_jit.link(isZero, m_jit.label()); - i += 3; - break; - }; - case op_resolve_base: { - Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 2].u.operand]); - emitPutArgConstant(reinterpret_cast<unsigned>(ident), 0); - emitCTICall(instruction + i, i, Machine::cti_op_resolve_base); - emitPutResult(instruction[i + 1].u.operand); - i += 3; - break; - } - case op_negate: { - emitGetArg(instruction[i + 2].u.operand, X86::eax); - m_jit.testl_i32r(JSImmediate::TagBitTypeInteger, X86::eax); - X86Assembler::JmpSrc notImmediate = m_jit.emitUnlinkedJe(); - - m_jit.cmpl_i32r(JSImmediate::TagBitTypeInteger, X86::eax); - X86Assembler::JmpSrc zeroImmediate = m_jit.emitUnlinkedJe(); - emitFastArithImmToInt(X86::eax); - m_jit.negl_r(X86::eax); // This can't overflow as we only have a 31bit int at this point - X86Assembler::JmpSrc overflow = emitArithIntToImmWithJump(X86::eax); - emitPutResult(instruction[i + 1].u.operand); - X86Assembler::JmpSrc immediateNegateSuccess = m_jit.emitUnlinkedJmp(); - - if (!isSSE2Present()) { - m_jit.link(zeroImmediate, m_jit.label()); - m_jit.link(overflow, m_jit.label()); - m_jit.link(notImmediate, m_jit.label()); - emitGetPutArg(instruction[i + 2].u.operand, 0, X86::ecx); - emitCTICall(instruction + i, i, Machine::cti_op_negate); - emitPutResult(instruction[i + 1].u.operand); - } else { - // Slow case immediates - m_slowCases.append(SlowCaseEntry(zeroImmediate, i)); - m_slowCases.append(SlowCaseEntry(overflow, i)); - m_jit.link(notImmediate, m_jit.label()); - ResultType resultType(instruction[i + 3].u.resultType); - if (!resultType.definitelyIsNumber()) { - emitJumpSlowCaseIfNotJSCell(X86::eax, i); - StructureID* numberStructureID = m_callFrame->globalData().numberStructureID.get(); - m_jit.cmpl_i32m(reinterpret_cast<unsigned>(numberStructureID), OBJECT_OFFSET(JSCell, m_structureID), X86::eax); - m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJne(), i)); - } - m_jit.movsd_mr(OBJECT_OFFSET(JSNumberCell, m_value), X86::eax, X86::xmm0); - // We need 3 copies of the sign bit mask so we can assure alignment and pad for the 128bit load - static double doubleSignBit[] = { -0.0, -0.0, -0.0 }; - m_jit.xorpd_mr((void*)((((uintptr_t)doubleSignBit)+15)&~15), X86::xmm0); - X86Assembler::JmpSrc wasCell; - if (!resultType.isReusableNumber()) - emitAllocateNumber(&m_callFrame->globalData(), i); - - putDoubleResultToJSNumberCellOrJSImmediate(X86::xmm0, X86::eax, instruction[i + 1].u.operand, &wasCell, - X86::xmm1, X86::ecx, X86::edx); - m_jit.link(wasCell, m_jit.label()); - } - m_jit.link(immediateNegateSuccess, m_jit.label()); - i += 4; - break; - } - case op_resolve_skip: { - Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 2].u.operand]); - emitPutArgConstant(reinterpret_cast<unsigned>(ident), 0); - emitPutArgConstant(instruction[i + 3].u.operand + m_codeBlock->needsFullScopeChain, 4); - emitCTICall(instruction + i, i, Machine::cti_op_resolve_skip); - emitPutResult(instruction[i + 1].u.operand); - i += 4; - break; - } - case op_resolve_global: { - // Fast case - unsigned globalObject = asInteger(instruction[i + 2].u.jsCell); - Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 3].u.operand]); - void* structureIDAddr = reinterpret_cast<void*>(instruction + i + 4); - void* offsetAddr = reinterpret_cast<void*>(instruction + i + 5); - - // Check StructureID of global object - m_jit.movl_i32r(globalObject, X86::eax); - m_jit.movl_mr(structureIDAddr, X86::edx); - m_jit.cmpl_rm(X86::edx, OBJECT_OFFSET(JSCell, m_structureID), X86::eax); - X86Assembler::JmpSrc noMatch = m_jit.emitUnlinkedJne(); // StructureIDs don't match - - // Load cached property - m_jit.movl_mr(OBJECT_OFFSET(JSGlobalObject, m_propertyStorage), X86::eax, X86::eax); - m_jit.movl_mr(offsetAddr, X86::edx); - m_jit.movl_mr(0, X86::eax, X86::edx, sizeof(JSValue*), X86::eax); - emitPutResult(instruction[i + 1].u.operand); - X86Assembler::JmpSrc end = m_jit.emitUnlinkedJmp(); - - // Slow case - m_jit.link(noMatch, m_jit.label()); - emitPutArgConstant(globalObject, 0); - emitPutArgConstant(reinterpret_cast<unsigned>(ident), 4); - emitPutArgConstant(reinterpret_cast<unsigned>(instruction + i), 8); - emitCTICall(instruction + i, i, Machine::cti_op_resolve_global); - emitPutResult(instruction[i + 1].u.operand); - m_jit.link(end, m_jit.label()); - i += 6; - break; - } - CTI_COMPILE_BINARY_OP(op_div) - case op_pre_dec: { - int srcDst = instruction[i + 1].u.operand; - emitGetArg(srcDst, X86::eax); - emitJumpSlowCaseIfNotImmNum(X86::eax, i); - m_jit.subl_i8r(getDeTaggedConstantImmediate(JSImmediate::oneImmediate()), X86::eax); - m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJo(), i)); - emitPutResult(srcDst); - i += 2; - break; - } - case op_jnless: { - unsigned target = instruction[i + 3].u.operand; - JSValue* src2imm = getConstantImmediateNumericArg(instruction[i + 2].u.operand); - if (src2imm) { - emitGetArg(instruction[i + 1].u.operand, X86::edx); - emitJumpSlowCaseIfNotImmNum(X86::edx, i); - m_jit.cmpl_i32r(asInteger(src2imm), X86::edx); - m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJge(), i + 3 + target)); - } else { - emitGetArg(instruction[i + 1].u.operand, X86::eax); - emitGetArg(instruction[i + 2].u.operand, X86::edx); - emitJumpSlowCaseIfNotImmNum(X86::eax, i); - emitJumpSlowCaseIfNotImmNum(X86::edx, i); - m_jit.cmpl_rr(X86::edx, X86::eax); - m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJge(), i + 3 + target)); - } - i += 4; - break; - } - case op_not: { - emitGetArg(instruction[i + 2].u.operand, X86::eax); - m_jit.xorl_i8r(JSImmediate::FullTagTypeBool, X86::eax); - m_jit.testl_i32r(JSImmediate::FullTagTypeMask, X86::eax); // i8? - m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJne(), i)); - m_jit.xorl_i8r((JSImmediate::FullTagTypeBool | JSImmediate::ExtendedPayloadBitBoolValue), X86::eax); - emitPutResult(instruction[i + 1].u.operand); - i += 3; - break; - } - case op_jfalse: { - unsigned target = instruction[i + 2].u.operand; - emitGetArg(instruction[i + 1].u.operand, X86::eax); - - m_jit.cmpl_i32r(asInteger(JSImmediate::zeroImmediate()), X86::eax); - m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJe(), i + 2 + target)); - m_jit.testl_i32r(JSImmediate::TagBitTypeInteger, X86::eax); - X86Assembler::JmpSrc isNonZero = m_jit.emitUnlinkedJne(); - - m_jit.cmpl_i32r(asInteger(JSImmediate::falseImmediate()), X86::eax); - m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJe(), i + 2 + target)); - m_jit.cmpl_i32r(asInteger(JSImmediate::trueImmediate()), X86::eax); - m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJne(), i)); - - m_jit.link(isNonZero, m_jit.label()); - i += 3; - break; - }; - case op_jeq_null: { - unsigned src = instruction[i + 1].u.operand; - unsigned target = instruction[i + 2].u.operand; - - emitGetArg(src, X86::eax); - m_jit.testl_i32r(JSImmediate::TagMask, X86::eax); - X86Assembler::JmpSrc isImmediate = m_jit.emitUnlinkedJnz(); - - m_jit.movl_mr(OBJECT_OFFSET(JSCell, m_structureID), X86::eax, X86::ecx); - m_jit.testl_i32m(MasqueradesAsUndefined, OBJECT_OFFSET(StructureID, m_typeInfo.m_flags), X86::ecx); - m_jit.setnz_r(X86::eax); - - X86Assembler::JmpSrc wasNotImmediate = m_jit.emitUnlinkedJmp(); - - m_jit.link(isImmediate, m_jit.label()); - - m_jit.movl_i32r(~JSImmediate::ExtendedTagBitUndefined, X86::ecx); - m_jit.andl_rr(X86::eax, X86::ecx); - m_jit.cmpl_i32r(JSImmediate::FullTagTypeNull, X86::ecx); - m_jit.sete_r(X86::eax); - - m_jit.link(wasNotImmediate, m_jit.label()); - - m_jit.movzbl_rr(X86::eax, X86::eax); - m_jit.cmpl_i32r(0, X86::eax); - m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJnz(), i + 2 + target)); - - i += 3; - break; - }; - case op_jneq_null: { - unsigned src = instruction[i + 1].u.operand; - unsigned target = instruction[i + 2].u.operand; - - emitGetArg(src, X86::eax); - m_jit.testl_i32r(JSImmediate::TagMask, X86::eax); - X86Assembler::JmpSrc isImmediate = m_jit.emitUnlinkedJnz(); - - m_jit.movl_mr(OBJECT_OFFSET(JSCell, m_structureID), X86::eax, X86::ecx); - m_jit.testl_i32m(MasqueradesAsUndefined, OBJECT_OFFSET(StructureID, m_typeInfo.m_flags), X86::ecx); - m_jit.setz_r(X86::eax); - - X86Assembler::JmpSrc wasNotImmediate = m_jit.emitUnlinkedJmp(); - - m_jit.link(isImmediate, m_jit.label()); - - m_jit.movl_i32r(~JSImmediate::ExtendedTagBitUndefined, X86::ecx); - m_jit.andl_rr(X86::eax, X86::ecx); - m_jit.cmpl_i32r(JSImmediate::FullTagTypeNull, X86::ecx); - m_jit.setne_r(X86::eax); - - m_jit.link(wasNotImmediate, m_jit.label()); - - m_jit.movzbl_rr(X86::eax, X86::eax); - m_jit.cmpl_i32r(0, X86::eax); - m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJnz(), i + 2 + target)); - - i += 3; - break; - } - case op_post_inc: { - int srcDst = instruction[i + 2].u.operand; - emitGetArg(srcDst, X86::eax); - m_jit.movl_rr(X86::eax, X86::edx); - emitJumpSlowCaseIfNotImmNum(X86::eax, i); - m_jit.addl_i8r(getDeTaggedConstantImmediate(JSImmediate::oneImmediate()), X86::edx); - m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJo(), i)); - emitPutResult(srcDst, X86::edx); - emitPutResult(instruction[i + 1].u.operand); - i += 3; - break; - } - case op_unexpected_load: { - JSValue* v = m_codeBlock->unexpectedConstants[instruction[i + 2].u.operand]; - m_jit.movl_i32r(asInteger(v), X86::eax); - emitPutResult(instruction[i + 1].u.operand); - i += 3; - break; - } - case op_jsr: { - int retAddrDst = instruction[i + 1].u.operand; - int target = instruction[i + 2].u.operand; - m_jit.movl_i32m(0, sizeof(Register) * retAddrDst, X86::edi); - X86Assembler::JmpDst addrPosition = m_jit.label(); - m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJmp(), i + 2 + target)); - X86Assembler::JmpDst sretTarget = m_jit.label(); - m_jsrSites.append(JSRInfo(addrPosition, sretTarget)); - i += 3; - break; - } - case op_sret: { - m_jit.jmp_m(sizeof(Register) * instruction[i + 1].u.operand, X86::edi); - i += 2; - break; - } - case op_eq: { - emitGetArg(instruction[i + 2].u.operand, X86::eax); - emitGetArg(instruction[i + 3].u.operand, X86::edx); - emitJumpSlowCaseIfNotImmNums(X86::eax, X86::edx, i); - m_jit.cmpl_rr(X86::edx, X86::eax); - m_jit.sete_r(X86::eax); - m_jit.movzbl_rr(X86::eax, X86::eax); - emitTagAsBoolImmediate(X86::eax); - emitPutResult(instruction[i + 1].u.operand); - i += 4; - break; - } - case op_lshift: { - emitGetArg(instruction[i + 2].u.operand, X86::eax); - emitGetArg(instruction[i + 3].u.operand, X86::ecx); - emitJumpSlowCaseIfNotImmNum(X86::eax, i); - emitJumpSlowCaseIfNotImmNum(X86::ecx, i); - emitFastArithImmToInt(X86::eax); - emitFastArithImmToInt(X86::ecx); - m_jit.shll_CLr(X86::eax); - emitFastArithIntToImmOrSlowCase(X86::eax, i); - emitPutResult(instruction[i + 1].u.operand); - i += 4; - break; - } - case op_bitand: { - unsigned src1 = instruction[i + 2].u.operand; - unsigned src2 = instruction[i + 3].u.operand; - unsigned dst = instruction[i + 1].u.operand; - if (JSValue* value = getConstantImmediateNumericArg(src1)) { - emitGetArg(src2, X86::eax); - emitJumpSlowCaseIfNotImmNum(X86::eax, i); - m_jit.andl_i32r(asInteger(value), X86::eax); // FIXME: make it more obvious this is relying on the format of JSImmediate - emitPutResult(dst); - } else if (JSValue* value = getConstantImmediateNumericArg(src2)) { - emitGetArg(src1, X86::eax); - emitJumpSlowCaseIfNotImmNum(X86::eax, i); - m_jit.andl_i32r(asInteger(value), X86::eax); - emitPutResult(dst); - } else { - emitGetArg(src1, X86::eax); - emitGetArg(src2, X86::edx); - m_jit.andl_rr(X86::edx, X86::eax); - emitJumpSlowCaseIfNotImmNum(X86::eax, i); - emitPutResult(dst); - } - i += 5; - break; - } - case op_rshift: { - emitGetArg(instruction[i + 2].u.operand, X86::eax); - emitGetArg(instruction[i + 3].u.operand, X86::ecx); - emitJumpSlowCaseIfNotImmNum(X86::eax, i); - emitJumpSlowCaseIfNotImmNum(X86::ecx, i); - emitFastArithImmToInt(X86::ecx); - m_jit.sarl_CLr(X86::eax); - emitFastArithPotentiallyReTagImmediate(X86::eax); - emitPutResult(instruction[i + 1].u.operand); - i += 4; - break; - } - case op_bitnot: { - emitGetArg(instruction[i + 2].u.operand, X86::eax); - emitJumpSlowCaseIfNotImmNum(X86::eax, i); - m_jit.xorl_i8r(~JSImmediate::TagBitTypeInteger, X86::eax); - emitPutResult(instruction[i + 1].u.operand); - i += 3; - break; - } - case op_resolve_with_base: { - Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 3].u.operand]); - emitPutArgConstant(reinterpret_cast<unsigned>(ident), 0); - emitCTICall(instruction + i, i, Machine::cti_op_resolve_with_base); - emitPutResult(instruction[i + 1].u.operand); - emitPutResult(instruction[i + 2].u.operand, X86::edx); - i += 4; - break; - } - case op_new_func_exp: { - FuncExprNode* func = (m_codeBlock->functionExpressions[instruction[i + 2].u.operand]).get(); - emitPutArgConstant(reinterpret_cast<unsigned>(func), 0); - emitCTICall(instruction + i, i, Machine::cti_op_new_func_exp); - emitPutResult(instruction[i + 1].u.operand); - i += 3; - break; - } - case op_mod: { - emitGetArg(instruction[i + 2].u.operand, X86::eax); - emitGetArg(instruction[i + 3].u.operand, X86::ecx); - emitJumpSlowCaseIfNotImmNum(X86::eax, i); - emitJumpSlowCaseIfNotImmNum(X86::ecx, i); - emitFastArithDeTagImmediate(X86::eax); - m_slowCases.append(SlowCaseEntry(emitFastArithDeTagImmediateJumpIfZero(X86::ecx), i)); - m_jit.cdq(); - m_jit.idivl_r(X86::ecx); - emitFastArithReTagImmediate(X86::edx); - m_jit.movl_rr(X86::edx, X86::eax); - emitPutResult(instruction[i + 1].u.operand); - i += 4; - break; - } - case op_jtrue: { - unsigned target = instruction[i + 2].u.operand; - emitGetArg(instruction[i + 1].u.operand, X86::eax); - - m_jit.cmpl_i32r(asInteger(JSImmediate::zeroImmediate()), X86::eax); - X86Assembler::JmpSrc isZero = m_jit.emitUnlinkedJe(); - m_jit.testl_i32r(JSImmediate::TagBitTypeInteger, X86::eax); - m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJne(), i + 2 + target)); - - m_jit.cmpl_i32r(asInteger(JSImmediate::trueImmediate()), X86::eax); - m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJe(), i + 2 + target)); - m_jit.cmpl_i32r(asInteger(JSImmediate::falseImmediate()), X86::eax); - m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJne(), i)); - - m_jit.link(isZero, m_jit.label()); - i += 3; - break; - } - CTI_COMPILE_BINARY_OP(op_less) - case op_neq: { - emitGetArg(instruction[i + 2].u.operand, X86::eax); - emitGetArg(instruction[i + 3].u.operand, X86::edx); - emitJumpSlowCaseIfNotImmNums(X86::eax, X86::edx, i); - m_jit.cmpl_rr(X86::eax, X86::edx); - - m_jit.setne_r(X86::eax); - m_jit.movzbl_rr(X86::eax, X86::eax); - emitTagAsBoolImmediate(X86::eax); - - emitPutResult(instruction[i + 1].u.operand); - - i += 4; - break; - } - case op_post_dec: { - int srcDst = instruction[i + 2].u.operand; - emitGetArg(srcDst, X86::eax); - m_jit.movl_rr(X86::eax, X86::edx); - emitJumpSlowCaseIfNotImmNum(X86::eax, i); - m_jit.subl_i8r(getDeTaggedConstantImmediate(JSImmediate::oneImmediate()), X86::edx); - m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJo(), i)); - emitPutResult(srcDst, X86::edx); - emitPutResult(instruction[i + 1].u.operand); - i += 3; - break; - } - CTI_COMPILE_BINARY_OP(op_urshift) - case op_bitxor: { - emitGetArg(instruction[i + 2].u.operand, X86::eax); - emitGetArg(instruction[i + 3].u.operand, X86::edx); - emitJumpSlowCaseIfNotImmNums(X86::eax, X86::edx, i); - m_jit.xorl_rr(X86::edx, X86::eax); - emitFastArithReTagImmediate(X86::eax); - emitPutResult(instruction[i + 1].u.operand); - i += 5; - break; - } - case op_new_regexp: { - RegExp* regExp = m_codeBlock->regexps[instruction[i + 2].u.operand].get(); - emitPutArgConstant(reinterpret_cast<unsigned>(regExp), 0); - emitCTICall(instruction + i, i, Machine::cti_op_new_regexp); - emitPutResult(instruction[i + 1].u.operand); - i += 3; - break; - } - case op_bitor: { - emitGetArg(instruction[i + 2].u.operand, X86::eax); - emitGetArg(instruction[i + 3].u.operand, X86::edx); - emitJumpSlowCaseIfNotImmNums(X86::eax, X86::edx, i); - m_jit.orl_rr(X86::edx, X86::eax); - emitPutResult(instruction[i + 1].u.operand); - i += 5; - break; - } - case op_call_eval: { - compileOpCall(opcodeID, instruction + i, i, callLinkInfoIndex++); - i += 7; - break; - } - case op_throw: { - emitGetPutArg(instruction[i + 1].u.operand, 0, X86::ecx); - emitCTICall(instruction + i, i, Machine::cti_op_throw); - m_jit.addl_i8r(0x20, X86::esp); - m_jit.popl_r(X86::ebx); - m_jit.popl_r(X86::edi); - m_jit.popl_r(X86::esi); - m_jit.ret(); - i += 2; - break; - } - case op_get_pnames: { - emitGetPutArg(instruction[i + 2].u.operand, 0, X86::ecx); - emitCTICall(instruction + i, i, Machine::cti_op_get_pnames); - emitPutResult(instruction[i + 1].u.operand); - i += 3; - break; - } - case op_next_pname: { - emitGetPutArg(instruction[i + 2].u.operand, 0, X86::ecx); - unsigned target = instruction[i + 3].u.operand; - emitCTICall(instruction + i, i, Machine::cti_op_next_pname); - m_jit.testl_rr(X86::eax, X86::eax); - X86Assembler::JmpSrc endOfIter = m_jit.emitUnlinkedJe(); - emitPutResult(instruction[i + 1].u.operand); - m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJmp(), i + 3 + target)); - m_jit.link(endOfIter, m_jit.label()); - i += 4; - break; - } - case op_push_scope: { - emitGetPutArg(instruction[i + 1].u.operand, 0, X86::ecx); - emitCTICall(instruction + i, i, Machine::cti_op_push_scope); - i += 2; - break; - } - case op_pop_scope: { - emitCTICall(instruction + i, i, Machine::cti_op_pop_scope); - i += 1; - break; - } - CTI_COMPILE_UNARY_OP(op_typeof) - CTI_COMPILE_UNARY_OP(op_is_undefined) - CTI_COMPILE_UNARY_OP(op_is_boolean) - CTI_COMPILE_UNARY_OP(op_is_number) - CTI_COMPILE_UNARY_OP(op_is_string) - CTI_COMPILE_UNARY_OP(op_is_object) - CTI_COMPILE_UNARY_OP(op_is_function) - case op_stricteq: { - compileOpStrictEq(instruction + i, i, OpStrictEq); - i += 4; - break; - } - case op_nstricteq: { - compileOpStrictEq(instruction + i, i, OpNStrictEq); - i += 4; - break; - } - case op_to_jsnumber: { - emitGetArg(instruction[i + 2].u.operand, X86::eax); - - m_jit.testl_i32r(JSImmediate::TagBitTypeInteger, X86::eax); - X86Assembler::JmpSrc wasImmediate = m_jit.emitUnlinkedJnz(); - - emitJumpSlowCaseIfNotJSCell(X86::eax, i); - - m_jit.movl_mr(OBJECT_OFFSET(JSCell, m_structureID), X86::eax, X86::ecx); - m_jit.cmpl_i32m(NumberType, OBJECT_OFFSET(StructureID, m_typeInfo.m_type), X86::ecx); - - m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJne(), i)); - - m_jit.link(wasImmediate, m_jit.label()); - - emitPutResult(instruction[i + 1].u.operand); - i += 3; - break; - } - case op_in: { - emitGetPutArg(instruction[i + 2].u.operand, 0, X86::ecx); - emitGetPutArg(instruction[i + 3].u.operand, 4, X86::ecx); - emitCTICall(instruction + i, i, Machine::cti_op_in); - emitPutResult(instruction[i + 1].u.operand); - i += 4; - break; - } - case op_push_new_scope: { - Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 2].u.operand]); - emitPutArgConstant(reinterpret_cast<unsigned>(ident), 0); - emitGetPutArg(instruction[i + 3].u.operand, 4, X86::ecx); - emitCTICall(instruction + i, i, Machine::cti_op_push_new_scope); - emitPutResult(instruction[i + 1].u.operand); - i += 4; - break; - } - case op_catch: { - emitGetCTIParam(CTI_ARGS_callFrame, X86::edi); // edi := r - emitPutResult(instruction[i + 1].u.operand); - i += 2; - break; - } - case op_jmp_scopes: { - unsigned count = instruction[i + 1].u.operand; - emitPutArgConstant(count, 0); - emitCTICall(instruction + i, i, Machine::cti_op_jmp_scopes); - unsigned target = instruction[i + 2].u.operand; - m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJmp(), i + 2 + target)); - i += 3; - break; - } - case op_put_by_index: { - emitGetPutArg(instruction[i + 1].u.operand, 0, X86::ecx); - emitPutArgConstant(instruction[i + 2].u.operand, 4); - emitGetPutArg(instruction[i + 3].u.operand, 8, X86::ecx); - emitCTICall(instruction + i, i, Machine::cti_op_put_by_index); - i += 4; - break; - } - case op_switch_imm: { - unsigned tableIndex = instruction[i + 1].u.operand; - unsigned defaultOffset = instruction[i + 2].u.operand; - unsigned scrutinee = instruction[i + 3].u.operand; - - // create jump table for switch destinations, track this switch statement. - SimpleJumpTable* jumpTable = &m_codeBlock->immediateSwitchJumpTables[tableIndex]; - m_switches.append(SwitchRecord(jumpTable, i, defaultOffset, SwitchRecord::Immediate)); - jumpTable->ctiOffsets.grow(jumpTable->branchOffsets.size()); - - emitGetPutArg(scrutinee, 0, X86::ecx); - emitPutArgConstant(tableIndex, 4); - emitCTICall(instruction + i, i, Machine::cti_op_switch_imm); - m_jit.jmp_r(X86::eax); - i += 4; - break; - } - case op_switch_char: { - unsigned tableIndex = instruction[i + 1].u.operand; - unsigned defaultOffset = instruction[i + 2].u.operand; - unsigned scrutinee = instruction[i + 3].u.operand; - - // create jump table for switch destinations, track this switch statement. - SimpleJumpTable* jumpTable = &m_codeBlock->characterSwitchJumpTables[tableIndex]; - m_switches.append(SwitchRecord(jumpTable, i, defaultOffset, SwitchRecord::Character)); - jumpTable->ctiOffsets.grow(jumpTable->branchOffsets.size()); - - emitGetPutArg(scrutinee, 0, X86::ecx); - emitPutArgConstant(tableIndex, 4); - emitCTICall(instruction + i, i, Machine::cti_op_switch_char); - m_jit.jmp_r(X86::eax); - i += 4; - break; - } - case op_switch_string: { - unsigned tableIndex = instruction[i + 1].u.operand; - unsigned defaultOffset = instruction[i + 2].u.operand; - unsigned scrutinee = instruction[i + 3].u.operand; - - // create jump table for switch destinations, track this switch statement. - StringJumpTable* jumpTable = &m_codeBlock->stringSwitchJumpTables[tableIndex]; - m_switches.append(SwitchRecord(jumpTable, i, defaultOffset)); - - emitGetPutArg(scrutinee, 0, X86::ecx); - emitPutArgConstant(tableIndex, 4); - emitCTICall(instruction + i, i, Machine::cti_op_switch_string); - m_jit.jmp_r(X86::eax); - i += 4; - break; - } - case op_del_by_val: { - emitGetPutArg(instruction[i + 2].u.operand, 0, X86::ecx); - emitGetPutArg(instruction[i + 3].u.operand, 4, X86::ecx); - emitCTICall(instruction + i, i, Machine::cti_op_del_by_val); - emitPutResult(instruction[i + 1].u.operand); - i += 4; - break; - } - case op_put_getter: { - emitGetPutArg(instruction[i + 1].u.operand, 0, X86::ecx); - Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 2].u.operand]); - emitPutArgConstant(reinterpret_cast<unsigned>(ident), 4); - emitGetPutArg(instruction[i + 3].u.operand, 8, X86::ecx); - emitCTICall(instruction + i, i, Machine::cti_op_put_getter); - i += 4; - break; - } - case op_put_setter: { - emitGetPutArg(instruction[i + 1].u.operand, 0, X86::ecx); - Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 2].u.operand]); - emitPutArgConstant(reinterpret_cast<unsigned>(ident), 4); - emitGetPutArg(instruction[i + 3].u.operand, 8, X86::ecx); - emitCTICall(instruction + i, i, Machine::cti_op_put_setter); - i += 4; - break; - } - case op_new_error: { - JSValue* message = m_codeBlock->unexpectedConstants[instruction[i + 3].u.operand]; - emitPutArgConstant(instruction[i + 2].u.operand, 0); - emitPutArgConstant(asInteger(message), 4); - emitPutArgConstant(m_codeBlock->lineNumberForVPC(&instruction[i]), 8); - emitCTICall(instruction + i, i, Machine::cti_op_new_error); - emitPutResult(instruction[i + 1].u.operand); - i += 4; - break; - } - case op_debug: { - emitPutArgConstant(instruction[i + 1].u.operand, 0); - emitPutArgConstant(instruction[i + 2].u.operand, 4); - emitPutArgConstant(instruction[i + 3].u.operand, 8); - emitCTICall(instruction + i, i, Machine::cti_op_debug); - i += 4; - break; - } - case op_eq_null: { - unsigned dst = instruction[i + 1].u.operand; - unsigned src1 = instruction[i + 2].u.operand; - - emitGetArg(src1, X86::eax); - m_jit.testl_i32r(JSImmediate::TagMask, X86::eax); - X86Assembler::JmpSrc isImmediate = m_jit.emitUnlinkedJnz(); - - m_jit.movl_mr(OBJECT_OFFSET(JSCell, m_structureID), X86::eax, X86::ecx); - m_jit.testl_i32m(MasqueradesAsUndefined, OBJECT_OFFSET(StructureID, m_typeInfo.m_flags), X86::ecx); - m_jit.setnz_r(X86::eax); - - X86Assembler::JmpSrc wasNotImmediate = m_jit.emitUnlinkedJmp(); - - m_jit.link(isImmediate, m_jit.label()); - - m_jit.movl_i32r(~JSImmediate::ExtendedTagBitUndefined, X86::ecx); - m_jit.andl_rr(X86::eax, X86::ecx); - m_jit.cmpl_i32r(JSImmediate::FullTagTypeNull, X86::ecx); - m_jit.sete_r(X86::eax); - - m_jit.link(wasNotImmediate, m_jit.label()); - - m_jit.movzbl_rr(X86::eax, X86::eax); - emitTagAsBoolImmediate(X86::eax); - emitPutResult(dst); - - i += 3; - break; - } - case op_neq_null: { - unsigned dst = instruction[i + 1].u.operand; - unsigned src1 = instruction[i + 2].u.operand; - - emitGetArg(src1, X86::eax); - m_jit.testl_i32r(JSImmediate::TagMask, X86::eax); - X86Assembler::JmpSrc isImmediate = m_jit.emitUnlinkedJnz(); - - m_jit.movl_mr(OBJECT_OFFSET(JSCell, m_structureID), X86::eax, X86::ecx); - m_jit.testl_i32m(MasqueradesAsUndefined, OBJECT_OFFSET(StructureID, m_typeInfo.m_flags), X86::ecx); - m_jit.setz_r(X86::eax); - - X86Assembler::JmpSrc wasNotImmediate = m_jit.emitUnlinkedJmp(); - - m_jit.link(isImmediate, m_jit.label()); - - m_jit.movl_i32r(~JSImmediate::ExtendedTagBitUndefined, X86::ecx); - m_jit.andl_rr(X86::eax, X86::ecx); - m_jit.cmpl_i32r(JSImmediate::FullTagTypeNull, X86::ecx); - m_jit.setne_r(X86::eax); - - m_jit.link(wasNotImmediate, m_jit.label()); - - m_jit.movzbl_rr(X86::eax, X86::eax); - emitTagAsBoolImmediate(X86::eax); - emitPutResult(dst); - - i += 3; - break; - } - case op_enter: { - // Even though CTI doesn't use them, we initialize our constant - // registers to zap stale pointers, to avoid unnecessarily prolonging - // object lifetime and increasing GC pressure. - size_t count = m_codeBlock->numVars + m_codeBlock->constantRegisters.size(); - for (size_t j = 0; j < count; ++j) - emitInitRegister(j); - - i+= 1; - break; - } - case op_enter_with_activation: { - // Even though CTI doesn't use them, we initialize our constant - // registers to zap stale pointers, to avoid unnecessarily prolonging - // object lifetime and increasing GC pressure. - size_t count = m_codeBlock->numVars + m_codeBlock->constantRegisters.size(); - for (size_t j = 0; j < count; ++j) - emitInitRegister(j); - - emitCTICall(instruction + i, i, Machine::cti_op_push_activation); - emitPutResult(instruction[i + 1].u.operand); - - i+= 2; - break; - } - case op_create_arguments: { - emitCTICall(instruction + i, i, (m_codeBlock->numParameters == 1) ? Machine::cti_op_create_arguments_no_params : Machine::cti_op_create_arguments); - i += 1; - break; - } - case op_convert_this: { - emitGetArg(instruction[i + 1].u.operand, X86::eax); - - emitJumpSlowCaseIfNotJSCell(X86::eax, i); - m_jit.movl_mr(OBJECT_OFFSET(JSCell, m_structureID), X86::eax, X86::edx); - m_jit.testl_i32m(NeedsThisConversion, OBJECT_OFFSET(StructureID, m_typeInfo.m_flags), X86::edx); - m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJnz(), i)); - - i += 2; - break; - } - case op_profile_will_call: { - emitGetCTIParam(CTI_ARGS_profilerReference, X86::eax); - m_jit.cmpl_i32m(0, X86::eax); - X86Assembler::JmpSrc noProfiler = m_jit.emitUnlinkedJe(); - emitGetPutArg(instruction[i + 1].u.operand, 0, X86::eax); - emitCTICall(instruction + i, i, Machine::cti_op_profile_will_call); - m_jit.link(noProfiler, m_jit.label()); - - i += 2; - break; - } - case op_profile_did_call: { - emitGetCTIParam(CTI_ARGS_profilerReference, X86::eax); - m_jit.cmpl_i32m(0, X86::eax); - X86Assembler::JmpSrc noProfiler = m_jit.emitUnlinkedJe(); - emitGetPutArg(instruction[i + 1].u.operand, 0, X86::eax); - emitCTICall(instruction + i, i, Machine::cti_op_profile_did_call); - m_jit.link(noProfiler, m_jit.label()); - - i += 2; - break; - } - case op_get_array_length: - case op_get_by_id_chain: - case op_get_by_id_generic: - case op_get_by_id_proto: - case op_get_by_id_self: - case op_get_string_length: - case op_put_by_id_generic: - case op_put_by_id_replace: - case op_put_by_id_transition: - ASSERT_NOT_REACHED(); - } - } - - ASSERT(propertyAccessInstructionIndex == m_codeBlock->propertyAccessInstructions.size()); - ASSERT(callLinkInfoIndex == m_codeBlock->callLinkInfos.size()); -} - - -void CTI::privateCompileLinkPass() -{ - unsigned jmpTableCount = m_jmpTable.size(); - for (unsigned i = 0; i < jmpTableCount; ++i) - m_jit.link(m_jmpTable[i].from, m_labels[m_jmpTable[i].to]); - m_jmpTable.clear(); -} - -#define CTI_COMPILE_BINARY_OP_SLOW_CASE(name) \ - case name: { \ - m_jit.link(iter->from, m_jit.label()); \ - emitGetPutArg(instruction[i + 2].u.operand, 0, X86::ecx); \ - emitGetPutArg(instruction[i + 3].u.operand, 4, X86::ecx); \ - emitCTICall(instruction + i, i, Machine::cti_##name); \ - emitPutResult(instruction[i + 1].u.operand); \ - i += 4; \ - break; \ - } - -void CTI::privateCompileSlowCases() -{ - unsigned propertyAccessInstructionIndex = 0; - unsigned callLinkInfoIndex = 0; - - Instruction* instruction = m_codeBlock->instructions.begin(); - for (Vector<SlowCaseEntry>::iterator iter = m_slowCases.begin(); iter != m_slowCases.end(); ++iter) { - unsigned i = iter->to; - switch (OpcodeID opcodeID = m_machine->getOpcodeID(instruction[i].u.opcode)) { - case op_convert_this: { - m_jit.link(iter->from, m_jit.label()); - m_jit.link((++iter)->from, m_jit.label()); - emitPutArg(X86::eax, 0); - emitCTICall(instruction + i, i, Machine::cti_op_convert_this); - emitPutResult(instruction[i + 1].u.operand); - i += 2; - break; - } - case op_add: { - unsigned dst = instruction[i + 1].u.operand; - unsigned src1 = instruction[i + 2].u.operand; - unsigned src2 = instruction[i + 3].u.operand; - if (JSValue* value = getConstantImmediateNumericArg(src1)) { - X86Assembler::JmpSrc notImm = iter->from; - m_jit.link((++iter)->from, m_jit.label()); - m_jit.subl_i32r(getDeTaggedConstantImmediate(value), X86::edx); - m_jit.link(notImm, m_jit.label()); - emitGetPutArg(src1, 0, X86::ecx); - emitPutArg(X86::edx, 4); - emitCTICall(instruction + i, i, Machine::cti_op_add); - emitPutResult(dst); - } else if (JSValue* value = getConstantImmediateNumericArg(src2)) { - X86Assembler::JmpSrc notImm = iter->from; - m_jit.link((++iter)->from, m_jit.label()); - m_jit.subl_i32r(getDeTaggedConstantImmediate(value), X86::eax); - m_jit.link(notImm, m_jit.label()); - emitPutArg(X86::eax, 0); - emitGetPutArg(src2, 4, X86::ecx); - emitCTICall(instruction + i, i, Machine::cti_op_add); - emitPutResult(dst); - } else { - OperandTypes types = OperandTypes::fromInt(instruction[i + 4].u.operand); - if (types.first().mightBeNumber() && types.second().mightBeNumber()) - compileBinaryArithOpSlowCase(instruction + i, op_add, iter, dst, src1, src2, types, i); - else - ASSERT_NOT_REACHED(); - } - - i += 5; - break; - } - case op_get_by_val: { - // The slow case that handles accesses to arrays (below) may jump back up to here. - X86Assembler::JmpDst beginGetByValSlow = m_jit.label(); - - X86Assembler::JmpSrc notImm = iter->from; - m_jit.link((++iter)->from, m_jit.label()); - m_jit.link((++iter)->from, m_jit.label()); - emitFastArithIntToImmNoCheck(X86::edx); - m_jit.link(notImm, m_jit.label()); - emitPutArg(X86::eax, 0); - emitPutArg(X86::edx, 4); - emitCTICall(instruction + i, i, Machine::cti_op_get_by_val); - emitPutResult(instruction[i + 1].u.operand); - m_jit.link(m_jit.emitUnlinkedJmp(), m_labels[i + 4]); - - // This is slow case that handles accesses to arrays above the fast cut-off. - // First, check if this is an access to the vector - m_jit.link((++iter)->from, m_jit.label()); - m_jit.cmpl_rm(X86::edx, OBJECT_OFFSET(ArrayStorage, m_vectorLength), X86::ecx); - m_jit.link(m_jit.emitUnlinkedJbe(), beginGetByValSlow); - - // okay, missed the fast region, but it is still in the vector. Get the value. - m_jit.movl_mr(OBJECT_OFFSET(ArrayStorage, m_vector[0]), X86::ecx, X86::edx, sizeof(JSValue*), X86::ecx); - // Check whether the value loaded is zero; if so we need to return undefined. - m_jit.testl_rr(X86::ecx, X86::ecx); - m_jit.link(m_jit.emitUnlinkedJe(), beginGetByValSlow); - emitPutResult(instruction[i + 1].u.operand, X86::ecx); - - i += 4; - break; - } - case op_sub: { - compileBinaryArithOpSlowCase(instruction + i, op_sub, iter, instruction[i + 1].u.operand, instruction[i + 2].u.operand, instruction[i + 3].u.operand, OperandTypes::fromInt(instruction[i + 4].u.operand), i); - i += 5; - break; - } - case op_negate: { - m_jit.link(iter->from, m_jit.label()); - emitGetPutArg(instruction[i + 2].u.operand, 0, X86::ecx); - emitCTICall(instruction + i, i, Machine::cti_op_negate); - emitPutResult(instruction[i + 1].u.operand); - i += 4; - break; - } - case op_rshift: { - m_jit.link(iter->from, m_jit.label()); - m_jit.link((++iter)->from, m_jit.label()); - emitPutArg(X86::eax, 0); - emitPutArg(X86::ecx, 4); - emitCTICall(instruction + i, i, Machine::cti_op_rshift); - emitPutResult(instruction[i + 1].u.operand); - i += 4; - break; - } - case op_lshift: { - X86Assembler::JmpSrc notImm1 = iter->from; - X86Assembler::JmpSrc notImm2 = (++iter)->from; - m_jit.link((++iter)->from, m_jit.label()); - emitGetArg(instruction[i + 2].u.operand, X86::eax); - emitGetArg(instruction[i + 3].u.operand, X86::ecx); - m_jit.link(notImm1, m_jit.label()); - m_jit.link(notImm2, m_jit.label()); - emitPutArg(X86::eax, 0); - emitPutArg(X86::ecx, 4); - emitCTICall(instruction + i, i, Machine::cti_op_lshift); - emitPutResult(instruction[i + 1].u.operand); - i += 4; - break; - } - case op_loop_if_less: { - emitSlowScriptCheck(instruction + i, i); - - unsigned target = instruction[i + 3].u.operand; - JSValue* src2imm = getConstantImmediateNumericArg(instruction[i + 2].u.operand); - if (src2imm) { - m_jit.link(iter->from, m_jit.label()); - emitPutArg(X86::edx, 0); - emitGetPutArg(instruction[i + 2].u.operand, 4, X86::ecx); - emitCTICall(instruction + i, i, Machine::cti_op_loop_if_less); - m_jit.testl_rr(X86::eax, X86::eax); - m_jit.link(m_jit.emitUnlinkedJne(), m_labels[i + 3 + target]); - } else { - m_jit.link(iter->from, m_jit.label()); - m_jit.link((++iter)->from, m_jit.label()); - emitPutArg(X86::eax, 0); - emitPutArg(X86::edx, 4); - emitCTICall(instruction + i, i, Machine::cti_op_loop_if_less); - m_jit.testl_rr(X86::eax, X86::eax); - m_jit.link(m_jit.emitUnlinkedJne(), m_labels[i + 3 + target]); - } - i += 4; - break; - } - case op_put_by_id: { - m_jit.link(iter->from, m_jit.label()); - m_jit.link((++iter)->from, m_jit.label()); - - Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 2].u.operand]); - emitPutArgConstant(reinterpret_cast<unsigned>(ident), 4); - emitPutArg(X86::eax, 0); - emitPutArg(X86::edx, 8); - X86Assembler::JmpSrc call = emitCTICall(instruction + i, i, Machine::cti_op_put_by_id); - - // Track the location of the call; this will be used to recover repatch information. - ASSERT(m_codeBlock->propertyAccessInstructions[propertyAccessInstructionIndex].opcodeIndex == i); - m_propertyAccessCompilationInfo[propertyAccessInstructionIndex].callReturnLocation = call; - ++propertyAccessInstructionIndex; - - i += 8; - break; - } - case op_get_by_id: { - // As for the hot path of get_by_id, above, we ensure that we can use an architecture specific offset - // so that we only need track one pointer into the slow case code - we track a pointer to the location - // of the call (which we can use to look up the repatch information), but should a array-length or - // prototype access trampoline fail we want to bail out back to here. To do so we can subtract back - // the distance from the call to the head of the slow case. - - m_jit.link(iter->from, m_jit.label()); - m_jit.link((++iter)->from, m_jit.label()); - -#ifndef NDEBUG - X86Assembler::JmpDst coldPathBegin = m_jit.label(); -#endif - emitPutArg(X86::eax, 0); - Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 3].u.operand]); - emitPutArgConstant(reinterpret_cast<unsigned>(ident), 4); - X86Assembler::JmpSrc call = emitCTICall(instruction + i, i, Machine::cti_op_get_by_id); - ASSERT(X86Assembler::getDifferenceBetweenLabels(coldPathBegin, call) == repatchOffsetGetByIdSlowCaseCall); - emitPutResult(instruction[i + 1].u.operand); - - // Track the location of the call; this will be used to recover repatch information. - ASSERT(m_codeBlock->propertyAccessInstructions[propertyAccessInstructionIndex].opcodeIndex == i); - m_propertyAccessCompilationInfo[propertyAccessInstructionIndex].callReturnLocation = call; - ++propertyAccessInstructionIndex; - - i += 8; - break; - } - case op_loop_if_lesseq: { - emitSlowScriptCheck(instruction + i, i); - - unsigned target = instruction[i + 3].u.operand; - JSValue* src2imm = getConstantImmediateNumericArg(instruction[i + 2].u.operand); - if (src2imm) { - m_jit.link(iter->from, m_jit.label()); - emitPutArg(X86::edx, 0); - emitGetPutArg(instruction[i + 2].u.operand, 4, X86::ecx); - emitCTICall(instruction + i, i, Machine::cti_op_loop_if_lesseq); - m_jit.testl_rr(X86::eax, X86::eax); - m_jit.link(m_jit.emitUnlinkedJne(), m_labels[i + 3 + target]); - } else { - m_jit.link(iter->from, m_jit.label()); - m_jit.link((++iter)->from, m_jit.label()); - emitPutArg(X86::eax, 0); - emitPutArg(X86::edx, 4); - emitCTICall(instruction + i, i, Machine::cti_op_loop_if_lesseq); - m_jit.testl_rr(X86::eax, X86::eax); - m_jit.link(m_jit.emitUnlinkedJne(), m_labels[i + 3 + target]); - } - i += 4; - break; - } - case op_pre_inc: { - unsigned srcDst = instruction[i + 1].u.operand; - X86Assembler::JmpSrc notImm = iter->from; - m_jit.link((++iter)->from, m_jit.label()); - m_jit.subl_i8r(getDeTaggedConstantImmediate(JSImmediate::oneImmediate()), X86::eax); - m_jit.link(notImm, m_jit.label()); - emitPutArg(X86::eax, 0); - emitCTICall(instruction + i, i, Machine::cti_op_pre_inc); - emitPutResult(srcDst); - i += 2; - break; - } - case op_put_by_val: { - // Normal slow cases - either is not an immediate imm, or is an array. - X86Assembler::JmpSrc notImm = iter->from; - m_jit.link((++iter)->from, m_jit.label()); - m_jit.link((++iter)->from, m_jit.label()); - emitFastArithIntToImmNoCheck(X86::edx); - m_jit.link(notImm, m_jit.label()); - emitGetArg(instruction[i + 3].u.operand, X86::ecx); - emitPutArg(X86::eax, 0); - emitPutArg(X86::edx, 4); - emitPutArg(X86::ecx, 8); - emitCTICall(instruction + i, i, Machine::cti_op_put_by_val); - m_jit.link(m_jit.emitUnlinkedJmp(), m_labels[i + 4]); - - // slow cases for immediate int accesses to arrays - m_jit.link((++iter)->from, m_jit.label()); - m_jit.link((++iter)->from, m_jit.label()); - emitGetArg(instruction[i + 3].u.operand, X86::ecx); - emitPutArg(X86::eax, 0); - emitPutArg(X86::edx, 4); - emitPutArg(X86::ecx, 8); - emitCTICall(instruction + i, i, Machine::cti_op_put_by_val_array); - - i += 4; - break; - } - case op_loop_if_true: { - emitSlowScriptCheck(instruction + i, i); - - m_jit.link(iter->from, m_jit.label()); - emitPutArg(X86::eax, 0); - emitCTICall(instruction + i, i, Machine::cti_op_jtrue); - m_jit.testl_rr(X86::eax, X86::eax); - unsigned target = instruction[i + 2].u.operand; - m_jit.link(m_jit.emitUnlinkedJne(), m_labels[i + 2 + target]); - i += 3; - break; - } - case op_pre_dec: { - unsigned srcDst = instruction[i + 1].u.operand; - X86Assembler::JmpSrc notImm = iter->from; - m_jit.link((++iter)->from, m_jit.label()); - m_jit.addl_i8r(getDeTaggedConstantImmediate(JSImmediate::oneImmediate()), X86::eax); - m_jit.link(notImm, m_jit.label()); - emitPutArg(X86::eax, 0); - emitCTICall(instruction + i, i, Machine::cti_op_pre_dec); - emitPutResult(srcDst); - i += 2; - break; - } - case op_jnless: { - unsigned target = instruction[i + 3].u.operand; - JSValue* src2imm = getConstantImmediateNumericArg(instruction[i + 2].u.operand); - if (src2imm) { - m_jit.link(iter->from, m_jit.label()); - emitPutArg(X86::edx, 0); - emitGetPutArg(instruction[i + 2].u.operand, 4, X86::ecx); - emitCTICall(instruction + i, i, Machine::cti_op_jless); - m_jit.testl_rr(X86::eax, X86::eax); - m_jit.link(m_jit.emitUnlinkedJe(), m_labels[i + 3 + target]); - } else { - m_jit.link(iter->from, m_jit.label()); - m_jit.link((++iter)->from, m_jit.label()); - emitPutArg(X86::eax, 0); - emitPutArg(X86::edx, 4); - emitCTICall(instruction + i, i, Machine::cti_op_jless); - m_jit.testl_rr(X86::eax, X86::eax); - m_jit.link(m_jit.emitUnlinkedJe(), m_labels[i + 3 + target]); - } - i += 4; - break; - } - case op_not: { - m_jit.link(iter->from, m_jit.label()); - m_jit.xorl_i8r(JSImmediate::FullTagTypeBool, X86::eax); - emitPutArg(X86::eax, 0); - emitCTICall(instruction + i, i, Machine::cti_op_not); - emitPutResult(instruction[i + 1].u.operand); - i += 3; - break; - } - case op_jfalse: { - m_jit.link(iter->from, m_jit.label()); - emitPutArg(X86::eax, 0); - emitCTICall(instruction + i, i, Machine::cti_op_jtrue); - m_jit.testl_rr(X86::eax, X86::eax); - unsigned target = instruction[i + 2].u.operand; - m_jit.link(m_jit.emitUnlinkedJe(), m_labels[i + 2 + target]); // inverted! - i += 3; - break; - } - case op_post_inc: { - unsigned srcDst = instruction[i + 2].u.operand; - m_jit.link(iter->from, m_jit.label()); - m_jit.link((++iter)->from, m_jit.label()); - emitPutArg(X86::eax, 0); - emitCTICall(instruction + i, i, Machine::cti_op_post_inc); - emitPutResult(instruction[i + 1].u.operand); - emitPutResult(srcDst, X86::edx); - i += 3; - break; - } - case op_bitnot: { - m_jit.link(iter->from, m_jit.label()); - emitPutArg(X86::eax, 0); - emitCTICall(instruction + i, i, Machine::cti_op_bitnot); - emitPutResult(instruction[i + 1].u.operand); - i += 3; - break; - } - case op_bitand: { - unsigned src1 = instruction[i + 2].u.operand; - unsigned src2 = instruction[i + 3].u.operand; - unsigned dst = instruction[i + 1].u.operand; - if (getConstantImmediateNumericArg(src1)) { - m_jit.link(iter->from, m_jit.label()); - emitGetPutArg(src1, 0, X86::ecx); - emitPutArg(X86::eax, 4); - emitCTICall(instruction + i, i, Machine::cti_op_bitand); - emitPutResult(dst); - } else if (getConstantImmediateNumericArg(src2)) { - m_jit.link(iter->from, m_jit.label()); - emitPutArg(X86::eax, 0); - emitGetPutArg(src2, 4, X86::ecx); - emitCTICall(instruction + i, i, Machine::cti_op_bitand); - emitPutResult(dst); - } else { - m_jit.link(iter->from, m_jit.label()); - emitGetPutArg(src1, 0, X86::ecx); - emitPutArg(X86::edx, 4); - emitCTICall(instruction + i, i, Machine::cti_op_bitand); - emitPutResult(dst); - } - i += 5; - break; - } - case op_jtrue: { - m_jit.link(iter->from, m_jit.label()); - emitPutArg(X86::eax, 0); - emitCTICall(instruction + i, i, Machine::cti_op_jtrue); - m_jit.testl_rr(X86::eax, X86::eax); - unsigned target = instruction[i + 2].u.operand; - m_jit.link(m_jit.emitUnlinkedJne(), m_labels[i + 2 + target]); - i += 3; - break; - } - case op_post_dec: { - unsigned srcDst = instruction[i + 2].u.operand; - m_jit.link(iter->from, m_jit.label()); - m_jit.link((++iter)->from, m_jit.label()); - emitPutArg(X86::eax, 0); - emitCTICall(instruction + i, i, Machine::cti_op_post_dec); - emitPutResult(instruction[i + 1].u.operand); - emitPutResult(srcDst, X86::edx); - i += 3; - break; - } - case op_bitxor: { - m_jit.link(iter->from, m_jit.label()); - emitPutArg(X86::eax, 0); - emitPutArg(X86::edx, 4); - emitCTICall(instruction + i, i, Machine::cti_op_bitxor); - emitPutResult(instruction[i + 1].u.operand); - i += 5; - break; - } - case op_bitor: { - m_jit.link(iter->from, m_jit.label()); - emitPutArg(X86::eax, 0); - emitPutArg(X86::edx, 4); - emitCTICall(instruction + i, i, Machine::cti_op_bitor); - emitPutResult(instruction[i + 1].u.operand); - i += 5; - break; - } - case op_eq: { - m_jit.link(iter->from, m_jit.label()); - emitPutArg(X86::eax, 0); - emitPutArg(X86::edx, 4); - emitCTICall(instruction + i, i, Machine::cti_op_eq); - emitPutResult(instruction[i + 1].u.operand); - i += 4; - break; - } - case op_neq: { - m_jit.link(iter->from, m_jit.label()); - emitPutArg(X86::eax, 0); - emitPutArg(X86::edx, 4); - emitCTICall(instruction + i, i, Machine::cti_op_neq); - emitPutResult(instruction[i + 1].u.operand); - i += 4; - break; - } - CTI_COMPILE_BINARY_OP_SLOW_CASE(op_stricteq); - CTI_COMPILE_BINARY_OP_SLOW_CASE(op_nstricteq); - case op_instanceof: { - m_jit.link(iter->from, m_jit.label()); - emitGetPutArg(instruction[i + 2].u.operand, 0, X86::ecx); - emitGetPutArg(instruction[i + 3].u.operand, 4, X86::ecx); - emitGetPutArg(instruction[i + 4].u.operand, 8, X86::ecx); - emitCTICall(instruction + i, i, Machine::cti_op_instanceof); - emitPutResult(instruction[i + 1].u.operand); - i += 5; - break; - } - case op_mod: { - X86Assembler::JmpSrc notImm1 = iter->from; - X86Assembler::JmpSrc notImm2 = (++iter)->from; - m_jit.link((++iter)->from, m_jit.label()); - emitFastArithReTagImmediate(X86::eax); - emitFastArithReTagImmediate(X86::ecx); - m_jit.link(notImm1, m_jit.label()); - m_jit.link(notImm2, m_jit.label()); - emitPutArg(X86::eax, 0); - emitPutArg(X86::ecx, 4); - emitCTICall(instruction + i, i, Machine::cti_op_mod); - emitPutResult(instruction[i + 1].u.operand); - i += 4; - break; - } - case op_mul: { - int dst = instruction[i + 1].u.operand; - int src1 = instruction[i + 2].u.operand; - int src2 = instruction[i + 3].u.operand; - JSValue* src1Value = getConstantImmediateNumericArg(src1); - JSValue* src2Value = getConstantImmediateNumericArg(src2); - int32_t value; - if (src1Value && ((value = JSImmediate::intValue(src1Value)) > 0)) { - m_jit.link(iter->from, m_jit.label()); - // There is an extra slow case for (op1 * -N) or (-N * op2), to check for 0 since this should produce a result of -0. - emitGetPutArg(src1, 0, X86::ecx); - emitGetPutArg(src2, 4, X86::ecx); - emitCTICall(instruction + i, i, Machine::cti_op_mul); - emitPutResult(dst); - } else if (src2Value && ((value = JSImmediate::intValue(src2Value)) > 0)) { - m_jit.link(iter->from, m_jit.label()); - // There is an extra slow case for (op1 * -N) or (-N * op2), to check for 0 since this should produce a result of -0. - emitGetPutArg(src1, 0, X86::ecx); - emitGetPutArg(src2, 4, X86::ecx); - emitCTICall(instruction + i, i, Machine::cti_op_mul); - emitPutResult(dst); - } else - compileBinaryArithOpSlowCase(instruction + i, op_mul, iter, dst, src1, src2, OperandTypes::fromInt(instruction[i + 4].u.operand), i); - i += 5; - break; - } - - case op_call: - case op_call_eval: - case op_construct: { - int dst = instruction[i + 1].u.operand; - int callee = instruction[i + 2].u.operand; - int argCount = instruction[i + 5].u.operand; - - m_jit.link(iter->from, m_jit.label()); - - // The arguments have been set up on the hot path for op_call_eval - if (opcodeID != op_call_eval) - compileOpCallSetupArgs(instruction + i, (opcodeID == op_construct), false); - - // Fast check for JS function. - m_jit.testl_i32r(JSImmediate::TagMask, X86::ecx); - X86Assembler::JmpSrc callLinkFailNotObject = m_jit.emitUnlinkedJne(); - m_jit.cmpl_i32m(reinterpret_cast<unsigned>(m_machine->m_jsFunctionVptr), X86::ecx); - X86Assembler::JmpSrc callLinkFailNotJSFunction = m_jit.emitUnlinkedJne(); - - // This handles JSFunctions - emitCTICall(instruction + i, i, (opcodeID == op_construct) ? Machine::cti_op_construct_JSConstruct : Machine::cti_op_call_JSFunction); - // initialize the new call frame (pointed to by edx, after the last call), then set edi to point to it. - compileOpCallInitializeCallFrame(callee, argCount); - m_jit.movl_rr(X86::edx, X86::edi); - - // Try to link & repatch this call. - CallLinkInfo* info = &(m_codeBlock->callLinkInfos[callLinkInfoIndex]); - emitPutArgConstant(reinterpret_cast<unsigned>(info), 4); - m_callStructureStubCompilationInfo[callLinkInfoIndex].callReturnLocation = - emitCTICall(instruction + i, i, Machine::cti_vm_lazyLinkCall); - emitNakedCall(i, X86::eax); - X86Assembler::JmpSrc storeResultForFirstRun = m_jit.emitUnlinkedJmp(); - - // This is the address for the cold path *after* the first run (which tries to link the call). - m_callStructureStubCompilationInfo[callLinkInfoIndex].coldPathOther = m_jit.label(); - - // The arguments have been set up on the hot path for op_call_eval - if (opcodeID != op_call_eval) - compileOpCallSetupArgs(instruction + i, (opcodeID == op_construct), false); - - // Check for JSFunctions. - m_jit.testl_i32r(JSImmediate::TagMask, X86::ecx); - X86Assembler::JmpSrc isNotObject = m_jit.emitUnlinkedJne(); - m_jit.cmpl_i32m(reinterpret_cast<unsigned>(m_machine->m_jsFunctionVptr), X86::ecx); - X86Assembler::JmpSrc isJSFunction = m_jit.emitUnlinkedJe(); - - // This handles host functions - X86Assembler::JmpDst notJSFunctionlabel = m_jit.label(); - m_jit.link(isNotObject, notJSFunctionlabel); - m_jit.link(callLinkFailNotObject, notJSFunctionlabel); - m_jit.link(callLinkFailNotJSFunction, notJSFunctionlabel); - emitCTICall(instruction + i, i, ((opcodeID == op_construct) ? Machine::cti_op_construct_NotJSConstruct : Machine::cti_op_call_NotJSFunction)); - X86Assembler::JmpSrc wasNotJSFunction = m_jit.emitUnlinkedJmp(); - - // Next, handle JSFunctions... - m_jit.link(isJSFunction, m_jit.label()); - emitCTICall(instruction + i, i, (opcodeID == op_construct) ? Machine::cti_op_construct_JSConstruct : Machine::cti_op_call_JSFunction); - // initialize the new call frame (pointed to by edx, after the last call). - compileOpCallInitializeCallFrame(callee, argCount); - m_jit.movl_rr(X86::edx, X86::edi); - - // load ctiCode from the new codeBlock. - m_jit.movl_mr(OBJECT_OFFSET(CodeBlock, ctiCode), X86::eax, X86::eax); - - // Move the new callframe into edi. - m_jit.movl_rr(X86::edx, X86::edi); - - // Check the ctiCode has been generated (if not compile it now), and make the call. - m_jit.testl_rr(X86::eax, X86::eax); - X86Assembler::JmpSrc hasCode = m_jit.emitUnlinkedJne(); - emitCTICall(instruction + i, i, Machine::cti_vm_compile); - m_jit.link(hasCode, m_jit.label()); - - emitNakedCall(i, X86::eax); - - // Put the return value in dst. In the interpreter, op_ret does this. - X86Assembler::JmpDst storeResult = m_jit.label(); - m_jit.link(wasNotJSFunction, storeResult); - m_jit.link(storeResultForFirstRun, storeResult); - emitPutResult(dst); - -#if ENABLE(CODEBLOCK_SAMPLING) - m_jit.movl_i32m(reinterpret_cast<unsigned>(m_codeBlock), m_machine->sampler()->codeBlockSlot()); -#endif - ++callLinkInfoIndex; - - i += 7; - break; - } - case op_to_jsnumber: { - m_jit.link(iter->from, m_jit.label()); - m_jit.link(iter->from, m_jit.label()); - - emitPutArg(X86::eax, 0); - emitCTICall(instruction + i, i, Machine::cti_op_to_jsnumber); - - emitPutResult(instruction[i + 1].u.operand); - i += 3; - break; - } - - default: - ASSERT_NOT_REACHED(); - break; - } - - m_jit.link(m_jit.emitUnlinkedJmp(), m_labels[i]); - } - - ASSERT(propertyAccessInstructionIndex == m_codeBlock->propertyAccessInstructions.size()); - ASSERT(callLinkInfoIndex == m_codeBlock->callLinkInfos.size()); -} - -void CTI::privateCompile() -{ -#if ENABLE(CODEBLOCK_SAMPLING) - m_jit.movl_i32m(reinterpret_cast<unsigned>(m_codeBlock), m_machine->sampler()->codeBlockSlot()); -#endif -#if ENABLE(OPCODE_SAMPLING) - m_jit.movl_i32m(m_machine->sampler()->encodeSample(m_codeBlock->instructions.begin()), m_machine->sampler()->sampleSlot()); -#endif - - // Could use a popl_m, but would need to offset the following instruction if so. - m_jit.popl_r(X86::ecx); - emitPutToCallFrameHeader(X86::ecx, RegisterFile::ReturnPC); - - X86Assembler::JmpSrc slowRegisterFileCheck; - X86Assembler::JmpDst afterRegisterFileCheck; - if (m_codeBlock->codeType == FunctionCode) { - // In the case of a fast linked call, we do not set this up in the caller. - m_jit.movl_i32m(reinterpret_cast<unsigned>(m_codeBlock), RegisterFile::CodeBlock * static_cast<int>(sizeof(Register)), X86::edi); - - emitGetCTIParam(CTI_ARGS_registerFile, X86::eax); - m_jit.leal_mr(m_codeBlock->numCalleeRegisters * sizeof(Register), X86::edi, X86::edx); - m_jit.cmpl_mr(OBJECT_OFFSET(RegisterFile, m_end), X86::eax, X86::edx); - slowRegisterFileCheck = m_jit.emitUnlinkedJg(); - afterRegisterFileCheck = m_jit.label(); - } - - privateCompileMainPass(); - privateCompileLinkPass(); - privateCompileSlowCases(); - - if (m_codeBlock->codeType == FunctionCode) { - m_jit.link(slowRegisterFileCheck, m_jit.label()); - emitCTICall(m_codeBlock->instructions.begin(), 0, Machine::cti_register_file_check); - X86Assembler::JmpSrc backToBody = m_jit.emitUnlinkedJmp(); - m_jit.link(backToBody, afterRegisterFileCheck); - } - - ASSERT(m_jmpTable.isEmpty()); - - void* code = m_jit.copy(); - ASSERT(code); - - // Translate vPC offsets into addresses in JIT generated code, for switch tables. - for (unsigned i = 0; i < m_switches.size(); ++i) { - SwitchRecord record = m_switches[i]; - unsigned opcodeIndex = record.m_opcodeIndex; - - if (record.m_type != SwitchRecord::String) { - ASSERT(record.m_type == SwitchRecord::Immediate || record.m_type == SwitchRecord::Character); - ASSERT(record.m_jumpTable.m_simpleJumpTable->branchOffsets.size() == record.m_jumpTable.m_simpleJumpTable->ctiOffsets.size()); - - record.m_jumpTable.m_simpleJumpTable->ctiDefault = m_jit.getRelocatedAddress(code, m_labels[opcodeIndex + 3 + record.m_defaultOffset]); - - for (unsigned j = 0; j < record.m_jumpTable.m_simpleJumpTable->branchOffsets.size(); ++j) { - unsigned offset = record.m_jumpTable.m_simpleJumpTable->branchOffsets[j]; - record.m_jumpTable.m_simpleJumpTable->ctiOffsets[j] = offset ? m_jit.getRelocatedAddress(code, m_labels[opcodeIndex + 3 + offset]) : record.m_jumpTable.m_simpleJumpTable->ctiDefault; - } - } else { - ASSERT(record.m_type == SwitchRecord::String); - - record.m_jumpTable.m_stringJumpTable->ctiDefault = m_jit.getRelocatedAddress(code, m_labels[opcodeIndex + 3 + record.m_defaultOffset]); - - StringJumpTable::StringOffsetTable::iterator end = record.m_jumpTable.m_stringJumpTable->offsetTable.end(); - for (StringJumpTable::StringOffsetTable::iterator it = record.m_jumpTable.m_stringJumpTable->offsetTable.begin(); it != end; ++it) { - unsigned offset = it->second.branchOffset; - it->second.ctiOffset = offset ? m_jit.getRelocatedAddress(code, m_labels[opcodeIndex + 3 + offset]) : record.m_jumpTable.m_stringJumpTable->ctiDefault; - } - } - } - - for (Vector<HandlerInfo>::iterator iter = m_codeBlock->exceptionHandlers.begin(); iter != m_codeBlock->exceptionHandlers.end(); ++iter) - iter->nativeCode = m_jit.getRelocatedAddress(code, m_labels[iter->target]); - - for (Vector<CallRecord>::iterator iter = m_calls.begin(); iter != m_calls.end(); ++iter) { - if (iter->to) - X86Assembler::link(code, iter->from, iter->to); - m_codeBlock->ctiReturnAddressVPCMap.add(m_jit.getRelocatedAddress(code, iter->from), iter->opcodeIndex); - } - - // Link absolute addresses for jsr - for (Vector<JSRInfo>::iterator iter = m_jsrSites.begin(); iter != m_jsrSites.end(); ++iter) - X86Assembler::linkAbsoluteAddress(code, iter->addrPosition, iter->target); - - for (unsigned i = 0; i < m_codeBlock->propertyAccessInstructions.size(); ++i) { - StructureStubInfo& info = m_codeBlock->propertyAccessInstructions[i]; - info.callReturnLocation = X86Assembler::getRelocatedAddress(code, m_propertyAccessCompilationInfo[i].callReturnLocation); - info.hotPathBegin = X86Assembler::getRelocatedAddress(code, m_propertyAccessCompilationInfo[i].hotPathBegin); - } - for (unsigned i = 0; i < m_codeBlock->callLinkInfos.size(); ++i) { - CallLinkInfo& info = m_codeBlock->callLinkInfos[i]; - info.callReturnLocation = X86Assembler::getRelocatedAddress(code, m_callStructureStubCompilationInfo[i].callReturnLocation); - info.hotPathBegin = X86Assembler::getRelocatedAddress(code, m_callStructureStubCompilationInfo[i].hotPathBegin); - info.hotPathOther = X86Assembler::getRelocatedAddress(code, m_callStructureStubCompilationInfo[i].hotPathOther); - info.coldPathOther = X86Assembler::getRelocatedAddress(code, m_callStructureStubCompilationInfo[i].coldPathOther); - } - - m_codeBlock->ctiCode = code; -} - -void CTI::privateCompileGetByIdSelf(StructureID* structureID, size_t cachedOffset, void* returnAddress) -{ - // Check eax is an object of the right StructureID. - m_jit.testl_i32r(JSImmediate::TagMask, X86::eax); - X86Assembler::JmpSrc failureCases1 = m_jit.emitUnlinkedJne(); - m_jit.cmpl_i32m(reinterpret_cast<uint32_t>(structureID), OBJECT_OFFSET(JSCell, m_structureID), X86::eax); - X86Assembler::JmpSrc failureCases2 = m_jit.emitUnlinkedJne(); - - // Checks out okay! - getDirectOffset - m_jit.movl_mr(OBJECT_OFFSET(JSObject, m_propertyStorage), X86::eax, X86::eax); - m_jit.movl_mr(cachedOffset * sizeof(JSValue*), X86::eax, X86::eax); - m_jit.ret(); - - void* code = m_jit.copy(); - ASSERT(code); - - X86Assembler::link(code, failureCases1, reinterpret_cast<void*>(Machine::cti_op_get_by_id_fail)); - X86Assembler::link(code, failureCases2, reinterpret_cast<void*>(Machine::cti_op_get_by_id_fail)); - - m_codeBlock->getStubInfo(returnAddress).stubRoutine = code; - - ctiRepatchCallByReturnAddress(returnAddress, code); -} - -void CTI::privateCompileGetByIdProto(StructureID* structureID, StructureID* prototypeStructureID, size_t cachedOffset, void* returnAddress) -{ -#if USE(CTI_REPATCH_PIC) - StructureStubInfo& info = m_codeBlock->getStubInfo(returnAddress); - - // We don't want to repatch more than once - in future go to cti_op_put_by_id_generic. - ctiRepatchCallByReturnAddress(returnAddress, reinterpret_cast<void*>(Machine::cti_op_get_by_id_fail)); - - // The prototype object definitely exists (if this stub exists the CodeBlock is referencing a StructureID that is - // referencing the prototype object - let's speculatively load it's table nice and early!) - JSObject* protoObject = asObject(structureID->prototypeForLookup(m_callFrame)); - PropertyStorage* protoPropertyStorage = &protoObject->m_propertyStorage; - m_jit.movl_mr(static_cast<void*>(protoPropertyStorage), X86::edx); - - // check eax is an object of the right StructureID. - m_jit.testl_i32r(JSImmediate::TagMask, X86::eax); - X86Assembler::JmpSrc failureCases1 = m_jit.emitUnlinkedJne(); - m_jit.cmpl_i32m(reinterpret_cast<uint32_t>(structureID), OBJECT_OFFSET(JSCell, m_structureID), X86::eax); - X86Assembler::JmpSrc failureCases2 = m_jit.emitUnlinkedJne(); - - // Check the prototype object's StructureID had not changed. - StructureID** protoStructureIDAddress = &(protoObject->m_structureID); - m_jit.cmpl_i32m(reinterpret_cast<uint32_t>(prototypeStructureID), static_cast<void*>(protoStructureIDAddress)); - X86Assembler::JmpSrc failureCases3 = m_jit.emitUnlinkedJne(); - - // Checks out okay! - getDirectOffset - m_jit.movl_mr(cachedOffset * sizeof(JSValue*), X86::edx, X86::ecx); - - X86Assembler::JmpSrc success = m_jit.emitUnlinkedJmp(); - - void* code = m_jit.copy(); - ASSERT(code); - - // Use the repatch information to link the failure cases back to the original slow case routine. - void* slowCaseBegin = reinterpret_cast<char*>(info.callReturnLocation) - repatchOffsetGetByIdSlowCaseCall; - X86Assembler::link(code, failureCases1, slowCaseBegin); - X86Assembler::link(code, failureCases2, slowCaseBegin); - X86Assembler::link(code, failureCases3, slowCaseBegin); - - // On success return back to the hot patch code, at a point it will perform the store to dest for us. - intptr_t successDest = (intptr_t)(info.hotPathBegin) + repatchOffsetGetByIdPropertyMapOffset; - X86Assembler::link(code, success, reinterpret_cast<void*>(successDest)); - - // Track the stub we have created so that it will be deleted later. - m_codeBlock->getStubInfo(returnAddress).stubRoutine = code; - - // Finally repatch the jump to sow case back in the hot path to jump here instead. - // FIXME: should revert this repatching, on failure. - intptr_t jmpLocation = reinterpret_cast<intptr_t>(info.hotPathBegin) + repatchOffsetGetByIdBranchToSlowCase; - X86Assembler::repatchBranchOffset(jmpLocation, code); -#else - // The prototype object definitely exists (if this stub exists the CodeBlock is referencing a StructureID that is - // referencing the prototype object - let's speculatively load it's table nice and early!) - JSObject* protoObject = asObject(structureID->prototypeForLookup(m_callFrame)); - PropertyStorage* protoPropertyStorage = &protoObject->m_propertyStorage; - m_jit.movl_mr(static_cast<void*>(protoPropertyStorage), X86::edx); - - // check eax is an object of the right StructureID. - m_jit.testl_i32r(JSImmediate::TagMask, X86::eax); - X86Assembler::JmpSrc failureCases1 = m_jit.emitUnlinkedJne(); - m_jit.cmpl_i32m(reinterpret_cast<uint32_t>(structureID), OBJECT_OFFSET(JSCell, m_structureID), X86::eax); - X86Assembler::JmpSrc failureCases2 = m_jit.emitUnlinkedJne(); - - // Check the prototype object's StructureID had not changed. - StructureID** protoStructureIDAddress = &(protoObject->m_structureID); - m_jit.cmpl_i32m(reinterpret_cast<uint32_t>(prototypeStructureID), static_cast<void*>(protoStructureIDAddress)); - X86Assembler::JmpSrc failureCases3 = m_jit.emitUnlinkedJne(); - - // Checks out okay! - getDirectOffset - m_jit.movl_mr(cachedOffset * sizeof(JSValue*), X86::edx, X86::eax); - - m_jit.ret(); - - void* code = m_jit.copy(); - ASSERT(code); - - X86Assembler::link(code, failureCases1, reinterpret_cast<void*>(Machine::cti_op_get_by_id_fail)); - X86Assembler::link(code, failureCases2, reinterpret_cast<void*>(Machine::cti_op_get_by_id_fail)); - X86Assembler::link(code, failureCases3, reinterpret_cast<void*>(Machine::cti_op_get_by_id_fail)); - - m_codeBlock->getStubInfo(returnAddress).stubRoutine = code; - - ctiRepatchCallByReturnAddress(returnAddress, code); -#endif -} - -void CTI::privateCompileGetByIdChain(StructureID* structureID, StructureIDChain* chain, size_t count, size_t cachedOffset, void* returnAddress) -{ - ASSERT(count); - - Vector<X86Assembler::JmpSrc> bucketsOfFail; - - // Check eax is an object of the right StructureID. - m_jit.testl_i32r(JSImmediate::TagMask, X86::eax); - bucketsOfFail.append(m_jit.emitUnlinkedJne()); - m_jit.cmpl_i32m(reinterpret_cast<uint32_t>(structureID), OBJECT_OFFSET(JSCell, m_structureID), X86::eax); - bucketsOfFail.append(m_jit.emitUnlinkedJne()); - - StructureID* currStructureID = structureID; - RefPtr<StructureID>* chainEntries = chain->head(); - JSObject* protoObject = 0; - for (unsigned i = 0; i<count; ++i) { - protoObject = asObject(currStructureID->prototypeForLookup(m_callFrame)); - currStructureID = chainEntries[i].get(); - - // Check the prototype object's StructureID had not changed. - StructureID** protoStructureIDAddress = &(protoObject->m_structureID); - m_jit.cmpl_i32m(reinterpret_cast<uint32_t>(currStructureID), static_cast<void*>(protoStructureIDAddress)); - bucketsOfFail.append(m_jit.emitUnlinkedJne()); - } - ASSERT(protoObject); - - PropertyStorage* protoPropertyStorage = &protoObject->m_propertyStorage; - m_jit.movl_mr(static_cast<void*>(protoPropertyStorage), X86::edx); - m_jit.movl_mr(cachedOffset * sizeof(JSValue*), X86::edx, X86::eax); - m_jit.ret(); - - bucketsOfFail.append(m_jit.emitUnlinkedJmp()); - - void* code = m_jit.copy(); - ASSERT(code); - - for (unsigned i = 0; i < bucketsOfFail.size(); ++i) - X86Assembler::link(code, bucketsOfFail[i], reinterpret_cast<void*>(Machine::cti_op_get_by_id_fail)); - - m_codeBlock->getStubInfo(returnAddress).stubRoutine = code; - - ctiRepatchCallByReturnAddress(returnAddress, code); -} - -void CTI::privateCompilePutByIdReplace(StructureID* structureID, size_t cachedOffset, void* returnAddress) -{ - // check eax is an object of the right StructureID. - m_jit.testl_i32r(JSImmediate::TagMask, X86::eax); - X86Assembler::JmpSrc failureCases1 = m_jit.emitUnlinkedJne(); - m_jit.cmpl_i32m(reinterpret_cast<uint32_t>(structureID), OBJECT_OFFSET(JSCell, m_structureID), X86::eax); - X86Assembler::JmpSrc failureCases2 = m_jit.emitUnlinkedJne(); - - // checks out okay! - putDirectOffset - m_jit.movl_mr(OBJECT_OFFSET(JSObject, m_propertyStorage), X86::eax, X86::eax); - m_jit.movl_rm(X86::edx, cachedOffset * sizeof(JSValue*), X86::eax); - m_jit.ret(); - - void* code = m_jit.copy(); - ASSERT(code); - - X86Assembler::link(code, failureCases1, reinterpret_cast<void*>(Machine::cti_op_put_by_id_fail)); - X86Assembler::link(code, failureCases2, reinterpret_cast<void*>(Machine::cti_op_put_by_id_fail)); - - m_codeBlock->getStubInfo(returnAddress).stubRoutine = code; - - ctiRepatchCallByReturnAddress(returnAddress, code); -} - -extern "C" { - - static JSObject* resizePropertyStorage(JSObject* baseObject, size_t oldSize, size_t newSize) - { - baseObject->allocatePropertyStorageInline(oldSize, newSize); - return baseObject; - } - -} - -static inline bool transitionWillNeedStorageRealloc(StructureID* oldStructureID, StructureID* newStructureID) -{ - return oldStructureID->propertyStorageCapacity() != newStructureID->propertyStorageCapacity(); -} - -void CTI::privateCompilePutByIdTransition(StructureID* oldStructureID, StructureID* newStructureID, size_t cachedOffset, StructureIDChain* sIDC, void* returnAddress) -{ - Vector<X86Assembler::JmpSrc, 16> failureCases; - // check eax is an object of the right StructureID. - m_jit.testl_i32r(JSImmediate::TagMask, X86::eax); - failureCases.append(m_jit.emitUnlinkedJne()); - m_jit.cmpl_i32m(reinterpret_cast<uint32_t>(oldStructureID), OBJECT_OFFSET(JSCell, m_structureID), X86::eax); - failureCases.append(m_jit.emitUnlinkedJne()); - Vector<X86Assembler::JmpSrc> successCases; - - // ecx = baseObject - m_jit.movl_mr(OBJECT_OFFSET(JSCell, m_structureID), X86::eax, X86::ecx); - // proto(ecx) = baseObject->structureID()->prototype() - m_jit.cmpl_i32m(ObjectType, OBJECT_OFFSET(StructureID, m_typeInfo) + OBJECT_OFFSET(TypeInfo, m_type), X86::ecx); - failureCases.append(m_jit.emitUnlinkedJne()); - m_jit.movl_mr(OBJECT_OFFSET(StructureID, m_prototype), X86::ecx, X86::ecx); - - // ecx = baseObject->m_structureID - for (RefPtr<StructureID>* it = sIDC->head(); *it; ++it) { - // null check the prototype - m_jit.cmpl_i32r(asInteger(jsNull()), X86::ecx); - successCases.append(m_jit.emitUnlinkedJe()); - - // Check the structure id - m_jit.cmpl_i32m(reinterpret_cast<uint32_t>(it->get()), OBJECT_OFFSET(JSCell, m_structureID), X86::ecx); - failureCases.append(m_jit.emitUnlinkedJne()); - - m_jit.movl_mr(OBJECT_OFFSET(JSCell, m_structureID), X86::ecx, X86::ecx); - m_jit.cmpl_i32m(ObjectType, OBJECT_OFFSET(StructureID, m_typeInfo) + OBJECT_OFFSET(TypeInfo, m_type), X86::ecx); - failureCases.append(m_jit.emitUnlinkedJne()); - m_jit.movl_mr(OBJECT_OFFSET(StructureID, m_prototype), X86::ecx, X86::ecx); - } - - failureCases.append(m_jit.emitUnlinkedJne()); - for (unsigned i = 0; i < successCases.size(); ++i) - m_jit.link(successCases[i], m_jit.label()); - - X86Assembler::JmpSrc callTarget; - - // emit a call only if storage realloc is needed - if (transitionWillNeedStorageRealloc(oldStructureID, newStructureID)) { - m_jit.pushl_r(X86::edx); - m_jit.pushl_i32(newStructureID->propertyStorageCapacity()); - m_jit.pushl_i32(oldStructureID->propertyStorageCapacity()); - m_jit.pushl_r(X86::eax); - callTarget = m_jit.emitCall(); - m_jit.addl_i32r(3 * sizeof(void*), X86::esp); - m_jit.popl_r(X86::edx); - } - - // Assumes m_refCount can be decremented easily, refcount decrement is safe as - // codeblock should ensure oldStructureID->m_refCount > 0 - m_jit.subl_i8m(1, reinterpret_cast<void*>(oldStructureID)); - m_jit.addl_i8m(1, reinterpret_cast<void*>(newStructureID)); - m_jit.movl_i32m(reinterpret_cast<uint32_t>(newStructureID), OBJECT_OFFSET(JSCell, m_structureID), X86::eax); - - // write the value - m_jit.movl_mr(OBJECT_OFFSET(JSObject, m_propertyStorage), X86::eax, X86::eax); - m_jit.movl_rm(X86::edx, cachedOffset * sizeof(JSValue*), X86::eax); - - m_jit.ret(); - - X86Assembler::JmpSrc failureJump; - if (failureCases.size()) { - for (unsigned i = 0; i < failureCases.size(); ++i) - m_jit.link(failureCases[i], m_jit.label()); - m_jit.emitRestoreArgumentReferenceForTrampoline(); - failureJump = m_jit.emitUnlinkedJmp(); - } - - void* code = m_jit.copy(); - ASSERT(code); - - if (failureCases.size()) - X86Assembler::link(code, failureJump, reinterpret_cast<void*>(Machine::cti_op_put_by_id_fail)); - - if (transitionWillNeedStorageRealloc(oldStructureID, newStructureID)) - X86Assembler::link(code, callTarget, reinterpret_cast<void*>(resizePropertyStorage)); - - m_codeBlock->getStubInfo(returnAddress).stubRoutine = code; - - ctiRepatchCallByReturnAddress(returnAddress, code); -} - -void CTI::unlinkCall(CallLinkInfo* callLinkInfo) -{ - // When the JSFunction is deleted the pointer embedded in the instruction stream will no longer be valid - // (and, if a new JSFunction happened to be constructed at the same location, we could get a false positive - // match). Reset the check so it no longer matches. - reinterpret_cast<void**>(callLinkInfo->hotPathBegin)[-1] = asPointer(JSImmediate::impossibleValue()); -} - -void CTI::linkCall(JSFunction* callee, CodeBlock* calleeCodeBlock, void* ctiCode, CallLinkInfo* callLinkInfo, int callerArgCount) -{ - // Currently we only link calls with the exact number of arguments. - if (callerArgCount == calleeCodeBlock->numParameters) { - ASSERT(!callLinkInfo->isLinked()); - - calleeCodeBlock->addCaller(callLinkInfo); - - reinterpret_cast<void**>(callLinkInfo->hotPathBegin)[-1] = callee; - ctiRepatchCallByReturnAddress(callLinkInfo->hotPathOther, ctiCode); - } - - // repatch the instruction that jumps out to the cold path, so that we only try to link once. - void* repatchCheck = reinterpret_cast<void*>(reinterpret_cast<ptrdiff_t>(callLinkInfo->hotPathBegin) + repatchOffsetOpCallCall); - ctiRepatchCallByReturnAddress(repatchCheck, callLinkInfo->coldPathOther); -} - -void* CTI::privateCompileArrayLengthTrampoline() -{ - // Check eax is an array - m_jit.testl_i32r(JSImmediate::TagMask, X86::eax); - X86Assembler::JmpSrc failureCases1 = m_jit.emitUnlinkedJne(); - m_jit.cmpl_i32m(reinterpret_cast<unsigned>(m_machine->m_jsArrayVptr), X86::eax); - X86Assembler::JmpSrc failureCases2 = m_jit.emitUnlinkedJne(); - - // Checks out okay! - get the length from the storage - m_jit.movl_mr(OBJECT_OFFSET(JSArray, m_storage), X86::eax, X86::eax); - m_jit.movl_mr(OBJECT_OFFSET(ArrayStorage, m_length), X86::eax, X86::eax); - - m_jit.addl_rr(X86::eax, X86::eax); - X86Assembler::JmpSrc failureCases3 = m_jit.emitUnlinkedJo(); - m_jit.addl_i8r(1, X86::eax); - - m_jit.ret(); - - void* code = m_jit.copy(); - ASSERT(code); - - X86Assembler::link(code, failureCases1, reinterpret_cast<void*>(Machine::cti_op_get_by_id_fail)); - X86Assembler::link(code, failureCases2, reinterpret_cast<void*>(Machine::cti_op_get_by_id_fail)); - X86Assembler::link(code, failureCases3, reinterpret_cast<void*>(Machine::cti_op_get_by_id_fail)); - - return code; -} - -void* CTI::privateCompileStringLengthTrampoline() -{ - // Check eax is a string - m_jit.testl_i32r(JSImmediate::TagMask, X86::eax); - X86Assembler::JmpSrc failureCases1 = m_jit.emitUnlinkedJne(); - m_jit.cmpl_i32m(reinterpret_cast<unsigned>(m_machine->m_jsStringVptr), X86::eax); - X86Assembler::JmpSrc failureCases2 = m_jit.emitUnlinkedJne(); - - // Checks out okay! - get the length from the Ustring. - m_jit.movl_mr(OBJECT_OFFSET(JSString, m_value) + OBJECT_OFFSET(UString, m_rep), X86::eax, X86::eax); - m_jit.movl_mr(OBJECT_OFFSET(UString::Rep, len), X86::eax, X86::eax); - - m_jit.addl_rr(X86::eax, X86::eax); - X86Assembler::JmpSrc failureCases3 = m_jit.emitUnlinkedJo(); - m_jit.addl_i8r(1, X86::eax); - - m_jit.ret(); - - void* code = m_jit.copy(); - ASSERT(code); - - X86Assembler::link(code, failureCases1, reinterpret_cast<void*>(Machine::cti_op_get_by_id_fail)); - X86Assembler::link(code, failureCases2, reinterpret_cast<void*>(Machine::cti_op_get_by_id_fail)); - X86Assembler::link(code, failureCases3, reinterpret_cast<void*>(Machine::cti_op_get_by_id_fail)); - - return code; -} - -void CTI::patchGetByIdSelf(CodeBlock* codeBlock, StructureID* structureID, size_t cachedOffset, void* returnAddress) -{ - StructureStubInfo& info = codeBlock->getStubInfo(returnAddress); - - // We don't want to repatch more than once - in future go to cti_op_get_by_id_generic. - // Should probably go to Machine::cti_op_get_by_id_fail, but that doesn't do anything interesting right now. - ctiRepatchCallByReturnAddress(returnAddress, reinterpret_cast<void*>(Machine::cti_op_get_by_id_generic)); - - // Repatch the offset into the propoerty map to load from, then repatch the StructureID to look for. - X86Assembler::repatchDisplacement(reinterpret_cast<intptr_t>(info.hotPathBegin) + repatchOffsetGetByIdPropertyMapOffset, cachedOffset * sizeof(JSValue*)); - X86Assembler::repatchImmediate(reinterpret_cast<intptr_t>(info.hotPathBegin) + repatchOffsetGetByIdStructureID, reinterpret_cast<uint32_t>(structureID)); -} - -void CTI::patchPutByIdReplace(CodeBlock* codeBlock, StructureID* structureID, size_t cachedOffset, void* returnAddress) -{ - StructureStubInfo& info = codeBlock->getStubInfo(returnAddress); - - // We don't want to repatch more than once - in future go to cti_op_put_by_id_generic. - // Should probably go to Machine::cti_op_put_by_id_fail, but that doesn't do anything interesting right now. - ctiRepatchCallByReturnAddress(returnAddress, reinterpret_cast<void*>(Machine::cti_op_put_by_id_generic)); - - // Repatch the offset into the propoerty map to load from, then repatch the StructureID to look for. - X86Assembler::repatchDisplacement(reinterpret_cast<intptr_t>(info.hotPathBegin) + repatchOffsetPutByIdPropertyMapOffset, cachedOffset * sizeof(JSValue*)); - X86Assembler::repatchImmediate(reinterpret_cast<intptr_t>(info.hotPathBegin) + repatchOffsetPutByIdStructureID, reinterpret_cast<uint32_t>(structureID)); -} - -void CTI::privateCompilePatchGetArrayLength(void* returnAddress) -{ - StructureStubInfo& info = m_codeBlock->getStubInfo(returnAddress); - - // We don't want to repatch more than once - in future go to cti_op_put_by_id_generic. - ctiRepatchCallByReturnAddress(returnAddress, reinterpret_cast<void*>(Machine::cti_op_get_by_id_fail)); - - // Check eax is an array - m_jit.testl_i32r(JSImmediate::TagMask, X86::eax); - X86Assembler::JmpSrc failureCases1 = m_jit.emitUnlinkedJne(); - m_jit.cmpl_i32m(reinterpret_cast<unsigned>(m_machine->m_jsArrayVptr), X86::eax); - X86Assembler::JmpSrc failureCases2 = m_jit.emitUnlinkedJne(); - - // Checks out okay! - get the length from the storage - m_jit.movl_mr(OBJECT_OFFSET(JSArray, m_storage), X86::eax, X86::ecx); - m_jit.movl_mr(OBJECT_OFFSET(ArrayStorage, m_length), X86::ecx, X86::ecx); - - m_jit.addl_rr(X86::ecx, X86::ecx); - X86Assembler::JmpSrc failureClobberedECX = m_jit.emitUnlinkedJo(); - m_jit.addl_i8r(1, X86::ecx); - - X86Assembler::JmpSrc success = m_jit.emitUnlinkedJmp(); - - m_jit.link(failureClobberedECX, m_jit.label()); - m_jit.emitRestoreArgumentReference(); - X86Assembler::JmpSrc failureCases3 = m_jit.emitUnlinkedJmp(); - - void* code = m_jit.copy(); - ASSERT(code); - - // Use the repatch information to link the failure cases back to the original slow case routine. - void* slowCaseBegin = reinterpret_cast<char*>(info.callReturnLocation) - repatchOffsetGetByIdSlowCaseCall; - X86Assembler::link(code, failureCases1, slowCaseBegin); - X86Assembler::link(code, failureCases2, slowCaseBegin); - X86Assembler::link(code, failureCases3, slowCaseBegin); - - // On success return back to the hot patch code, at a point it will perform the store to dest for us. - intptr_t successDest = (intptr_t)(info.hotPathBegin) + repatchOffsetGetByIdPropertyMapOffset; - X86Assembler::link(code, success, reinterpret_cast<void*>(successDest)); - - // Track the stub we have created so that it will be deleted later. - m_codeBlock->getStubInfo(returnAddress).stubRoutine = code; - - // Finally repatch the jump to sow case back in the hot path to jump here instead. - // FIXME: should revert this repatching, on failure. - intptr_t jmpLocation = reinterpret_cast<intptr_t>(info.hotPathBegin) + repatchOffsetGetByIdBranchToSlowCase; - X86Assembler::repatchBranchOffset(jmpLocation, code); -} - -void CTI::emitGetVariableObjectRegister(X86Assembler::RegisterID variableObject, int index, X86Assembler::RegisterID dst) -{ - m_jit.movl_mr(JSVariableObject::offsetOf_d(), variableObject, dst); - m_jit.movl_mr(JSVariableObject::offsetOf_Data_registers(), dst, dst); - m_jit.movl_mr(index * sizeof(Register), dst, dst); -} - -void CTI::emitPutVariableObjectRegister(X86Assembler::RegisterID src, X86Assembler::RegisterID variableObject, int index) -{ - m_jit.movl_mr(JSVariableObject::offsetOf_d(), variableObject, variableObject); - m_jit.movl_mr(JSVariableObject::offsetOf_Data_registers(), variableObject, variableObject); - m_jit.movl_rm(src, index * sizeof(Register), variableObject); -} - -#if ENABLE(WREC) - -void* CTI::compileRegExp(Machine* machine, const UString& pattern, unsigned* numSubpatterns_ptr, const char** error_ptr, bool ignoreCase, bool multiline) -{ - // TODO: better error messages - if (pattern.size() > MaxPatternSize) { - *error_ptr = "regular expression too large"; - return 0; - } - - X86Assembler jit(machine->jitCodeBuffer()); - WRECParser parser(pattern, ignoreCase, multiline, jit); - - jit.emitConvertToFastCall(); - // (0) Setup: - // Preserve regs & initialize outputRegister. - jit.pushl_r(WRECGenerator::outputRegister); - jit.pushl_r(WRECGenerator::currentValueRegister); - // push pos onto the stack, both to preserve and as a parameter available to parseDisjunction - jit.pushl_r(WRECGenerator::currentPositionRegister); - // load output pointer - jit.movl_mr(16 -#if COMPILER(MSVC) - + 3 * sizeof(void*) -#endif - , X86::esp, WRECGenerator::outputRegister); - - // restart point on match fail. - WRECGenerator::JmpDst nextLabel = jit.label(); - - // (1) Parse Disjunction: - - // Parsing the disjunction should fully consume the pattern. - JmpSrcVector failures; - parser.parseDisjunction(failures); - if (parser.isEndOfPattern()) { - parser.m_err = WRECParser::Error_malformedPattern; - } - if (parser.m_err) { - // TODO: better error messages - *error_ptr = "TODO: better error messages"; - return 0; - } - - // (2) Success: - // Set return value & pop registers from the stack. - - jit.testl_rr(WRECGenerator::outputRegister, WRECGenerator::outputRegister); - WRECGenerator::JmpSrc noOutput = jit.emitUnlinkedJe(); - - jit.movl_rm(WRECGenerator::currentPositionRegister, 4, WRECGenerator::outputRegister); - jit.popl_r(X86::eax); - jit.movl_rm(X86::eax, WRECGenerator::outputRegister); - jit.popl_r(WRECGenerator::currentValueRegister); - jit.popl_r(WRECGenerator::outputRegister); - jit.ret(); - - jit.link(noOutput, jit.label()); - - jit.popl_r(X86::eax); - jit.movl_rm(X86::eax, WRECGenerator::outputRegister); - jit.popl_r(WRECGenerator::currentValueRegister); - jit.popl_r(WRECGenerator::outputRegister); - jit.ret(); - - // (3) Failure: - // All fails link to here. Progress the start point & if it is within scope, loop. - // Otherwise, return fail value. - WRECGenerator::JmpDst here = jit.label(); - for (unsigned i = 0; i < failures.size(); ++i) - jit.link(failures[i], here); - failures.clear(); - - jit.movl_mr(X86::esp, WRECGenerator::currentPositionRegister); - jit.addl_i8r(1, WRECGenerator::currentPositionRegister); - jit.movl_rm(WRECGenerator::currentPositionRegister, X86::esp); - jit.cmpl_rr(WRECGenerator::lengthRegister, WRECGenerator::currentPositionRegister); - jit.link(jit.emitUnlinkedJle(), nextLabel); - - jit.addl_i8r(4, X86::esp); - - jit.movl_i32r(-1, X86::eax); - jit.popl_r(WRECGenerator::currentValueRegister); - jit.popl_r(WRECGenerator::outputRegister); - jit.ret(); - - *numSubpatterns_ptr = parser.m_numSubpatterns; - - void* code = jit.copy(); - ASSERT(code); - return code; -} - -#endif // ENABLE(WREC) - -} // namespace JSC - -#endif // ENABLE(CTI) diff --git a/JavaScriptCore/VM/CTI.h b/JavaScriptCore/VM/CTI.h deleted file mode 100644 index 04bb6ca..0000000 --- a/JavaScriptCore/VM/CTI.h +++ /dev/null @@ -1,475 +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 CTI_h -#define CTI_h - -#if ENABLE(CTI) - -#define WTF_USE_CTI_REPATCH_PIC 1 - -#include "Machine.h" -#include "Opcode.h" -#include "RegisterFile.h" -#include <masm/X86Assembler.h> -#include <profiler/Profiler.h> -#include <wtf/AlwaysInline.h> -#include <wtf/Vector.h> - -#define CTI_ARGS_code 0x0C -#define CTI_ARGS_registerFile 0x0D -#define CTI_ARGS_callFrame 0x0E -#define CTI_ARGS_exception 0x0F -#define CTI_ARGS_profilerReference 0x10 -#define CTI_ARGS_globalData 0x11 - -#define ARG_callFrame static_cast<CallFrame*>(ARGS[CTI_ARGS_callFrame]) -#define ARG_registerFile static_cast<RegisterFile*>(ARGS[CTI_ARGS_registerFile]) -#define ARG_exception static_cast<JSValue**>(ARGS[CTI_ARGS_exception]) -#define ARG_profilerReference static_cast<Profiler**>(ARGS[CTI_ARGS_profilerReference]) -#define ARG_globalData static_cast<JSGlobalData*>(ARGS[CTI_ARGS_globalData]) - -#define ARG_setCallFrame(newCallFrame) (ARGS[CTI_ARGS_callFrame] = (newCallFrame)) - -#define ARG_src1 static_cast<JSValue*>(ARGS[1]) -#define ARG_src2 static_cast<JSValue*>(ARGS[2]) -#define ARG_src3 static_cast<JSValue*>(ARGS[3]) -#define ARG_src4 static_cast<JSValue*>(ARGS[4]) -#define ARG_src5 static_cast<JSValue*>(ARGS[5]) -#define ARG_id1 static_cast<Identifier*>(ARGS[1]) -#define ARG_id2 static_cast<Identifier*>(ARGS[2]) -#define ARG_id3 static_cast<Identifier*>(ARGS[3]) -#define ARG_id4 static_cast<Identifier*>(ARGS[4]) -#define ARG_int1 reinterpret_cast<intptr_t>(ARGS[1]) -#define ARG_int2 reinterpret_cast<intptr_t>(ARGS[2]) -#define ARG_int3 reinterpret_cast<intptr_t>(ARGS[3]) -#define ARG_int4 reinterpret_cast<intptr_t>(ARGS[4]) -#define ARG_int5 reinterpret_cast<intptr_t>(ARGS[5]) -#define ARG_int6 reinterpret_cast<intptr_t>(ARGS[6]) -#define ARG_func1 static_cast<FuncDeclNode*>(ARGS[1]) -#define ARG_funcexp1 static_cast<FuncExprNode*>(ARGS[1]) -#define ARG_registers1 static_cast<Register*>(ARGS[1]) -#define ARG_regexp1 static_cast<RegExp*>(ARGS[1]) -#define ARG_pni1 static_cast<JSPropertyNameIterator*>(ARGS[1]) -#define ARG_instr1 static_cast<Instruction*>(ARGS[1]) -#define ARG_instr2 static_cast<Instruction*>(ARGS[2]) -#define ARG_instr3 static_cast<Instruction*>(ARGS[3]) -#define ARG_instr4 static_cast<Instruction*>(ARGS[4]) -#define ARG_instr5 static_cast<Instruction*>(ARGS[5]) -#define ARG_instr6 static_cast<Instruction*>(ARGS[6]) -#define ARG_linkInfo2 static_cast<CallLinkInfo*>(ARGS[2]) - -#define CTI_RETURN_ADDRESS_SLOT (ARGS[-1]) - -#if COMPILER(MSVC) -#define FASTCALL __fastcall -#elif COMPILER(GCC) -#define FASTCALL __attribute__ ((fastcall)) -#else -#error Need to support fastcall calling convention in this compiler -#endif - -namespace JSC { - - class CodeBlock; - class JSPropertyNameIterator; - class Machine; - class Register; - class RegisterFile; - class ScopeChainNode; - class SimpleJumpTable; - class StringJumpTable; - class StructureIDChain; - - struct CallLinkInfo; - struct Instruction; - struct OperandTypes; - - typedef JSValue* (SFX_CALL *CTIHelper_j)(CTI_ARGS); - typedef JSObject* (SFX_CALL *CTIHelper_o)(CTI_ARGS); - typedef JSPropertyNameIterator* (SFX_CALL *CTIHelper_p)(CTI_ARGS); - typedef void (SFX_CALL *CTIHelper_v)(CTI_ARGS); - typedef void* (SFX_CALL *CTIHelper_s)(CTI_ARGS); - typedef int (SFX_CALL *CTIHelper_b)(CTI_ARGS); - typedef VoidPtrPair (SFX_CALL *CTIHelper_2)(CTI_ARGS); - - struct CallRecord { - X86Assembler::JmpSrc from; - void* to; - unsigned opcodeIndex; - - CallRecord() - { - } - - CallRecord(X86Assembler::JmpSrc f, CTIHelper_j t, unsigned i) - : from(f) - , to(reinterpret_cast<void*>(t)) - , opcodeIndex(i) - { - } - - CallRecord(X86Assembler::JmpSrc f, CTIHelper_o t, unsigned i) - : from(f) - , to(reinterpret_cast<void*>(t)) - , opcodeIndex(i) - { - } - - CallRecord(X86Assembler::JmpSrc f, CTIHelper_p t, unsigned i) - : from(f) - , to(reinterpret_cast<void*>(t)) - , opcodeIndex(i) - { - } - - CallRecord(X86Assembler::JmpSrc f, CTIHelper_v t, unsigned i) - : from(f) - , to(reinterpret_cast<void*>(t)) - , opcodeIndex(i) - { - } - - CallRecord(X86Assembler::JmpSrc f, CTIHelper_s t, unsigned i) - : from(f) - , to(reinterpret_cast<void*>(t)) - , opcodeIndex(i) - { - } - - CallRecord(X86Assembler::JmpSrc f, CTIHelper_b t, unsigned i) - : from(f) - , to(reinterpret_cast<void*>(t)) - , opcodeIndex(i) - { - } - - CallRecord(X86Assembler::JmpSrc f, CTIHelper_2 t, unsigned i) - : from(f) - , to(reinterpret_cast<void*>(t)) - , opcodeIndex(i) - { - } - - CallRecord(X86Assembler::JmpSrc f, unsigned i) - : from(f) - , to(0) - , opcodeIndex(i) - { - } - }; - - struct JmpTable { - X86Assembler::JmpSrc from; - unsigned to; - - JmpTable(X86Assembler::JmpSrc f, unsigned t) - : from(f) - , to(t) - { - } - }; - - struct SlowCaseEntry { - X86Assembler::JmpSrc from; - unsigned to; - unsigned hint; - - SlowCaseEntry(X86Assembler::JmpSrc f, unsigned t, unsigned h = 0) - : from(f) - , to(t) - , hint(h) - { - } - }; - - struct SwitchRecord { - enum Type { - Immediate, - Character, - String - }; - - Type m_type; - - union { - SimpleJumpTable* m_simpleJumpTable; - StringJumpTable* m_stringJumpTable; - } m_jumpTable; - - unsigned m_opcodeIndex; - unsigned m_defaultOffset; - - SwitchRecord(SimpleJumpTable* jumpTable, unsigned opcodeIndex, unsigned defaultOffset, Type type) - : m_type(type) - , m_opcodeIndex(opcodeIndex) - , m_defaultOffset(defaultOffset) - { - m_jumpTable.m_simpleJumpTable = jumpTable; - } - - SwitchRecord(StringJumpTable* jumpTable, unsigned opcodeIndex, unsigned defaultOffset) - : m_type(String) - , m_opcodeIndex(opcodeIndex) - , m_defaultOffset(defaultOffset) - { - m_jumpTable.m_stringJumpTable = jumpTable; - } - }; - - struct StructureStubCompilationInfo { - X86Assembler::JmpSrc callReturnLocation; - X86Assembler::JmpDst hotPathBegin; - X86Assembler::JmpSrc hotPathOther; - X86Assembler::JmpDst coldPathOther; - }; - - extern "C" { - JSValue* ctiTrampoline(void* code, RegisterFile*, CallFrame*, JSValue** exception, Profiler**, JSGlobalData*); - void ctiVMThrowTrampoline(); - }; - - void ctiSetReturnAddress(void** where, void* what); - void ctiRepatchCallByReturnAddress(void* where, void* what); - - class CTI { - static const int repatchGetByIdDefaultStructureID = -1; - // Magic number - initial offset cannot be representable as a signed 8bit value, or the X86Assembler - // will compress the displacement, and we may not be able to fit a repatched offset. - static const int repatchGetByIdDefaultOffset = 256; - -#if USE(FAST_CALL_CTI_ARGUMENT) - static const int ctiArgumentInitSize = 2; -#elif USE(CTI_ARGUMENT) - static const int ctiArgumentInitSize = 4; -#else - static const int ctiArgumentInitSize = 0; -#endif - // These architecture specific value are used to enable repatching - see comment on op_put_by_id. - static const int repatchOffsetPutByIdStructureID = 19; - static const int repatchOffsetPutByIdPropertyMapOffset = 34; - // These architecture specific value are used to enable repatching - see comment on op_get_by_id. - static const int repatchOffsetGetByIdStructureID = 19; - static const int repatchOffsetGetByIdBranchToSlowCase = 25; - static const int repatchOffsetGetByIdPropertyMapOffset = 34; -#if ENABLE(OPCODE_SAMPLING) - static const int repatchOffsetGetByIdSlowCaseCall = 27 + 4 + ctiArgumentInitSize; -#else - static const int repatchOffsetGetByIdSlowCaseCall = 17 + 4 + ctiArgumentInitSize; -#endif - static const int repatchOffsetOpCallCall = 6; - - public: - static void compile(Machine* machine, CallFrame* callFrame, CodeBlock* codeBlock) - { - CTI cti(machine, callFrame, codeBlock); - cti.privateCompile(); - } - -#if ENABLE(WREC) - static void* compileRegExp(Machine*, const UString& pattern, unsigned* numSubpatterns_ptr, const char** error_ptr, bool ignoreCase = false, bool multiline = false); -#endif - - static void compileGetByIdSelf(Machine* machine, CallFrame* callFrame, CodeBlock* codeBlock, StructureID* structureID, size_t cachedOffset, void* returnAddress) - { - CTI cti(machine, callFrame, codeBlock); - cti.privateCompileGetByIdSelf(structureID, cachedOffset, returnAddress); - } - - static void compileGetByIdProto(Machine* machine, CallFrame* callFrame, CodeBlock* codeBlock, StructureID* structureID, StructureID* prototypeStructureID, size_t cachedOffset, void* returnAddress) - { - CTI cti(machine, callFrame, codeBlock); - cti.privateCompileGetByIdProto(structureID, prototypeStructureID, cachedOffset, returnAddress); - } - - static void compileGetByIdChain(Machine* machine, CallFrame* callFrame, CodeBlock* codeBlock, StructureID* structureID, StructureIDChain* chain, size_t count, size_t cachedOffset, void* returnAddress) - { - CTI cti(machine, callFrame, codeBlock); - cti.privateCompileGetByIdChain(structureID, chain, count, cachedOffset, returnAddress); - } - - static void compilePutByIdReplace(Machine* machine, CallFrame* callFrame, CodeBlock* codeBlock, StructureID* structureID, size_t cachedOffset, void* returnAddress) - { - CTI cti(machine, callFrame, codeBlock); - cti.privateCompilePutByIdReplace(structureID, cachedOffset, returnAddress); - } - - static void compilePutByIdTransition(Machine* machine, CallFrame* callFrame, CodeBlock* codeBlock, StructureID* oldStructureID, StructureID* newStructureID, size_t cachedOffset, StructureIDChain* sIDC, void* returnAddress) - { - CTI cti(machine, callFrame, codeBlock); - cti.privateCompilePutByIdTransition(oldStructureID, newStructureID, cachedOffset, sIDC, returnAddress); - } - - static void* compileArrayLengthTrampoline(Machine* machine, CallFrame* callFrame, CodeBlock* codeBlock) - { - CTI cti(machine, callFrame, codeBlock); - return cti.privateCompileArrayLengthTrampoline(); - } - - static void* compileStringLengthTrampoline(Machine* machine, CallFrame* callFrame, CodeBlock* codeBlock) - { - CTI cti(machine, callFrame, codeBlock); - return cti.privateCompileStringLengthTrampoline(); - } - - static void patchGetByIdSelf(CodeBlock* codeBlock, StructureID* structureID, size_t cachedOffset, void* returnAddress); - static void patchPutByIdReplace(CodeBlock* codeBlock, StructureID* structureID, size_t cachedOffset, void* returnAddress); - - static void compilePatchGetArrayLength(Machine* machine, CallFrame* callFrame, CodeBlock* codeBlock, void* returnAddress) - { - CTI cti(machine, callFrame, codeBlock); - return cti.privateCompilePatchGetArrayLength(returnAddress); - } - - static void linkCall(JSFunction* callee, CodeBlock* calleeCodeBlock, void* ctiCode, CallLinkInfo* callLinkInfo, int callerArgCount); - static void unlinkCall(CallLinkInfo*); - - inline static JSValue* execute(void* code, RegisterFile* registerFile, CallFrame* callFrame, JSGlobalData* globalData, JSValue** exception) - { - return ctiTrampoline(code, registerFile, callFrame, exception, Profiler::enabledProfilerReference(), globalData); - } - - private: - CTI(Machine*, CallFrame*, CodeBlock*); - - static uintptr_t asInteger(JSValue*); - - bool isConstant(int src); - JSValue* getConstant(CallFrame*, int src); - - void privateCompileMainPass(); - void privateCompileLinkPass(); - void privateCompileSlowCases(); - void privateCompile(); - void privateCompileGetByIdSelf(StructureID*, size_t cachedOffset, void* returnAddress); - void privateCompileGetByIdProto(StructureID*, StructureID* prototypeStructureID, size_t cachedOffset, void* returnAddress); - void privateCompileGetByIdChain(StructureID*, StructureIDChain*, size_t count, size_t cachedOffset, void* returnAddress); - void privateCompilePutByIdReplace(StructureID*, size_t cachedOffset, void* returnAddress); - void privateCompilePutByIdTransition(StructureID*, StructureID*, size_t cachedOffset, StructureIDChain*, void* returnAddress); - - void* privateCompileArrayLengthTrampoline(); - void* privateCompileStringLengthTrampoline(); - void privateCompilePatchGetArrayLength(void* returnAddress); - - void compileOpCall(OpcodeID, Instruction* instruction, unsigned i, unsigned callLinkInfoIndex); - void compileOpCallInitializeCallFrame(unsigned callee, unsigned argCount); - void compileOpCallSetupArgs(Instruction* instruction, bool isConstruct, bool isEval); - enum CompileOpStrictEqType { OpStrictEq, OpNStrictEq }; - void compileOpStrictEq(Instruction* instruction, unsigned i, CompileOpStrictEqType type); - void putDoubleResultToJSNumberCellOrJSImmediate(X86::XMMRegisterID xmmSource, X86::RegisterID jsNumberCell, unsigned dst, X86Assembler::JmpSrc* wroteJSNumberCell, X86::XMMRegisterID tempXmm, X86::RegisterID tempReg1, X86::RegisterID tempReg2); - void compileBinaryArithOp(OpcodeID, unsigned dst, unsigned src1, unsigned src2, OperandTypes opi, unsigned i); - void compileBinaryArithOpSlowCase(Instruction*, OpcodeID, Vector<SlowCaseEntry>::iterator& iter, unsigned dst, unsigned src1, unsigned src2, OperandTypes opi, unsigned i); - - void emitGetArg(int src, X86Assembler::RegisterID dst); - void emitGetPutArg(unsigned src, unsigned offset, X86Assembler::RegisterID scratch); - void emitPutArg(X86Assembler::RegisterID src, unsigned offset); - void emitPutArgConstant(unsigned value, unsigned offset); - void emitPutResult(unsigned dst, X86Assembler::RegisterID from = X86::eax); - - void emitInitRegister(unsigned dst); - - void emitPutCTIParam(void* value, unsigned name); - void emitPutCTIParam(X86Assembler::RegisterID from, unsigned name); - void emitGetCTIParam(unsigned name, X86Assembler::RegisterID to); - - void emitPutToCallFrameHeader(X86Assembler::RegisterID from, RegisterFile::CallFrameHeaderEntry entry); - void emitGetFromCallFrameHeader(RegisterFile::CallFrameHeaderEntry entry, X86Assembler::RegisterID to); - - JSValue* getConstantImmediateNumericArg(unsigned src); - unsigned getDeTaggedConstantImmediate(JSValue* imm); - - void emitJumpSlowCaseIfIsJSCell(X86Assembler::RegisterID reg, unsigned opcodeIndex); - void emitJumpSlowCaseIfNotJSCell(X86Assembler::RegisterID reg, unsigned opcodeIndex); - - void emitJumpSlowCaseIfNotImmNum(X86Assembler::RegisterID, unsigned opcodeIndex); - void emitJumpSlowCaseIfNotImmNums(X86Assembler::RegisterID, X86Assembler::RegisterID, unsigned opcodeIndex); - - void emitFastArithDeTagImmediate(X86Assembler::RegisterID); - X86Assembler::JmpSrc emitFastArithDeTagImmediateJumpIfZero(X86Assembler::RegisterID); - void emitFastArithReTagImmediate(X86Assembler::RegisterID); - void emitFastArithPotentiallyReTagImmediate(X86Assembler::RegisterID); - void emitFastArithImmToInt(X86Assembler::RegisterID); - void emitFastArithIntToImmOrSlowCase(X86Assembler::RegisterID, unsigned opcodeIndex); - void emitFastArithIntToImmNoCheck(X86Assembler::RegisterID); - X86Assembler::JmpSrc emitArithIntToImmWithJump(X86Assembler::RegisterID reg); - - void emitTagAsBoolImmediate(X86Assembler::RegisterID reg); - - void emitAllocateNumber(JSGlobalData*, unsigned); - - X86Assembler::JmpSrc emitNakedCall(unsigned opcodeIndex, X86::RegisterID); - X86Assembler::JmpSrc emitNakedCall(unsigned opcodeIndex, void(*function)()); - X86Assembler::JmpSrc emitNakedFastCall(unsigned opcodeIndex, void*); - X86Assembler::JmpSrc emitCTICall(Instruction*, unsigned opcodeIndex, CTIHelper_j); - X86Assembler::JmpSrc emitCTICall(Instruction*, unsigned opcodeIndex, CTIHelper_o); - X86Assembler::JmpSrc emitCTICall(Instruction*, unsigned opcodeIndex, CTIHelper_p); - X86Assembler::JmpSrc emitCTICall(Instruction*, unsigned opcodeIndex, CTIHelper_v); - X86Assembler::JmpSrc emitCTICall(Instruction*, unsigned opcodeIndex, CTIHelper_s); - X86Assembler::JmpSrc emitCTICall(Instruction*, unsigned opcodeIndex, CTIHelper_b); - X86Assembler::JmpSrc emitCTICall(Instruction*, unsigned opcodeIndex, CTIHelper_2); - - void emitGetVariableObjectRegister(X86Assembler::RegisterID variableObject, int index, X86Assembler::RegisterID dst); - void emitPutVariableObjectRegister(X86Assembler::RegisterID src, X86Assembler::RegisterID variableObject, int index); - - void emitSlowScriptCheck(Instruction*, unsigned opcodeIndex); -#ifndef NDEBUG - void printOpcodeOperandTypes(unsigned src1, unsigned src2); -#endif - - X86Assembler m_jit; - Machine* m_machine; - CallFrame* m_callFrame; - CodeBlock* m_codeBlock; - - Vector<CallRecord> m_calls; - Vector<X86Assembler::JmpDst> m_labels; - Vector<StructureStubCompilationInfo> m_propertyAccessCompilationInfo; - Vector<StructureStubCompilationInfo> m_callStructureStubCompilationInfo; - Vector<JmpTable> m_jmpTable; - - struct JSRInfo { - X86Assembler::JmpDst addrPosition; - X86Assembler::JmpDst target; - - JSRInfo(const X86Assembler::JmpDst& storeLocation, const X86Assembler::JmpDst& targetLocation) - : addrPosition(storeLocation) - , target(targetLocation) - { - } - }; - - Vector<JSRInfo> m_jsrSites; - Vector<SlowCaseEntry> m_slowCases; - Vector<SwitchRecord> m_switches; - - // This limit comes from the limit set in PCRE - static const int MaxPatternSize = (1 << 16); - - }; -} - -#endif // ENABLE(CTI) - -#endif // CTI_h diff --git a/JavaScriptCore/VM/CodeBlock.cpp b/JavaScriptCore/VM/CodeBlock.cpp deleted file mode 100644 index 38ef598..0000000 --- a/JavaScriptCore/VM/CodeBlock.cpp +++ /dev/null @@ -1,1184 +0,0 @@ -/* - * Copyright (C) 2008 Apple Inc. All rights reserved. - * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca> - * - * 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 "CodeBlock.h" - -#include "CTI.h" -#include "JSValue.h" -#include "Machine.h" -#include "Debugger.h" -#include <stdio.h> -#include <wtf/StringExtras.h> - -namespace JSC { - -#if !defined(NDEBUG) || ENABLE(OPCODE_SAMPLING) - -static UString escapeQuotes(const UString& str) -{ - UString result = str; - int pos = 0; - while ((pos = result.find('\"', pos)) >= 0) { - result = result.substr(0, pos) + "\"\\\"\"" + result.substr(pos + 1); - pos += 4; - } - return result; -} - -static UString valueToSourceString(ExecState* exec, JSValue* val) -{ - if (val->isString()) { - UString result("\""); - result += escapeQuotes(val->toString(exec)) + "\""; - return result; - } - - return val->toString(exec); -} - -static CString registerName(int r) -{ - if (r == missingThisObjectMarker()) - return "<null>"; - - return (UString("r") + UString::from(r)).UTF8String(); -} - -static CString constantName(ExecState* exec, int k, JSValue* value) -{ - return (valueToSourceString(exec, value) + "(@k" + UString::from(k) + ")").UTF8String(); -} - -static CString idName(int id0, const Identifier& ident) -{ - return (ident.ustring() + "(@id" + UString::from(id0) +")").UTF8String(); -} - -static UString regexpToSourceString(RegExp* regExp) -{ - UString pattern = UString("/") + regExp->pattern() + "/"; - if (regExp->global()) - pattern += "g"; - if (regExp->ignoreCase()) - pattern += "i"; - if (regExp->multiline()) - pattern += "m"; - - return pattern; -} - -static CString regexpName(int re, RegExp* regexp) -{ - return (regexpToSourceString(regexp) + "(@re" + UString::from(re) + ")").UTF8String(); -} - -static UString pointerToSourceString(void* p) -{ - char buffer[2 + 2 * sizeof(void*) + 1]; // 0x [two characters per byte] \0 - snprintf(buffer, sizeof(buffer), "%p", p); - return buffer; -} - -NEVER_INLINE static const char* debugHookName(int debugHookID) -{ - switch (static_cast<DebugHookID>(debugHookID)) { - case DidEnterCallFrame: - return "didEnterCallFrame"; - case WillLeaveCallFrame: - return "willLeaveCallFrame"; - case WillExecuteStatement: - return "willExecuteStatement"; - case WillExecuteProgram: - return "willExecuteProgram"; - case DidExecuteProgram: - return "didExecuteProgram"; - case DidReachBreakpoint: - return "didReachBreakpoint"; - } - - ASSERT_NOT_REACHED(); - return ""; -} - -static int jumpTarget(const Vector<Instruction>::const_iterator& begin, Vector<Instruction>::const_iterator& it, int offset) -{ - return it - begin + offset; -} - -static void printUnaryOp(int location, Vector<Instruction>::const_iterator& it, const char* op) -{ - int r0 = (++it)->u.operand; - int r1 = (++it)->u.operand; - - printf("[%4d] %s\t\t %s, %s\n", location, op, registerName(r0).c_str(), registerName(r1).c_str()); -} - -static void printBinaryOp(int location, Vector<Instruction>::const_iterator& it, const char* op) -{ - int r0 = (++it)->u.operand; - int r1 = (++it)->u.operand; - int r2 = (++it)->u.operand; - printf("[%4d] %s\t\t %s, %s, %s\n", location, op, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str()); -} - -static void printConditionalJump(const Vector<Instruction>::const_iterator& begin, Vector<Instruction>::const_iterator& it, int location, const char* op) -{ - int r0 = (++it)->u.operand; - int offset = (++it)->u.operand; - printf("[%4d] %s\t\t %s, %d(->%d)\n", location, op, registerName(r0).c_str(), offset, jumpTarget(begin, it, offset)); -} - -static void printGetByIdOp(int location, Vector<Instruction>::const_iterator& it, const Vector<Identifier>& identifiers, const char* op) -{ - int r0 = (++it)->u.operand; - int r1 = (++it)->u.operand; - int id0 = (++it)->u.operand; - printf("[%4d] %s\t %s, %s, %s\n", location, op, registerName(r0).c_str(), registerName(r1).c_str(), idName(id0, identifiers[id0]).c_str()); - it += 4; -} - -static void printPutByIdOp(int location, Vector<Instruction>::const_iterator& it, const Vector<Identifier>& identifiers, const char* op) -{ - int r0 = (++it)->u.operand; - int id0 = (++it)->u.operand; - int r1 = (++it)->u.operand; - printf("[%4d] %s\t %s, %s, %s\n", location, op, registerName(r0).c_str(), idName(id0, identifiers[id0]).c_str(), registerName(r1).c_str()); - it += 4; -} - -void CodeBlock::printStructureID(const char* name, const Instruction* vPC, int operand) const -{ - unsigned instructionOffset = vPC - instructions.begin(); - printf(" [%4d] %s: %s\n", instructionOffset, name, pointerToSourceString(vPC[operand].u.structureID).UTF8String().c_str()); -} - -void CodeBlock::printStructureIDs(const Instruction* vPC) const -{ - Machine* machine = globalData->machine; - unsigned instructionOffset = vPC - instructions.begin(); - - if (vPC[0].u.opcode == machine->getOpcode(op_get_by_id)) { - printStructureID("get_by_id", vPC, 4); - return; - } - if (vPC[0].u.opcode == machine->getOpcode(op_get_by_id_self)) { - printStructureID("get_by_id_self", vPC, 4); - return; - } - if (vPC[0].u.opcode == machine->getOpcode(op_get_by_id_proto)) { - printf(" [%4d] %s: %s, %s\n", instructionOffset, "get_by_id_proto", pointerToSourceString(vPC[4].u.structureID).UTF8String().c_str(), pointerToSourceString(vPC[5].u.structureID).UTF8String().c_str()); - return; - } - if (vPC[0].u.opcode == machine->getOpcode(op_put_by_id_transition)) { - printf(" [%4d] %s: %s, %s, %s\n", instructionOffset, "put_by_id_new", pointerToSourceString(vPC[4].u.structureID).UTF8String().c_str(), pointerToSourceString(vPC[5].u.structureID).UTF8String().c_str(), pointerToSourceString(vPC[6].u.structureIDChain).UTF8String().c_str()); - return; - } - if (vPC[0].u.opcode == machine->getOpcode(op_get_by_id_chain)) { - printf(" [%4d] %s: %s, %s\n", instructionOffset, "get_by_id_chain", pointerToSourceString(vPC[4].u.structureID).UTF8String().c_str(), pointerToSourceString(vPC[5].u.structureIDChain).UTF8String().c_str()); - return; - } - if (vPC[0].u.opcode == machine->getOpcode(op_put_by_id)) { - printStructureID("put_by_id", vPC, 4); - return; - } - if (vPC[0].u.opcode == machine->getOpcode(op_put_by_id_replace)) { - printStructureID("put_by_id_replace", vPC, 4); - return; - } - if (vPC[0].u.opcode == machine->getOpcode(op_resolve_global)) { - printStructureID("resolve_global", vPC, 4); - return; - } - - // These instructions doesn't ref StructureIDs. - ASSERT(vPC[0].u.opcode == machine->getOpcode(op_get_by_id_generic) || vPC[0].u.opcode == machine->getOpcode(op_put_by_id_generic) || vPC[0].u.opcode == machine->getOpcode(op_call) || vPC[0].u.opcode == machine->getOpcode(op_call_eval) || vPC[0].u.opcode == machine->getOpcode(op_construct)); -} - -void CodeBlock::dump(ExecState* exec) const -{ - Vector<Instruction>::const_iterator begin = instructions.begin(); - Vector<Instruction>::const_iterator end = instructions.end(); - - size_t instructionCount = 0; - for (Vector<Instruction>::const_iterator it = begin; it != end; ++it) - if (exec->machine()->isOpcode(it->u.opcode)) - ++instructionCount; - - printf("%lu instructions; %lu bytes at %p; %d parameter(s); %d callee register(s)\n\n", - static_cast<unsigned long>(instructionCount), - static_cast<unsigned long>(instructions.size() * sizeof(Instruction)), - this, numParameters, numCalleeRegisters); - - for (Vector<Instruction>::const_iterator it = begin; it != end; ++it) - dump(exec, begin, it); - - if (identifiers.size()) { - printf("\nIdentifiers:\n"); - size_t i = 0; - do { - printf(" id%u = %s\n", static_cast<unsigned>(i), identifiers[i].ascii()); - ++i; - } while (i != identifiers.size()); - } - - if (constantRegisters.size()) { - printf("\nConstants:\n"); - unsigned registerIndex = numVars; - size_t i = 0; - do { - printf(" r%u = %s\n", registerIndex, valueToSourceString(exec, constantRegisters[i].jsValue(exec)).ascii()); - ++i; - ++registerIndex; - } while (i < constantRegisters.size()); - } - - if (unexpectedConstants.size()) { - printf("\nUnexpected Constants:\n"); - size_t i = 0; - do { - printf(" k%u = %s\n", static_cast<unsigned>(i), valueToSourceString(exec, unexpectedConstants[i]).ascii()); - ++i; - } while (i < unexpectedConstants.size()); - } - - if (regexps.size()) { - printf("\nRegExps:\n"); - size_t i = 0; - do { - printf(" re%u = %s\n", static_cast<unsigned>(i), regexpToSourceString(regexps[i].get()).ascii()); - ++i; - } while (i < regexps.size()); - } - - if (globalResolveInstructions.size() || propertyAccessInstructions.size()) - printf("\nStructureIDs:\n"); - - if (globalResolveInstructions.size()) { - size_t i = 0; - do { - printStructureIDs(&instructions[globalResolveInstructions[i]]); - ++i; - } while (i < globalResolveInstructions.size()); - } - if (propertyAccessInstructions.size()) { - size_t i = 0; - do { - printStructureIDs(&instructions[propertyAccessInstructions[i].opcodeIndex]); - ++i; - } while (i < propertyAccessInstructions.size()); - } - - if (exceptionHandlers.size()) { - printf("\nException Handlers:\n"); - unsigned i = 0; - do { - printf("\t %d: { start: [%4d] end: [%4d] target: [%4d] }\n", i + 1, exceptionHandlers[i].start, exceptionHandlers[i].end, exceptionHandlers[i].target); - ++i; - } while (i < exceptionHandlers.size()); - } - - if (immediateSwitchJumpTables.size()) { - printf("Immediate Switch Jump Tables:\n"); - unsigned i = 0; - do { - printf(" %1d = {\n", i); - int entry = 0; - Vector<int32_t>::const_iterator end = immediateSwitchJumpTables[i].branchOffsets.end(); - for (Vector<int32_t>::const_iterator iter = immediateSwitchJumpTables[i].branchOffsets.begin(); iter != end; ++iter, ++entry) { - if (!*iter) - continue; - printf("\t\t%4d => %04d\n", entry + immediateSwitchJumpTables[i].min, *iter); - } - printf(" }\n"); - ++i; - } while (i < immediateSwitchJumpTables.size()); - } - - if (characterSwitchJumpTables.size()) { - printf("\nCharacter Switch Jump Tables:\n"); - unsigned i = 0; - do { - printf(" %1d = {\n", i); - int entry = 0; - Vector<int32_t>::const_iterator end = characterSwitchJumpTables[i].branchOffsets.end(); - for (Vector<int32_t>::const_iterator iter = characterSwitchJumpTables[i].branchOffsets.begin(); iter != end; ++iter, ++entry) { - if (!*iter) - continue; - ASSERT(!((i + characterSwitchJumpTables[i].min) & ~0xFFFF)); - UChar ch = static_cast<UChar>(entry + characterSwitchJumpTables[i].min); - printf("\t\t\"%s\" => %04d\n", UString(&ch, 1).ascii(), *iter); - } - printf(" }\n"); - ++i; - } while (i < characterSwitchJumpTables.size()); - } - - if (stringSwitchJumpTables.size()) { - printf("\nString Switch Jump Tables:\n"); - unsigned i = 0; - do { - printf(" %1d = {\n", i); - StringJumpTable::StringOffsetTable::const_iterator end = stringSwitchJumpTables[i].offsetTable.end(); - for (StringJumpTable::StringOffsetTable::const_iterator iter = stringSwitchJumpTables[i].offsetTable.begin(); iter != end; ++iter) - printf("\t\t\"%s\" => %04d\n", UString(iter->first).ascii(), iter->second.branchOffset); - printf(" }\n"); - ++i; - } while (i < stringSwitchJumpTables.size()); - } - - printf("\n"); -} - -void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& begin, Vector<Instruction>::const_iterator& it) const -{ - int location = it - begin; - switch (exec->machine()->getOpcodeID(it->u.opcode)) { - case op_enter: { - printf("[%4d] enter\n", location); - break; - } - case op_enter_with_activation: { - int r0 = (++it)->u.operand; - printf("[%4d] enter_with_activation %s\n", location, registerName(r0).c_str()); - break; - } - case op_create_arguments: { - printf("[%4d] create_arguments\n", location); - break; - } - case op_convert_this: { - int r0 = (++it)->u.operand; - printf("[%4d] convert_this %s\n", location, registerName(r0).c_str()); - break; - } - case op_unexpected_load: { - int r0 = (++it)->u.operand; - int k0 = (++it)->u.operand; - printf("[%4d] unexpected_load\t %s, %s\n", location, registerName(r0).c_str(), constantName(exec, k0, unexpectedConstants[k0]).c_str()); - break; - } - case op_new_object: { - int r0 = (++it)->u.operand; - printf("[%4d] new_object\t %s\n", location, registerName(r0).c_str()); - break; - } - case op_new_array: { - int dst = (++it)->u.operand; - int argv = (++it)->u.operand; - int argc = (++it)->u.operand; - printf("[%4d] new_array\t %s, %s, %d\n", location, registerName(dst).c_str(), registerName(argv).c_str(), argc); - break; - } - case op_new_regexp: { - int r0 = (++it)->u.operand; - int re0 = (++it)->u.operand; - printf("[%4d] new_regexp\t %s, %s\n", location, registerName(r0).c_str(), regexpName(re0, regexps[re0].get()).c_str()); - break; - } - case op_mov: { - int r0 = (++it)->u.operand; - int r1 = (++it)->u.operand; - printf("[%4d] mov\t\t %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str()); - break; - } - case op_not: { - printUnaryOp(location, it, "not"); - break; - } - case op_eq: { - printBinaryOp(location, it, "eq"); - break; - } - case op_eq_null: { - printUnaryOp(location, it, "eq_null"); - break; - } - case op_neq: { - printBinaryOp(location, it, "neq"); - break; - } - case op_neq_null: { - printUnaryOp(location, it, "neq_null"); - break; - } - case op_stricteq: { - printBinaryOp(location, it, "stricteq"); - break; - } - case op_nstricteq: { - printBinaryOp(location, it, "nstricteq"); - break; - } - case op_less: { - printBinaryOp(location, it, "less"); - break; - } - case op_lesseq: { - printBinaryOp(location, it, "lesseq"); - break; - } - case op_pre_inc: { - int r0 = (++it)->u.operand; - printf("[%4d] pre_inc\t\t %s\n", location, registerName(r0).c_str()); - break; - } - case op_pre_dec: { - int r0 = (++it)->u.operand; - printf("[%4d] pre_dec\t\t %s\n", location, registerName(r0).c_str()); - break; - } - case op_post_inc: { - printUnaryOp(location, it, "post_inc"); - break; - } - case op_post_dec: { - printUnaryOp(location, it, "post_dec"); - break; - } - case op_to_jsnumber: { - printUnaryOp(location, it, "to_jsnumber"); - break; - } - case op_negate: { - printUnaryOp(location, it, "negate"); - ++it; - break; - } - case op_add: { - printBinaryOp(location, it, "add"); - ++it; - break; - } - case op_mul: { - printBinaryOp(location, it, "mul"); - ++it; - break; - } - case op_div: { - printBinaryOp(location, it, "div"); - break; - } - case op_mod: { - printBinaryOp(location, it, "mod"); - break; - } - case op_sub: { - printBinaryOp(location, it, "sub"); - ++it; - break; - } - case op_lshift: { - printBinaryOp(location, it, "lshift"); - break; - } - case op_rshift: { - printBinaryOp(location, it, "rshift"); - break; - } - case op_urshift: { - printBinaryOp(location, it, "urshift"); - break; - } - case op_bitand: { - printBinaryOp(location, it, "bitand"); - ++it; - break; - } - case op_bitxor: { - printBinaryOp(location, it, "bitxor"); - ++it; - break; - } - case op_bitor: { - printBinaryOp(location, it, "bitor"); - ++it; - break; - } - case op_bitnot: { - printUnaryOp(location, it, "bitnot"); - break; - } - case op_instanceof: { - int r0 = (++it)->u.operand; - int r1 = (++it)->u.operand; - int r2 = (++it)->u.operand; - int r3 = (++it)->u.operand; - printf("[%4d] instanceof\t\t %s, %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str(), registerName(r3).c_str()); - break; - } - case op_typeof: { - printUnaryOp(location, it, "typeof"); - break; - } - case op_is_undefined: { - printUnaryOp(location, it, "is_undefined"); - break; - } - case op_is_boolean: { - printUnaryOp(location, it, "is_boolean"); - break; - } - case op_is_number: { - printUnaryOp(location, it, "is_number"); - break; - } - case op_is_string: { - printUnaryOp(location, it, "is_string"); - break; - } - case op_is_object: { - printUnaryOp(location, it, "is_object"); - break; - } - case op_is_function: { - printUnaryOp(location, it, "is_function"); - break; - } - case op_in: { - printBinaryOp(location, it, "in"); - break; - } - case op_resolve: { - int r0 = (++it)->u.operand; - int id0 = (++it)->u.operand; - printf("[%4d] resolve\t\t %s, %s\n", location, registerName(r0).c_str(), idName(id0, identifiers[id0]).c_str()); - break; - } - case op_resolve_skip: { - int r0 = (++it)->u.operand; - int id0 = (++it)->u.operand; - int skipLevels = (++it)->u.operand; - printf("[%4d] resolve_skip\t %s, %s, %d\n", location, registerName(r0).c_str(), idName(id0, identifiers[id0]).c_str(), skipLevels); - break; - } - case op_resolve_global: { - int r0 = (++it)->u.operand; - JSValue* scope = static_cast<JSValue*>((++it)->u.jsCell); - int id0 = (++it)->u.operand; - printf("[%4d] resolve_global\t %s, %s, %s\n", location, registerName(r0).c_str(), valueToSourceString(exec, scope).ascii(), idName(id0, identifiers[id0]).c_str()); - it += 2; - break; - } - case op_get_scoped_var: { - int r0 = (++it)->u.operand; - int index = (++it)->u.operand; - int skipLevels = (++it)->u.operand; - printf("[%4d] get_scoped_var\t %s, %d, %d\n", location, registerName(r0).c_str(), index, skipLevels); - break; - } - case op_put_scoped_var: { - int index = (++it)->u.operand; - int skipLevels = (++it)->u.operand; - int r0 = (++it)->u.operand; - printf("[%4d] put_scoped_var\t %d, %d, %s\n", location, index, skipLevels, registerName(r0).c_str()); - break; - } - case op_get_global_var: { - int r0 = (++it)->u.operand; - JSValue* scope = static_cast<JSValue*>((++it)->u.jsCell); - int index = (++it)->u.operand; - printf("[%4d] get_global_var\t %s, %s, %d\n", location, registerName(r0).c_str(), valueToSourceString(exec, scope).ascii(), index); - break; - } - case op_put_global_var: { - JSValue* scope = static_cast<JSValue*>((++it)->u.jsCell); - int index = (++it)->u.operand; - int r0 = (++it)->u.operand; - printf("[%4d] put_global_var\t %s, %d, %s\n", location, valueToSourceString(exec, scope).ascii(), index, registerName(r0).c_str()); - break; - } - case op_resolve_base: { - int r0 = (++it)->u.operand; - int id0 = (++it)->u.operand; - printf("[%4d] resolve_base\t %s, %s\n", location, registerName(r0).c_str(), idName(id0, identifiers[id0]).c_str()); - break; - } - case op_resolve_with_base: { - int r0 = (++it)->u.operand; - int r1 = (++it)->u.operand; - int id0 = (++it)->u.operand; - printf("[%4d] resolve_with_base %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), idName(id0, identifiers[id0]).c_str()); - break; - } - case op_resolve_func: { - int r0 = (++it)->u.operand; - int r1 = (++it)->u.operand; - int id0 = (++it)->u.operand; - printf("[%4d] resolve_func\t %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), idName(id0, identifiers[id0]).c_str()); - break; - } - case op_get_by_id: { - printGetByIdOp(location, it, identifiers, "get_by_id"); - break; - } - case op_get_by_id_self: { - printGetByIdOp(location, it, identifiers, "get_by_id_self"); - break; - } - case op_get_by_id_proto: { - printGetByIdOp(location, it, identifiers, "get_by_id_proto"); - break; - } - case op_get_by_id_chain: { - printGetByIdOp(location, it, identifiers, "get_by_id_chain"); - break; - } - case op_get_by_id_generic: { - printGetByIdOp(location, it, identifiers, "get_by_id_generic"); - break; - } - case op_get_array_length: { - printGetByIdOp(location, it, identifiers, "get_array_length"); - break; - } - case op_get_string_length: { - printGetByIdOp(location, it, identifiers, "get_string_length"); - break; - } - case op_put_by_id: { - printPutByIdOp(location, it, identifiers, "put_by_id"); - break; - } - case op_put_by_id_replace: { - printPutByIdOp(location, it, identifiers, "put_by_id_replace"); - break; - } - case op_put_by_id_transition: { - printPutByIdOp(location, it, identifiers, "put_by_id_transition"); - break; - } - case op_put_by_id_generic: { - printPutByIdOp(location, it, identifiers, "put_by_id_generic"); - break; - } - case op_put_getter: { - int r0 = (++it)->u.operand; - int id0 = (++it)->u.operand; - int r1 = (++it)->u.operand; - printf("[%4d] put_getter\t %s, %s, %s\n", location, registerName(r0).c_str(), idName(id0, identifiers[id0]).c_str(), registerName(r1).c_str()); - break; - } - case op_put_setter: { - int r0 = (++it)->u.operand; - int id0 = (++it)->u.operand; - int r1 = (++it)->u.operand; - printf("[%4d] put_setter\t %s, %s, %s\n", location, registerName(r0).c_str(), idName(id0, identifiers[id0]).c_str(), registerName(r1).c_str()); - break; - } - case op_del_by_id: { - int r0 = (++it)->u.operand; - int r1 = (++it)->u.operand; - int id0 = (++it)->u.operand; - printf("[%4d] del_by_id\t %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), idName(id0, identifiers[id0]).c_str()); - break; - } - case op_get_by_val: { - int r0 = (++it)->u.operand; - int r1 = (++it)->u.operand; - int r2 = (++it)->u.operand; - printf("[%4d] get_by_val\t %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str()); - break; - } - case op_put_by_val: { - int r0 = (++it)->u.operand; - int r1 = (++it)->u.operand; - int r2 = (++it)->u.operand; - printf("[%4d] put_by_val\t %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str()); - break; - } - case op_del_by_val: { - int r0 = (++it)->u.operand; - int r1 = (++it)->u.operand; - int r2 = (++it)->u.operand; - printf("[%4d] del_by_val\t %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str()); - break; - } - case op_put_by_index: { - int r0 = (++it)->u.operand; - unsigned n0 = (++it)->u.operand; - int r1 = (++it)->u.operand; - printf("[%4d] put_by_index\t %s, %u, %s\n", location, registerName(r0).c_str(), n0, registerName(r1).c_str()); - break; - } - case op_jmp: { - int offset = (++it)->u.operand; - printf("[%4d] jmp\t\t %d(->%d)\n", location, offset, jumpTarget(begin, it, offset)); - break; - } - case op_loop: { - int offset = (++it)->u.operand; - printf("[%4d] loop\t\t %d(->%d)\n", location, offset, jumpTarget(begin, it, offset)); - break; - } - case op_jtrue: { - printConditionalJump(begin, it, location, "jtrue"); - break; - } - case op_loop_if_true: { - printConditionalJump(begin, it, location, "loop_if_true"); - break; - } - case op_jfalse: { - printConditionalJump(begin, it, location, "jfalse"); - break; - } - case op_jeq_null: { - printConditionalJump(begin, it, location, "jeq_null"); - break; - } - case op_jneq_null: { - printConditionalJump(begin, it, location, "jneq_null"); - break; - } - case op_jnless: { - int r0 = (++it)->u.operand; - int r1 = (++it)->u.operand; - int offset = (++it)->u.operand; - printf("[%4d] jnless\t\t %s, %s, %d(->%d)\n", location, registerName(r0).c_str(), registerName(r1).c_str(), offset, jumpTarget(begin, it, offset)); - break; - } - case op_loop_if_less: { - int r0 = (++it)->u.operand; - int r1 = (++it)->u.operand; - int offset = (++it)->u.operand; - printf("[%4d] loop_if_less\t %s, %s, %d(->%d)\n", location, registerName(r0).c_str(), registerName(r1).c_str(), offset, jumpTarget(begin, it, offset)); - break; - } - case op_loop_if_lesseq: { - int r0 = (++it)->u.operand; - int r1 = (++it)->u.operand; - int offset = (++it)->u.operand; - printf("[%4d] loop_if_lesseq\t %s, %s, %d(->%d)\n", location, registerName(r0).c_str(), registerName(r1).c_str(), offset, jumpTarget(begin, it, offset)); - break; - } - case op_switch_imm: { - int tableIndex = (++it)->u.operand; - int defaultTarget = (++it)->u.operand; - int scrutineeRegister = (++it)->u.operand; - printf("[%4d] switch_imm\t %d, %d(->%d), %s\n", location, tableIndex, defaultTarget, jumpTarget(begin, it, defaultTarget), registerName(scrutineeRegister).c_str()); - break; - } - case op_switch_char: { - int tableIndex = (++it)->u.operand; - int defaultTarget = (++it)->u.operand; - int scrutineeRegister = (++it)->u.operand; - printf("[%4d] switch_char\t %d, %d(->%d), %s\n", location, tableIndex, defaultTarget, jumpTarget(begin, it, defaultTarget), registerName(scrutineeRegister).c_str()); - break; - } - case op_switch_string: { - int tableIndex = (++it)->u.operand; - int defaultTarget = (++it)->u.operand; - int scrutineeRegister = (++it)->u.operand; - printf("[%4d] switch_string\t %d, %d(->%d), %s\n", location, tableIndex, defaultTarget, jumpTarget(begin, it, defaultTarget), registerName(scrutineeRegister).c_str()); - break; - } - case op_new_func: { - int r0 = (++it)->u.operand; - int f0 = (++it)->u.operand; - printf("[%4d] new_func\t\t %s, f%d\n", location, registerName(r0).c_str(), f0); - break; - } - case op_new_func_exp: { - int r0 = (++it)->u.operand; - int f0 = (++it)->u.operand; - printf("[%4d] new_func_exp\t %s, f%d\n", location, registerName(r0).c_str(), f0); - break; - } - case op_call: { - int r0 = (++it)->u.operand; - int r1 = (++it)->u.operand; - int r2 = (++it)->u.operand; - int tempCount = (++it)->u.operand; - int argCount = (++it)->u.operand; - int registerOffset = (++it)->u.operand; - printf("[%4d] call\t\t %s, %s, %s, %d, %d, %d\n", location, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str(), tempCount, argCount, registerOffset); - break; - } - case op_call_eval: { - int r0 = (++it)->u.operand; - int r1 = (++it)->u.operand; - int r2 = (++it)->u.operand; - int tempCount = (++it)->u.operand; - int argCount = (++it)->u.operand; - int registerOffset = (++it)->u.operand; - printf("[%4d] call_eval\t\t %s, %s, %s, %d, %d, %d\n", location, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str(), tempCount, argCount, registerOffset); - break; - } - case op_tear_off_activation: { - int r0 = (++it)->u.operand; - printf("[%4d] tear_off_activation\t %s\n", location, registerName(r0).c_str()); - break; - } - case op_tear_off_arguments: { - printf("[%4d] tear_off_arguments\n", location); - break; - } - case op_ret: { - int r0 = (++it)->u.operand; - printf("[%4d] ret\t\t %s\n", location, registerName(r0).c_str()); - break; - } - case op_construct: { - int r0 = (++it)->u.operand; - int r1 = (++it)->u.operand; - int r2 = (++it)->u.operand; - int tempCount = (++it)->u.operand; - int argCount = (++it)->u.operand; - int registerOffset = (++it)->u.operand; - printf("[%4d] construct\t %s, %s, %s, %d, %d, %d\n", location, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str(), tempCount, argCount, registerOffset); - break; - } - case op_construct_verify: { - int r0 = (++it)->u.operand; - int r1 = (++it)->u.operand; - printf("[%4d] construct_verify\t %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str()); - break; - } - case op_get_pnames: { - int r0 = (++it)->u.operand; - int r1 = (++it)->u.operand; - printf("[%4d] get_pnames\t %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str()); - break; - } - case op_next_pname: { - int dest = (++it)->u.operand; - int iter = (++it)->u.operand; - int offset = (++it)->u.operand; - printf("[%4d] next_pname\t %s, %s, %d(->%d)\n", location, registerName(dest).c_str(), registerName(iter).c_str(), offset, jumpTarget(begin, it, offset)); - break; - } - case op_push_scope: { - int r0 = (++it)->u.operand; - printf("[%4d] push_scope\t %s\n", location, registerName(r0).c_str()); - break; - } - case op_pop_scope: { - printf("[%4d] pop_scope\n", location); - break; - } - case op_push_new_scope: { - int r0 = (++it)->u.operand; - int id0 = (++it)->u.operand; - int r1 = (++it)->u.operand; - printf("[%4d] push_new_scope \t%s, %s, %s\n", location, registerName(r0).c_str(), idName(id0, identifiers[id0]).c_str(), registerName(r1).c_str()); - break; - } - case op_jmp_scopes: { - int scopeDelta = (++it)->u.operand; - int offset = (++it)->u.operand; - printf("[%4d] jmp_scopes\t^%d, %d(->%d)\n", location, scopeDelta, offset, jumpTarget(begin, it, offset)); - break; - } - case op_catch: { - int r0 = (++it)->u.operand; - printf("[%4d] catch\t\t %s\n", location, registerName(r0).c_str()); - break; - } - case op_throw: { - int r0 = (++it)->u.operand; - printf("[%4d] throw\t\t %s\n", location, registerName(r0).c_str()); - break; - } - case op_new_error: { - int r0 = (++it)->u.operand; - int errorType = (++it)->u.operand; - int k0 = (++it)->u.operand; - printf("[%4d] new_error\t %s, %d, %s\n", location, registerName(r0).c_str(), errorType, constantName(exec, k0, unexpectedConstants[k0]).c_str()); - break; - } - case op_jsr: { - int retAddrDst = (++it)->u.operand; - int offset = (++it)->u.operand; - printf("[%4d] jsr\t\t %s, %d(->%d)\n", location, registerName(retAddrDst).c_str(), offset, jumpTarget(begin, it, offset)); - break; - } - case op_sret: { - int retAddrSrc = (++it)->u.operand; - printf("[%4d] sret\t\t %s\n", location, registerName(retAddrSrc).c_str()); - break; - } - case op_debug: { - int debugHookID = (++it)->u.operand; - int firstLine = (++it)->u.operand; - int lastLine = (++it)->u.operand; - printf("[%4d] debug\t\t %s, %d, %d\n", location, debugHookName(debugHookID), firstLine, lastLine); - break; - } - case op_profile_will_call: { - int function = (++it)->u.operand; - printf("[%4d] profile_will_call %s\n", location, registerName(function).c_str()); - break; - } - case op_profile_did_call: { - int function = (++it)->u.operand; - printf("[%4d] profile_did_call\t %s\n", location, registerName(function).c_str()); - break; - } - case op_end: { - int r0 = (++it)->u.operand; - printf("[%4d] end\t\t %s\n", location, registerName(r0).c_str()); - break; - } - } -} - -#endif // !defined(NDEBUG) || ENABLE(OPCODE_SAMPLING) - -CodeBlock::~CodeBlock() -{ - for (size_t size = globalResolveInstructions.size(), i = 0; i < size; ++i) { - derefStructureIDs(&instructions[globalResolveInstructions[i]]); - } - - for (size_t size = propertyAccessInstructions.size(), i = 0; i < size; ++i) { - derefStructureIDs(&instructions[propertyAccessInstructions[i].opcodeIndex]); - if (propertyAccessInstructions[i].stubRoutine) - WTF::fastFreeExecutable(propertyAccessInstructions[i].stubRoutine); - } - - for (size_t size = callLinkInfos.size(), i = 0; i < size; ++i) { - CallLinkInfo* callLinkInfo = &callLinkInfos[i]; - if (callLinkInfo->isLinked()) - callLinkInfo->callee->removeCaller(callLinkInfo); - } - -#if ENABLE(CTI) - unlinkCallers(); - - if (ctiCode) - WTF::fastFreeExecutable(ctiCode); -#endif -} - -#if ENABLE(CTI) -void CodeBlock::unlinkCallers() -{ - size_t size = linkedCallerList.size(); - for (size_t i = 0; i < size; ++i) { - CallLinkInfo* currentCaller = linkedCallerList[i]; - CTI::unlinkCall(currentCaller); - currentCaller->setUnlinked(); - } - linkedCallerList.clear(); -} -#endif - -void CodeBlock::derefStructureIDs(Instruction* vPC) const -{ - Machine* machine = globalData->machine; - - if (vPC[0].u.opcode == machine->getOpcode(op_get_by_id_self)) { - vPC[4].u.structureID->deref(); - return; - } - if (vPC[0].u.opcode == machine->getOpcode(op_get_by_id_proto)) { - vPC[4].u.structureID->deref(); - vPC[5].u.structureID->deref(); - return; - } - if (vPC[0].u.opcode == machine->getOpcode(op_get_by_id_chain)) { - vPC[4].u.structureID->deref(); - vPC[5].u.structureIDChain->deref(); - return; - } - if (vPC[0].u.opcode == machine->getOpcode(op_put_by_id_transition)) { - vPC[4].u.structureID->deref(); - vPC[5].u.structureID->deref(); - vPC[6].u.structureIDChain->deref(); - return; - } - if (vPC[0].u.opcode == machine->getOpcode(op_put_by_id_replace)) { - vPC[4].u.structureID->deref(); - return; - } - if (vPC[0].u.opcode == machine->getOpcode(op_resolve_global)) { - if(vPC[4].u.structureID) - vPC[4].u.structureID->deref(); - return; - } - - // These instructions don't ref their StructureIDs. - ASSERT(vPC[0].u.opcode == machine->getOpcode(op_get_by_id) || vPC[0].u.opcode == machine->getOpcode(op_put_by_id) || vPC[0].u.opcode == machine->getOpcode(op_get_by_id_generic) || vPC[0].u.opcode == machine->getOpcode(op_put_by_id_generic) || vPC[0].u.opcode == machine->getOpcode(op_get_array_length) || vPC[0].u.opcode == machine->getOpcode(op_get_string_length)); -} - -void CodeBlock::refStructureIDs(Instruction* vPC) const -{ - Machine* machine = globalData->machine; - - if (vPC[0].u.opcode == machine->getOpcode(op_get_by_id_self)) { - vPC[4].u.structureID->ref(); - return; - } - if (vPC[0].u.opcode == machine->getOpcode(op_get_by_id_proto)) { - vPC[4].u.structureID->ref(); - vPC[5].u.structureID->ref(); - return; - } - if (vPC[0].u.opcode == machine->getOpcode(op_get_by_id_chain)) { - vPC[4].u.structureID->ref(); - vPC[5].u.structureIDChain->ref(); - return; - } - if (vPC[0].u.opcode == machine->getOpcode(op_put_by_id_transition)) { - vPC[4].u.structureID->ref(); - vPC[5].u.structureID->ref(); - vPC[6].u.structureIDChain->ref(); - return; - } - if (vPC[0].u.opcode == machine->getOpcode(op_put_by_id_replace)) { - vPC[4].u.structureID->ref(); - return; - } - - // These instructions don't ref their StructureIDs. - ASSERT(vPC[0].u.opcode == machine->getOpcode(op_get_by_id) || vPC[0].u.opcode == machine->getOpcode(op_put_by_id) || vPC[0].u.opcode == machine->getOpcode(op_get_by_id_generic) || vPC[0].u.opcode == machine->getOpcode(op_put_by_id_generic)); -} - -void CodeBlock::mark() -{ - for (size_t i = 0; i < constantRegisters.size(); ++i) - if (!constantRegisters[i].marked()) - constantRegisters[i].mark(); - - for (size_t i = 0; i < unexpectedConstants.size(); ++i) - if (!unexpectedConstants[i]->marked()) - unexpectedConstants[i]->mark(); - - for (size_t i = 0; i < functions.size(); ++i) - functions[i]->body()->mark(); - - for (size_t i = 0; i < functionExpressions.size(); ++i) - functionExpressions[i]->body()->mark(); -} - -bool CodeBlock::getHandlerForVPC(const Instruction* vPC, Instruction*& target, int& scopeDepth) -{ - Vector<HandlerInfo>::iterator ptr = exceptionHandlers.begin(); - Vector<HandlerInfo>::iterator end = exceptionHandlers.end(); - unsigned addressOffset = vPC - instructions.begin(); - ASSERT(addressOffset < instructions.size()); - - for (; ptr != end; ++ptr) { - // Handlers are ordered innermost first, so the first handler we encounter - // that contains the source address is the correct handler to use. - if (ptr->start <= addressOffset && ptr->end >= addressOffset) { - scopeDepth = ptr->scopeDepth; - target = instructions.begin() + ptr->target; - return true; - } - } - return false; -} - -void* CodeBlock::nativeExceptionCodeForHandlerVPC(const Instruction* handlerVPC) -{ - Vector<HandlerInfo>::iterator ptr = exceptionHandlers.begin(); - Vector<HandlerInfo>::iterator end = exceptionHandlers.end(); - - for (; ptr != end; ++ptr) { - Instruction*target = instructions.begin() + ptr->target; - if (handlerVPC == target) - return ptr->nativeCode; - } - - return 0; -} - -int CodeBlock::lineNumberForVPC(const Instruction* vPC) -{ - unsigned instructionOffset = vPC - instructions.begin(); - ASSERT(instructionOffset < instructions.size()); - - if (!lineInfo.size()) - return ownerNode->source().firstLine(); // Empty function - - int low = 0; - int high = lineInfo.size(); - while (low < high) { - int mid = low + (high - low) / 2; - if (lineInfo[mid].instructionOffset <= instructionOffset) - low = mid + 1; - else - high = mid; - } - - if (!low) - return ownerNode->source().firstLine(); - return lineInfo[low - 1].lineNumber; -} - -int CodeBlock::expressionRangeForVPC(const Instruction* vPC, int& divot, int& startOffset, int& endOffset) -{ - unsigned instructionOffset = vPC - instructions.begin(); - ASSERT(instructionOffset < instructions.size()); - - if (!expressionInfo.size()) { - // We didn't think anything could throw. Apparently we were wrong. - startOffset = 0; - endOffset = 0; - divot = 0; - return lineNumberForVPC(vPC); - } - - int low = 0; - int high = expressionInfo.size(); - while (low < high) { - int mid = low + (high - low) / 2; - if (expressionInfo[mid].instructionOffset <= instructionOffset) - low = mid + 1; - else - high = mid; - } - - ASSERT(low); - if (!low) { - startOffset = 0; - endOffset = 0; - divot = 0; - return lineNumberForVPC(vPC); - } - - startOffset = expressionInfo[low - 1].startOffset; - endOffset = expressionInfo[low - 1].endOffset; - divot = expressionInfo[low - 1].divotPoint + sourceOffset; - return lineNumberForVPC(vPC); -} - -int32_t SimpleJumpTable::offsetForValue(int32_t value, int32_t defaultOffset) -{ - if (value >= min && static_cast<uint32_t>(value - min) < branchOffsets.size()) { - int32_t offset = branchOffsets[value - min]; - if (offset) - return offset; - } - return defaultOffset; -} - -} // namespace JSC diff --git a/JavaScriptCore/VM/CodeBlock.h b/JavaScriptCore/VM/CodeBlock.h deleted file mode 100644 index d745164..0000000 --- a/JavaScriptCore/VM/CodeBlock.h +++ /dev/null @@ -1,399 +0,0 @@ -/* - * Copyright (C) 2008 Apple Inc. All rights reserved. - * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca> - * - * 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 CodeBlock_h -#define CodeBlock_h - -#include "Instruction.h" -#include "JSGlobalObject.h" -#include "nodes.h" -#include "Parser.h" -#include "SourceCode.h" -#include "ustring.h" -#include <wtf/RefPtr.h> -#include <wtf/Vector.h> - -namespace JSC { - - class ExecState; - - enum CodeType { GlobalCode, EvalCode, FunctionCode }; - - static ALWAYS_INLINE int missingThisObjectMarker() { return std::numeric_limits<int>::max(); } - - struct HandlerInfo { - uint32_t start; - uint32_t end; - uint32_t target; - uint32_t scopeDepth; - void* nativeCode; - }; - - struct ExpressionRangeInfo { - enum { - MaxOffset = (1 << 7) - 1, - MaxDivot = (1 << 25) - 1 - }; - uint32_t instructionOffset : 25; - uint32_t divotPoint : 25; - uint32_t startOffset : 7; - uint32_t endOffset : 7; - }; - - struct LineInfo { - uint32_t instructionOffset; - int32_t lineNumber; - }; - - struct OffsetLocation { - int32_t branchOffset; -#if ENABLE(CTI) - void* ctiOffset; -#endif - }; - - struct StructureStubInfo { - StructureStubInfo(unsigned opcodeIndex) - : opcodeIndex(opcodeIndex) - , stubRoutine(0) - , callReturnLocation(0) - , hotPathBegin(0) - { - } - - unsigned opcodeIndex; - void* stubRoutine; - void* callReturnLocation; - void* hotPathBegin; - }; - - struct CallLinkInfo { - CallLinkInfo() - : callReturnLocation(0) - , hotPathBegin(0) - , hotPathOther(0) - , coldPathOther(0) - , callee(0) - { - } - - unsigned opcodeIndex; - void* callReturnLocation; - void* hotPathBegin; - void* hotPathOther; - void* coldPathOther; - CodeBlock* callee; - unsigned position; - - void setUnlinked() { callee = 0; } - bool isLinked() { return callee; } - }; - - inline void* getStructureStubInfoReturnLocation(StructureStubInfo* structureStubInfo) - { - return structureStubInfo->callReturnLocation; - } - - // Binary chop algorithm, calls valueAtPosition on pre-sorted elements in array, - // compares result with key (KeyTypes should be comparable with '--', '<', '>'). - // Optimized for cases where the array contains the key, checked by assertions. - template<typename ArrayType, typename KeyType, KeyType(*valueAtPosition)(ArrayType*)> - inline ArrayType* binaryChop(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. - while (size > 1) { - // Pick an element to check, half way through the array, and read the value. - int pos = (size - 1) >> 1; - KeyType val = valueAtPosition(&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); - } - - // '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 == valueAtPosition(&array[0])); - return &array[0]; - } - - struct StringJumpTable { - typedef HashMap<RefPtr<UString::Rep>, OffsetLocation> StringOffsetTable; - StringOffsetTable offsetTable; -#if ENABLE(CTI) - void* ctiDefault; // FIXME: it should not be necessary to store this. -#endif - - inline int32_t offsetForValue(UString::Rep* value, int32_t defaultOffset) - { - StringOffsetTable::const_iterator end = offsetTable.end(); - StringOffsetTable::const_iterator loc = offsetTable.find(value); - if (loc == end) - return defaultOffset; - return loc->second.branchOffset; - } - -#if ENABLE(CTI) - inline void* ctiForValue(UString::Rep* value) - { - StringOffsetTable::const_iterator end = offsetTable.end(); - StringOffsetTable::const_iterator loc = offsetTable.find(value); - if (loc == end) - return ctiDefault; - return loc->second.ctiOffset; - } -#endif - }; - - struct SimpleJumpTable { - // FIXME: The two Vectors can be combind into one Vector<OffsetLocation> - Vector<int32_t> branchOffsets; - int32_t min; -#if ENABLE(CTI) - Vector<void*> ctiOffsets; - void* ctiDefault; -#endif - - int32_t offsetForValue(int32_t value, int32_t defaultOffset); - void add(int32_t key, int32_t offset) - { - if (!branchOffsets[key]) - branchOffsets[key] = offset; - } - -#if ENABLE(CTI) - inline void* ctiForValue(int32_t value) - { - if (value >= min && static_cast<uint32_t>(value - min) < ctiOffsets.size()) - return ctiOffsets[value - min]; - return ctiDefault; - } -#endif - }; - - class EvalCodeCache { - public: - PassRefPtr<EvalNode> get(ExecState* exec, const UString& evalSource, ScopeChainNode* scopeChain, JSValue*& exceptionValue) - { - RefPtr<EvalNode> evalNode; - - if (evalSource.size() < maxCacheableSourceLength && (*scopeChain->begin())->isVariableObject()) - evalNode = cacheMap.get(evalSource.rep()); - - if (!evalNode) { - int errLine; - UString errMsg; - - SourceCode source = makeSource(evalSource); - evalNode = exec->globalData().parser->parse<EvalNode>(exec, exec->dynamicGlobalObject()->debugger(), source, &errLine, &errMsg); - if (evalNode) { - if (evalSource.size() < maxCacheableSourceLength && (*scopeChain->begin())->isVariableObject() && cacheMap.size() < maxCacheEntries) - cacheMap.set(evalSource.rep(), evalNode); - } else { - exceptionValue = Error::create(exec, SyntaxError, errMsg, errLine, source.provider()->asID(), NULL); - return 0; - } - } - - return evalNode.release(); - } - - private: - static const int maxCacheableSourceLength = 256; - static const int maxCacheEntries = 64; - - HashMap<RefPtr<UString::Rep>, RefPtr<EvalNode> > cacheMap; - }; - - struct CodeBlock { - CodeBlock(ScopeNode* ownerNode, CodeType codeType, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset) - : ownerNode(ownerNode) - , globalData(0) -#if ENABLE(CTI) - , ctiCode(0) -#endif - , numCalleeRegisters(0) - , numConstants(0) - , numVars(0) - , numParameters(0) - , needsFullScopeChain(ownerNode->needsActivation()) - , usesEval(ownerNode->usesEval()) - , codeType(codeType) - , source(sourceProvider) - , sourceOffset(sourceOffset) - { - ASSERT(source); - } - - ~CodeBlock(); - -#if ENABLE(CTI) - void unlinkCallers(); -#endif - - void addCaller(CallLinkInfo* caller) - { - caller->callee = this; - caller->position = linkedCallerList.size(); - linkedCallerList.append(caller); - } - - void removeCaller(CallLinkInfo* caller) - { - unsigned pos = caller->position; - unsigned lastPos = linkedCallerList.size() - 1; - - if (pos != lastPos) { - linkedCallerList[pos] = linkedCallerList[lastPos]; - linkedCallerList[pos]->position = pos; - } - linkedCallerList.shrink(lastPos); - } - -#if !defined(NDEBUG) || ENABLE_OPCODE_SAMPLING - void dump(ExecState*) const; - void printStructureIDs(const Instruction*) const; - void printStructureID(const char* name, const Instruction*, int operand) const; -#endif - int expressionRangeForVPC(const Instruction*, int& divot, int& startOffset, int& endOffset); - int lineNumberForVPC(const Instruction* vPC); - bool getHandlerForVPC(const Instruction* vPC, Instruction*& target, int& scopeDepth); - void* nativeExceptionCodeForHandlerVPC(const Instruction* handlerVPC); - - void mark(); - void refStructureIDs(Instruction* vPC) const; - void derefStructureIDs(Instruction* vPC) const; - - StructureStubInfo& getStubInfo(void* returnAddress) - { - return *(binaryChop<StructureStubInfo, void*, getStructureStubInfoReturnLocation>(propertyAccessInstructions.begin(), propertyAccessInstructions.size(), returnAddress)); - } - - ScopeNode* ownerNode; - JSGlobalData* globalData; -#if ENABLE(CTI) - void* ctiCode; -#endif - - int numCalleeRegisters; - - // NOTE: numConstants holds the number of constant registers allocated - // by the code generator, not the number of constant registers used. - // (Duplicate constants are uniqued during code generation, and spare - // constant registers may be allocated.) - int numConstants; - int numVars; - int numParameters; - int thisRegister; - bool needsFullScopeChain; - bool usesEval; - bool usesArguments; - CodeType codeType; - RefPtr<SourceProvider> source; - unsigned sourceOffset; - - Vector<Instruction> instructions; - Vector<unsigned> globalResolveInstructions; - Vector<StructureStubInfo> propertyAccessInstructions; - Vector<CallLinkInfo> callLinkInfos; - Vector<CallLinkInfo*> linkedCallerList; - - // Constant pool - Vector<Identifier> identifiers; - Vector<RefPtr<FuncDeclNode> > functions; - Vector<RefPtr<FuncExprNode> > functionExpressions; - Vector<Register> constantRegisters; - Vector<JSValue*> unexpectedConstants; - Vector<RefPtr<RegExp> > regexps; - Vector<HandlerInfo> exceptionHandlers; - Vector<ExpressionRangeInfo> expressionInfo; - Vector<LineInfo> lineInfo; - - Vector<SimpleJumpTable> immediateSwitchJumpTables; - Vector<SimpleJumpTable> characterSwitchJumpTables; - Vector<StringJumpTable> stringSwitchJumpTables; - - HashSet<unsigned, DefaultHash<unsigned>::Hash, WTF::UnsignedWithZeroKeyHashTraits<unsigned> > labels; - -#if ENABLE(CTI) - HashMap<void*, unsigned> ctiReturnAddressVPCMap; -#endif - - EvalCodeCache evalCodeCache; - - private: -#if !defined(NDEBUG) || ENABLE(OPCODE_SAMPLING) - void dump(ExecState*, const Vector<Instruction>::const_iterator& begin, Vector<Instruction>::const_iterator&) const; -#endif - - }; - - // Program code is not marked by any function, so we make the global object - // responsible for marking it. - - struct ProgramCodeBlock : public CodeBlock { - ProgramCodeBlock(ScopeNode* ownerNode, CodeType codeType, JSGlobalObject* globalObject, PassRefPtr<SourceProvider> sourceProvider) - : CodeBlock(ownerNode, codeType, sourceProvider, 0) - , globalObject(globalObject) - { - globalObject->codeBlocks().add(this); - } - - ~ProgramCodeBlock() - { - if (globalObject) - globalObject->codeBlocks().remove(this); - } - - JSGlobalObject* globalObject; // For program and eval nodes, the global object that marks the constant pool. - }; - - struct EvalCodeBlock : public ProgramCodeBlock { - EvalCodeBlock(ScopeNode* ownerNode, JSGlobalObject* globalObject, PassRefPtr<SourceProvider> sourceProvider) - : ProgramCodeBlock(ownerNode, EvalCode, globalObject, sourceProvider) - { - } - }; - -} // namespace JSC - -#endif // CodeBlock_h diff --git a/JavaScriptCore/VM/Machine.h b/JavaScriptCore/VM/Machine.h deleted file mode 100644 index 6cb8aaa..0000000 --- a/JavaScriptCore/VM/Machine.h +++ /dev/null @@ -1,374 +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 Machine_h -#define Machine_h - -#include "ArgList.h" -#include "JSCell.h" -#include "JSValue.h" -#include "Opcode.h" -#include "RegisterFile.h" -#include <wtf/HashMap.h> - -#ifdef ANDROID_INSTRUMENT -#include "TimeCounter.h" -#endif - -namespace JSC { - - class CodeBlock; - class EvalNode; - class FunctionBodyNode; - class Instruction; - class InternalFunction; - class JITCodeBuffer; - class JSFunction; - class JSGlobalObject; - class ProgramNode; - class Register; - class ScopeChainNode; - class SamplingTool; - -#if ENABLE(CTI) - -#if USE(CTI_ARGUMENT) -#define CTI_ARGS void** args -#define ARGS (args) -#else -#define CTI_ARGS void* args, ... -#define ARGS (&args) -#endif - -#if USE(FAST_CALL_CTI_ARGUMENT) - -#if COMPILER(MSVC) -#define SFX_CALL __fastcall -#elif COMPILER(GCC) -#define SFX_CALL __attribute__ ((fastcall)) -#else -#error Need to support fastcall calling convention in this compiler -#endif - -#else - -#if COMPILER(MSVC) -#define SFX_CALL __cdecl -#else -#define SFX_CALL -#endif - -#endif - - typedef uint64_t VoidPtrPair; - - typedef union - { - struct { void* first; void* second; } s; - VoidPtrPair i; - } VoidPtrPairValue; -#endif - - enum DebugHookID { - WillExecuteProgram, - DidExecuteProgram, - DidEnterCallFrame, - DidReachBreakpoint, - WillLeaveCallFrame, - WillExecuteStatement - }; - - enum { MaxReentryDepth = 128 }; - - class Machine { - friend class CTI; - public: - Machine(); - ~Machine(); - - RegisterFile& registerFile() { return m_registerFile; } - - Opcode getOpcode(OpcodeID id) - { - #if HAVE(COMPUTED_GOTO) - return m_opcodeTable[id]; - #else - return id; - #endif - } - - OpcodeID getOpcodeID(Opcode opcode) - { - #if HAVE(COMPUTED_GOTO) - ASSERT(isOpcode(opcode)); - return m_opcodeIDTable.get(opcode); - #else - return opcode; - #endif - } - - bool isOpcode(Opcode opcode); - - JSValue* execute(ProgramNode*, CallFrame*, ScopeChainNode*, JSObject* thisObj, JSValue** exception); - JSValue* execute(FunctionBodyNode*, CallFrame*, JSFunction*, JSObject* thisObj, const ArgList& args, ScopeChainNode*, JSValue** exception); - JSValue* execute(EvalNode* evalNode, CallFrame* exec, JSObject* thisObj, ScopeChainNode* scopeChain, JSValue** exception); - - JSValue* retrieveArguments(CallFrame*, JSFunction*) const; - JSValue* retrieveCaller(CallFrame*, InternalFunction*) const; - void retrieveLastCaller(CallFrame*, int& lineNumber, intptr_t& sourceID, UString& sourceURL, JSValue*& function) const; - - void getArgumentsData(CallFrame*, JSFunction*&, ptrdiff_t& firstParameterIndex, Register*& argv, int& argc); - void setTimeoutTime(unsigned timeoutTime) { m_timeoutTime = timeoutTime; } - - void startTimeoutCheck() - { - if (!m_timeoutCheckCount) - resetTimeoutCheck(); -#ifdef ANDROID_INSTRUMENT - if (!m_timeoutCheckCount) - android::TimeCounter::start(android::TimeCounter::JavaScriptTimeCounter); -#endif - ++m_timeoutCheckCount; - } - - void stopTimeoutCheck() - { - ASSERT(m_timeoutCheckCount); - --m_timeoutCheckCount; -#ifdef ANDROID_INSTRUMENT - if (!m_timeoutCheckCount) - android::TimeCounter::record(android::TimeCounter::JavaScriptTimeCounter, __FUNCTION__); -#endif - } - - inline void initTimeout() - { - ASSERT(!m_timeoutCheckCount); - resetTimeoutCheck(); - m_timeoutTime = 0; - m_timeoutCheckCount = 0; - } - - void setSampler(SamplingTool* sampler) { m_sampler = sampler; } - SamplingTool* sampler() { return m_sampler; } - -#if ENABLE(CTI) - - static void SFX_CALL cti_timeout_check(CTI_ARGS); - static void SFX_CALL cti_register_file_check(CTI_ARGS); - - static JSObject* SFX_CALL cti_op_convert_this(CTI_ARGS); - static void SFX_CALL cti_op_end(CTI_ARGS); - static JSValue* SFX_CALL cti_op_add(CTI_ARGS); - static JSValue* SFX_CALL cti_op_pre_inc(CTI_ARGS); - static int SFX_CALL cti_op_loop_if_less(CTI_ARGS); - static int SFX_CALL cti_op_loop_if_lesseq(CTI_ARGS); - static JSObject* SFX_CALL cti_op_new_object(CTI_ARGS); - static void SFX_CALL cti_op_put_by_id(CTI_ARGS); - static void SFX_CALL cti_op_put_by_id_second(CTI_ARGS); - static void SFX_CALL cti_op_put_by_id_generic(CTI_ARGS); - static void SFX_CALL cti_op_put_by_id_fail(CTI_ARGS); - static JSValue* SFX_CALL cti_op_get_by_id(CTI_ARGS); - static JSValue* SFX_CALL cti_op_get_by_id_second(CTI_ARGS); - static JSValue* SFX_CALL cti_op_get_by_id_generic(CTI_ARGS); - static JSValue* SFX_CALL cti_op_get_by_id_fail(CTI_ARGS); - static JSValue* SFX_CALL cti_op_del_by_id(CTI_ARGS); - static JSValue* SFX_CALL cti_op_instanceof(CTI_ARGS); - static JSValue* SFX_CALL cti_op_mul(CTI_ARGS); - static JSObject* SFX_CALL cti_op_new_func(CTI_ARGS); - static VoidPtrPair SFX_CALL cti_op_call_JSFunction(CTI_ARGS); - static JSValue* SFX_CALL cti_op_call_NotJSFunction(CTI_ARGS); - static void SFX_CALL cti_op_create_arguments(CTI_ARGS); - static void SFX_CALL cti_op_create_arguments_no_params(CTI_ARGS); - static void SFX_CALL cti_op_tear_off_activation(CTI_ARGS); - static void SFX_CALL cti_op_tear_off_arguments(CTI_ARGS); - static void SFX_CALL cti_op_profile_will_call(CTI_ARGS); - static void SFX_CALL cti_op_profile_did_call(CTI_ARGS); - static void SFX_CALL cti_op_ret_scopeChain(CTI_ARGS); - static JSObject* SFX_CALL cti_op_new_array(CTI_ARGS); - static JSValue* SFX_CALL cti_op_resolve(CTI_ARGS); - static JSValue* SFX_CALL cti_op_resolve_global(CTI_ARGS); - static JSObject* SFX_CALL cti_op_construct_JSConstructFast(CTI_ARGS); - static VoidPtrPair SFX_CALL cti_op_construct_JSConstruct(CTI_ARGS); - static JSValue* SFX_CALL cti_op_construct_NotJSConstruct(CTI_ARGS); - static JSValue* SFX_CALL cti_op_get_by_val(CTI_ARGS); - static VoidPtrPair SFX_CALL cti_op_resolve_func(CTI_ARGS); - static JSValue* SFX_CALL cti_op_sub(CTI_ARGS); - static void SFX_CALL cti_op_put_by_val(CTI_ARGS); - static void SFX_CALL cti_op_put_by_val_array(CTI_ARGS); - static JSValue* SFX_CALL cti_op_lesseq(CTI_ARGS); - static int SFX_CALL cti_op_loop_if_true(CTI_ARGS); - static JSValue* SFX_CALL cti_op_resolve_base(CTI_ARGS); - static JSValue* SFX_CALL cti_op_negate(CTI_ARGS); - static JSValue* SFX_CALL cti_op_resolve_skip(CTI_ARGS); - static JSValue* SFX_CALL cti_op_div(CTI_ARGS); - static JSValue* SFX_CALL cti_op_pre_dec(CTI_ARGS); - static int SFX_CALL cti_op_jless(CTI_ARGS); - static JSValue* SFX_CALL cti_op_not(CTI_ARGS); - static int SFX_CALL cti_op_jtrue(CTI_ARGS); - static VoidPtrPair SFX_CALL cti_op_post_inc(CTI_ARGS); - static JSValue* SFX_CALL cti_op_eq(CTI_ARGS); - static JSValue* SFX_CALL cti_op_lshift(CTI_ARGS); - static JSValue* SFX_CALL cti_op_bitand(CTI_ARGS); - static JSValue* SFX_CALL cti_op_rshift(CTI_ARGS); - static JSValue* SFX_CALL cti_op_bitnot(CTI_ARGS); - static VoidPtrPair SFX_CALL cti_op_resolve_with_base(CTI_ARGS); - static JSObject* SFX_CALL cti_op_new_func_exp(CTI_ARGS); - static JSValue* SFX_CALL cti_op_mod(CTI_ARGS); - static JSValue* SFX_CALL cti_op_less(CTI_ARGS); - static JSValue* SFX_CALL cti_op_neq(CTI_ARGS); - static VoidPtrPair SFX_CALL cti_op_post_dec(CTI_ARGS); - static JSValue* SFX_CALL cti_op_urshift(CTI_ARGS); - static JSValue* SFX_CALL cti_op_bitxor(CTI_ARGS); - static JSObject* SFX_CALL cti_op_new_regexp(CTI_ARGS); - static JSValue* SFX_CALL cti_op_bitor(CTI_ARGS); - static JSValue* SFX_CALL cti_op_call_eval(CTI_ARGS); - static JSValue* SFX_CALL cti_op_throw(CTI_ARGS); - static JSPropertyNameIterator* SFX_CALL cti_op_get_pnames(CTI_ARGS); - static JSValue* SFX_CALL cti_op_next_pname(CTI_ARGS); - static void SFX_CALL cti_op_push_scope(CTI_ARGS); - static void SFX_CALL cti_op_pop_scope(CTI_ARGS); - static JSValue* SFX_CALL cti_op_typeof(CTI_ARGS); - static JSValue* SFX_CALL cti_op_is_undefined(CTI_ARGS); - static JSValue* SFX_CALL cti_op_is_boolean(CTI_ARGS); - static JSValue* SFX_CALL cti_op_is_number(CTI_ARGS); - static JSValue* SFX_CALL cti_op_is_string(CTI_ARGS); - static JSValue* SFX_CALL cti_op_is_object(CTI_ARGS); - static JSValue* SFX_CALL cti_op_is_function(CTI_ARGS); - static JSValue* SFX_CALL cti_op_stricteq(CTI_ARGS); - static JSValue* SFX_CALL cti_op_nstricteq(CTI_ARGS); - static JSValue* SFX_CALL cti_op_to_jsnumber(CTI_ARGS); - static JSValue* SFX_CALL cti_op_in(CTI_ARGS); - static JSObject* SFX_CALL cti_op_push_new_scope(CTI_ARGS); - static void SFX_CALL cti_op_jmp_scopes(CTI_ARGS); - static void SFX_CALL cti_op_put_by_index(CTI_ARGS); - static void* SFX_CALL cti_op_switch_imm(CTI_ARGS); - static void* SFX_CALL cti_op_switch_char(CTI_ARGS); - static void* SFX_CALL cti_op_switch_string(CTI_ARGS); - static JSValue* SFX_CALL cti_op_del_by_val(CTI_ARGS); - static void SFX_CALL cti_op_put_getter(CTI_ARGS); - static void SFX_CALL cti_op_put_setter(CTI_ARGS); - static JSObject* SFX_CALL cti_op_new_error(CTI_ARGS); - static void SFX_CALL cti_op_debug(CTI_ARGS); - - static JSValue* SFX_CALL cti_allocate_number(CTI_ARGS); - - static JSValue* SFX_CALL cti_vm_throw(CTI_ARGS); - static void* SFX_CALL cti_vm_compile(CTI_ARGS); - static void* SFX_CALL cti_vm_lazyLinkCall(CTI_ARGS); - static JSObject* SFX_CALL cti_op_push_activation(CTI_ARGS); - -#endif // ENABLE(CTI) - - // Default number of ticks before a timeout check should be done. - static const int initialTickCountThreshold = 1024; - - bool isJSArray(JSValue* v) { return !JSImmediate::isImmediate(v) && v->asCell()->vptr() == m_jsArrayVptr; } - bool isJSString(JSValue* v) { return !JSImmediate::isImmediate(v) && v->asCell()->vptr() == m_jsStringVptr; } - - private: - enum ExecutionFlag { Normal, InitializeAndReturn }; - - NEVER_INLINE JSValue* callEval(CallFrame*, JSObject* thisObject, ScopeChainNode*, RegisterFile*, int argv, int argc, JSValue*& exceptionValue); - JSValue* execute(EvalNode*, CallFrame*, JSObject* thisObject, int registerOffset, ScopeChainNode*, JSValue** exception); - - NEVER_INLINE void debug(CallFrame*, DebugHookID, int firstLine, int lastLine); - - NEVER_INLINE bool resolve(CallFrame*, Instruction*, JSValue*& exceptionValue); - NEVER_INLINE bool resolveSkip(CallFrame*, Instruction*, JSValue*& exceptionValue); - NEVER_INLINE bool resolveGlobal(CallFrame*, Instruction*, JSValue*& exceptionValue); - NEVER_INLINE void resolveBase(CallFrame*, Instruction* vPC); - NEVER_INLINE bool resolveBaseAndProperty(CallFrame*, Instruction*, JSValue*& exceptionValue); - NEVER_INLINE ScopeChainNode* createExceptionScope(CallFrame*, const Instruction* vPC); - - NEVER_INLINE bool unwindCallFrame(CallFrame*&, JSValue*, const Instruction*&, CodeBlock*&); - NEVER_INLINE Instruction* throwException(CallFrame*&, JSValue*&, const Instruction*, bool); - NEVER_INLINE bool resolveBaseAndFunc(CallFrame*, Instruction*, JSValue*& exceptionValue); - - static ALWAYS_INLINE CallFrame* slideRegisterWindowForCall(CodeBlock*, RegisterFile*, CallFrame*, size_t registerOffset, int argc); - - static CallFrame* findFunctionCallFrame(CallFrame*, InternalFunction*); - - JSValue* privateExecute(ExecutionFlag, RegisterFile*, CallFrame*, JSValue** exception); - - void dumpCallFrame(const RegisterFile*, CallFrame*); - void dumpRegisters(const RegisterFile*, CallFrame*); - - JSValue* checkTimeout(JSGlobalObject*); - void resetTimeoutCheck(); - - void tryCacheGetByID(CallFrame*, CodeBlock*, Instruction*, JSValue* baseValue, const Identifier& propertyName, const PropertySlot&); - void uncacheGetByID(CodeBlock*, Instruction* vPC); - void tryCachePutByID(CallFrame*, CodeBlock*, Instruction*, JSValue* baseValue, const PutPropertySlot&); - void uncachePutByID(CodeBlock*, Instruction* vPC); - - bool isCallOpcode(Opcode opcode) { return opcode == getOpcode(op_call) || opcode == getOpcode(op_construct) || opcode == getOpcode(op_call_eval); } - -#if ENABLE(CTI) - static void throwStackOverflowPreviousFrame(CallFrame*, JSGlobalData*, void*& returnAddress); - - void tryCTICacheGetByID(CallFrame*, CodeBlock*, void* returnAddress, JSValue* baseValue, const Identifier& propertyName, const PropertySlot&); - void tryCTICachePutByID(CallFrame*, CodeBlock*, void* returnAddress, JSValue* baseValue, const PutPropertySlot&); - - void* getCTIArrayLengthTrampoline(CallFrame*, CodeBlock*); - void* getCTIStringLengthTrampoline(CallFrame*, CodeBlock*); - - JITCodeBuffer* jitCodeBuffer() const { return m_jitCodeBuffer.get(); } -#endif - - SamplingTool* m_sampler; - -#if ENABLE(CTI) - void* m_ctiArrayLengthTrampoline; - void* m_ctiStringLengthTrampoline; - - OwnPtr<JITCodeBuffer> m_jitCodeBuffer; -#endif - - int m_reentryDepth; - unsigned m_timeoutTime; - unsigned m_timeAtLastCheckTimeout; - unsigned m_timeExecuting; - unsigned m_timeoutCheckCount; - unsigned m_ticksUntilNextTimeoutCheck; - - RegisterFile m_registerFile; - - void* m_jsArrayVptr; - void* m_jsStringVptr; - void* m_jsFunctionVptr; - -#if HAVE(COMPUTED_GOTO) - Opcode m_opcodeTable[numOpcodeIDs]; // Maps OpcodeID => Opcode for compiling - HashMap<Opcode, OpcodeID> m_opcodeIDTable; // Maps Opcode => OpcodeID for decompiling -#endif - }; - -} // namespace JSC - -#endif // Machine_h diff --git a/JavaScriptCore/VM/Opcode.h b/JavaScriptCore/VM/Opcode.h deleted file mode 100644 index fb65cec..0000000 --- a/JavaScriptCore/VM/Opcode.h +++ /dev/null @@ -1,219 +0,0 @@ -/* - * Copyright (C) 2008 Apple Inc. All rights reserved. - * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca> - * - * 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 Opcodes_h -#define Opcodes_h - -#include <algorithm> -#include <string.h> - -#include <wtf/Assertions.h> - -namespace JSC { - - #define FOR_EACH_OPCODE_ID(macro) \ - macro(op_enter) \ - macro(op_enter_with_activation) \ - macro(op_create_arguments) \ - macro(op_convert_this) \ - \ - macro(op_unexpected_load) \ - macro(op_new_object) \ - macro(op_new_array) \ - macro(op_new_regexp) \ - macro(op_mov) \ - \ - macro(op_not) \ - macro(op_eq) \ - macro(op_eq_null) \ - macro(op_neq) \ - macro(op_neq_null) \ - macro(op_stricteq) \ - macro(op_nstricteq) \ - macro(op_less) \ - macro(op_lesseq) \ - \ - macro(op_pre_inc) \ - macro(op_pre_dec) \ - macro(op_post_inc) \ - macro(op_post_dec) \ - macro(op_to_jsnumber) \ - macro(op_negate) \ - macro(op_add) \ - macro(op_mul) \ - macro(op_div) \ - macro(op_mod) \ - macro(op_sub) \ - \ - macro(op_lshift) \ - macro(op_rshift) \ - macro(op_urshift) \ - macro(op_bitand) \ - macro(op_bitxor) \ - macro(op_bitor) \ - macro(op_bitnot) \ - \ - macro(op_instanceof) \ - macro(op_typeof) \ - macro(op_is_undefined) \ - macro(op_is_boolean) \ - macro(op_is_number) \ - macro(op_is_string) \ - macro(op_is_object) \ - macro(op_is_function) \ - macro(op_in) \ - \ - macro(op_resolve) \ - macro(op_resolve_skip) \ - macro(op_resolve_global) \ - macro(op_get_scoped_var) \ - macro(op_put_scoped_var) \ - macro(op_get_global_var) \ - macro(op_put_global_var) \ - macro(op_resolve_base) \ - macro(op_resolve_with_base) \ - macro(op_resolve_func) \ - macro(op_get_by_id) \ - macro(op_get_by_id_self) \ - macro(op_get_by_id_proto) \ - macro(op_get_by_id_chain) \ - macro(op_get_by_id_generic) \ - macro(op_get_array_length) \ - macro(op_get_string_length) \ - macro(op_put_by_id) \ - macro(op_put_by_id_transition) \ - macro(op_put_by_id_replace) \ - macro(op_put_by_id_generic) \ - macro(op_del_by_id) \ - macro(op_get_by_val) \ - macro(op_put_by_val) \ - macro(op_del_by_val) \ - macro(op_put_by_index) \ - macro(op_put_getter) \ - macro(op_put_setter) \ - \ - macro(op_jmp) \ - macro(op_jtrue) \ - macro(op_jfalse) \ - macro(op_jeq_null) \ - macro(op_jneq_null) \ - macro(op_jnless) \ - macro(op_jmp_scopes) \ - macro(op_loop) \ - macro(op_loop_if_true) \ - macro(op_loop_if_less) \ - macro(op_loop_if_lesseq) \ - macro(op_switch_imm) \ - macro(op_switch_char) \ - macro(op_switch_string) \ - \ - macro(op_new_func) \ - macro(op_new_func_exp) \ - macro(op_call) \ - macro(op_call_eval) \ - macro(op_tear_off_activation) \ - macro(op_tear_off_arguments) \ - macro(op_ret) \ - \ - macro(op_construct) \ - macro(op_construct_verify) \ - \ - macro(op_get_pnames) \ - macro(op_next_pname) \ - \ - macro(op_push_scope) \ - macro(op_pop_scope) \ - macro(op_push_new_scope) \ - \ - macro(op_catch) \ - macro(op_throw) \ - macro(op_new_error) \ - \ - macro(op_jsr) \ - macro(op_sret) \ - \ - macro(op_debug) \ - macro(op_profile_will_call) \ - macro(op_profile_did_call) \ - \ - macro(op_end) // end must be the last opcode in the list - - #define OPCODE_ID_ENUM(opcode) opcode, - typedef enum { FOR_EACH_OPCODE_ID(OPCODE_ID_ENUM) } OpcodeID; - #undef OPCODE_ID_ENUM - - const int numOpcodeIDs = op_end + 1; - - #define VERIFY_OPCODE_ID(id) COMPILE_ASSERT(id <= op_end, ASSERT_THAT_JS_OPCODE_IDS_ARE_VALID); - FOR_EACH_OPCODE_ID(VERIFY_OPCODE_ID); - #undef VERIFY_OPCODE_ID - -#if HAVE(COMPUTED_GOTO) - typedef void* Opcode; -#else - typedef OpcodeID Opcode; -#endif - -#if ENABLE(OPCODE_SAMPLING) || ENABLE(CODEBLOCK_SAMPLING) || ENABLE(OPCODE_STATS) - -#define PADDING_STRING " " -#define PADDING_STRING_LENGTH static_cast<unsigned>(strlen(PADDING_STRING)) - - extern const char* const opcodeNames[]; - - inline const char* padOpcodeName(OpcodeID op, unsigned width) - { - unsigned pad = width - strlen(opcodeNames[op]); - pad = std::min(pad, PADDING_STRING_LENGTH); - return PADDING_STRING + PADDING_STRING_LENGTH - pad; - } - -#undef PADDING_STRING_LENGTH -#undef PADDING_STRING - -#endif - -#if ENABLE(OPCODE_STATS) - - struct OpcodeStats { - OpcodeStats(); - ~OpcodeStats(); - static long long opcodeCounts[numOpcodeIDs]; - static long long opcodePairCounts[numOpcodeIDs][numOpcodeIDs]; - static int lastOpcode; - - static void recordInstruction(int opcode); - static void resetLastInstruction(); - }; - -#endif - -} // namespace JSC - -#endif // Opcodes_h diff --git a/JavaScriptCore/assembler/AssemblerBuffer.h b/JavaScriptCore/assembler/AssemblerBuffer.h new file mode 100644 index 0000000..e1f53d8 --- /dev/null +++ b/JavaScriptCore/assembler/AssemblerBuffer.h @@ -0,0 +1,160 @@ +/* + * 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 AssemblerBuffer_h +#define AssemblerBuffer_h + +#include <wtf/Platform.h> + +#if ENABLE(ASSEMBLER) + +#include "stdint.h" +#include <string.h> +#include <jit/ExecutableAllocator.h> +#include <wtf/Assertions.h> +#include <wtf/FastMalloc.h> + +namespace JSC { + + class AssemblerBuffer { + static const int inlineCapacity = 256; + public: + AssemblerBuffer() + : m_buffer(m_inlineBuffer) + , m_capacity(inlineCapacity) + , m_size(0) + { + } + + ~AssemblerBuffer() + { + if (m_buffer != m_inlineBuffer) + fastFree(m_buffer); + } + + void ensureSpace(int space) + { + if (m_size > m_capacity - space) + grow(); + } + + bool isAligned(int alignment) const + { + return !(m_size & (alignment - 1)); + } + + void putByteUnchecked(int value) + { + ASSERT(!(m_size > m_capacity - 4)); + m_buffer[m_size] = value; + m_size++; + } + + void putByte(int value) + { + if (m_size > m_capacity - 4) + grow(); + putByteUnchecked(value); + } + + void putShortUnchecked(int value) + { + ASSERT(!(m_size > m_capacity - 4)); + *reinterpret_cast<short*>(&m_buffer[m_size]) = value; + m_size += 2; + } + + void putShort(int value) + { + if (m_size > m_capacity - 4) + grow(); + putShortUnchecked(value); + } + + void putIntUnchecked(int value) + { + *reinterpret_cast<int*>(&m_buffer[m_size]) = value; + m_size += 4; + } + + void putInt64Unchecked(int64_t value) + { + *reinterpret_cast<int64_t*>(&m_buffer[m_size]) = value; + m_size += 8; + } + + void putInt(int value) + { + if (m_size > m_capacity - 4) + grow(); + putIntUnchecked(value); + } + + void* data() const + { + return m_buffer; + } + + int size() const + { + return m_size; + } + + void* executableCopy(ExecutablePool* allocator) + { + if (!m_size) + return 0; + + void* result = allocator->alloc(m_size); + + if (!result) + return 0; + + return memcpy(result, m_buffer, m_size); + } + + private: + void grow() + { + m_capacity += m_capacity / 2; + + if (m_buffer == m_inlineBuffer) { + char* newBuffer = static_cast<char*>(fastMalloc(m_capacity)); + m_buffer = static_cast<char*>(memcpy(newBuffer, m_buffer, m_size)); + } else + m_buffer = static_cast<char*>(fastRealloc(m_buffer, m_capacity)); + } + + char m_inlineBuffer[inlineCapacity]; + char* m_buffer; + int m_capacity; + int m_size; + }; + +} // namespace JSC + +#endif // ENABLE(ASSEMBLER) + +#endif // AssemblerBuffer_h diff --git a/JavaScriptCore/assembler/MacroAssembler.h b/JavaScriptCore/assembler/MacroAssembler.h new file mode 100644 index 0000000..9d24653 --- /dev/null +++ b/JavaScriptCore/assembler/MacroAssembler.h @@ -0,0 +1,2019 @@ +/* + * 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 MacroAssembler_h +#define MacroAssembler_h + +#include <wtf/Platform.h> + +#if ENABLE(ASSEMBLER) + +#include "X86Assembler.h" + +namespace JSC { + +class MacroAssembler { +protected: + X86Assembler m_assembler; + +#if PLATFORM(X86_64) + static const X86::RegisterID scratchRegister = X86::r11; +#endif + +public: + typedef X86::RegisterID RegisterID; + + // Note: do not rely on values in this enum, these will change (to 0..3). + enum Scale { + TimesOne = 1, + TimesTwo = 2, + TimesFour = 4, + TimesEight = 8, +#if PLATFORM(X86) + ScalePtr = TimesFour +#endif +#if PLATFORM(X86_64) + ScalePtr = TimesEight +#endif + }; + + MacroAssembler() + { + } + + size_t size() { return m_assembler.size(); } + void* copyCode(ExecutablePool* allocator) + { + return m_assembler.executableCopy(allocator); + } + + + // Address: + // + // Describes a simple base-offset address. + struct Address { + explicit Address(RegisterID base, int32_t offset = 0) + : base(base) + , offset(offset) + { + } + + RegisterID base; + int32_t offset; + }; + + // ImplicitAddress: + // + // This class is used for explicit 'load' and 'store' operations + // (as opposed to situations in which a memory operand is provided + // to a generic operation, such as an integer arithmetic instruction). + // + // In the case of a load (or store) operation we want to permit + // addresses to be implicitly constructed, e.g. the two calls: + // + // load32(Address(addrReg), destReg); + // load32(addrReg, destReg); + // + // Are equivalent, and the explicit wrapping of the Address in the former + // is unnecessary. + struct ImplicitAddress { + ImplicitAddress(RegisterID base) + : base(base) + , offset(0) + { + } + + ImplicitAddress(Address address) + : base(address.base) + , offset(address.offset) + { + } + + RegisterID base; + int32_t offset; + }; + + // BaseIndex: + // + // Describes a complex addressing mode. + struct BaseIndex { + BaseIndex(RegisterID base, RegisterID index, Scale scale, int32_t offset = 0) + : base(base) + , index(index) + , scale(scale) + , offset(offset) + { + } + + RegisterID base; + RegisterID index; + Scale scale; + int32_t offset; + }; + + // AbsoluteAddress: + // + // Describes an memory operand given by a pointer. For regular load & store + // operations an unwrapped void* will be used, rather than using this. + struct AbsoluteAddress { + explicit AbsoluteAddress(void* ptr) + : m_ptr(ptr) + { + } + + void* m_ptr; + }; + + + class Jump; + class PatchBuffer; + + // DataLabelPtr: + // + // A DataLabelPtr is used to refer to a location in the code containing a pointer to be + // patched after the code has been generated. + class DataLabelPtr { + friend class MacroAssembler; + friend class PatchBuffer; + + public: + DataLabelPtr() + { + } + + DataLabelPtr(MacroAssembler* masm) + : m_label(masm->m_assembler.label()) + { + } + + static void patch(void* address, void* value) + { + X86Assembler::patchPointer(reinterpret_cast<intptr_t>(address), reinterpret_cast<intptr_t>(value)); + } + + private: + X86Assembler::JmpDst m_label; + }; + + // DataLabel32: + // + // A DataLabelPtr is used to refer to a location in the code containing a pointer to be + // patched after the code has been generated. + class DataLabel32 { + friend class MacroAssembler; + friend class PatchBuffer; + + public: + DataLabel32() + { + } + + DataLabel32(MacroAssembler* masm) + : m_label(masm->m_assembler.label()) + { + } + + static void patch(void* address, int32_t value) + { + X86Assembler::patchImmediate(reinterpret_cast<intptr_t>(address), value); + } + + private: + X86Assembler::JmpDst m_label; + }; + + // Label: + // + // A Label records a point in the generated instruction stream, typically such that + // it may be used as a destination for a jump. + class Label { + friend class Jump; + friend class MacroAssembler; + friend class PatchBuffer; + + public: + Label() + { + } + + Label(MacroAssembler* masm) + : m_label(masm->m_assembler.label()) + { + } + + // FIXME: transitionary method, while we replace JmpSrces with Jumps. + operator X86Assembler::JmpDst() + { + return m_label; + } + + private: + X86Assembler::JmpDst m_label; + }; + + + // Jump: + // + // A jump object is a reference to a jump instruction that has been planted + // into the code buffer - it is typically used to link the jump, setting the + // relative offset such that when executed it will jump to the desired + // destination. + // + // Jump objects retain a pointer to the assembler for syntactic purposes - + // to allow the jump object to be able to link itself, e.g.: + // + // Jump forwardsBranch = jne32(Imm32(0), reg1); + // // ... + // forwardsBranch.link(); + // + // Jumps may also be linked to a Label. + class Jump { + friend class PatchBuffer; + friend class MacroAssembler; + + public: + Jump() + { + } + + // FIXME: transitionary method, while we replace JmpSrces with Jumps. + Jump(X86Assembler::JmpSrc jmp) + : m_jmp(jmp) + { + } + + void link(MacroAssembler* masm) + { + masm->m_assembler.link(m_jmp, masm->m_assembler.label()); + } + + void linkTo(Label label, MacroAssembler* masm) + { + masm->m_assembler.link(m_jmp, label.m_label); + } + + // FIXME: transitionary method, while we replace JmpSrces with Jumps. + operator X86Assembler::JmpSrc() + { + return m_jmp; + } + + static void patch(void* address, void* destination) + { + X86Assembler::patchBranchOffset(reinterpret_cast<intptr_t>(address), destination); + } + + private: + X86Assembler::JmpSrc m_jmp; + }; + + // JumpList: + // + // A JumpList is a set of Jump objects. + // All jumps in the set will be linked to the same destination. + class JumpList { + friend class PatchBuffer; + + public: + void link(MacroAssembler* masm) + { + size_t size = m_jumps.size(); + for (size_t i = 0; i < size; ++i) + m_jumps[i].link(masm); + m_jumps.clear(); + } + + void linkTo(Label label, MacroAssembler* masm) + { + size_t size = m_jumps.size(); + for (size_t i = 0; i < size; ++i) + m_jumps[i].linkTo(label, masm); + m_jumps.clear(); + } + + void append(Jump jump) + { + m_jumps.append(jump); + } + + void append(JumpList& other) + { + m_jumps.append(other.m_jumps.begin(), other.m_jumps.size()); + } + + bool empty() + { + return !m_jumps.size(); + } + + private: + Vector<Jump, 16> m_jumps; + }; + + + // PatchBuffer: + // + // This class assists in linking code generated by the macro assembler, once code generation + // has been completed, and the code has been copied to is final location in memory. At this + // time pointers to labels within the code may be resolved, and relative offsets to external + // addresses may be fixed. + // + // Specifically: + // * Jump objects may be linked to external targets, + // * The address of Jump objects may taken, such that it can later be relinked. + // * The return address of a Jump object representing a call may be acquired. + // * The address of a Label pointing into the code may be resolved. + // * The value referenced by a DataLabel may be fixed. + // + // FIXME: distinguish between Calls & Jumps (make a specific call to obtain the return + // address of calls, as opposed to a point that can be used to later relink a Jump - + // possibly wrap the later up in an object that can do just that). + class PatchBuffer { + public: + PatchBuffer(void* code) + : m_code(code) + { + } + + void link(Jump jump, void* target) + { + X86Assembler::link(m_code, jump.m_jmp, target); + } + + void link(JumpList list, void* target) + { + for (unsigned i = 0; i < list.m_jumps.size(); ++i) + X86Assembler::link(m_code, list.m_jumps[i], target); + } + + void* addressOf(Jump jump) + { + return X86Assembler::getRelocatedAddress(m_code, jump.m_jmp); + } + + void* addressOf(Label label) + { + return X86Assembler::getRelocatedAddress(m_code, label.m_label); + } + + void* addressOf(DataLabelPtr label) + { + return X86Assembler::getRelocatedAddress(m_code, label.m_label); + } + + void* addressOf(DataLabel32 label) + { + return X86Assembler::getRelocatedAddress(m_code, label.m_label); + } + + void setPtr(DataLabelPtr label, void* value) + { + X86Assembler::patchAddress(m_code, label.m_label, value); + } + + private: + void* m_code; + }; + + + // ImmPtr: + // + // A pointer sized immediate operand to an instruction - this is wrapped + // in a class requiring explicit construction in order to differentiate + // from pointers used as absolute addresses to memory operations + struct ImmPtr { + explicit ImmPtr(void* value) + : m_value(value) + { + } + + intptr_t asIntptr() + { + return reinterpret_cast<intptr_t>(m_value); + } + + void* m_value; + }; + + + // Imm32: + // + // A 32bit immediate operand to an instruction - this is wrapped in a + // class requiring explicit construction in order to prevent RegisterIDs + // (which are implemented as an enum) from accidentally being passed as + // immediate values. + struct Imm32 { + explicit Imm32(int32_t value) + : m_value(value) + { + } + +#if PLATFORM(X86) + explicit Imm32(ImmPtr ptr) + : m_value(ptr.asIntptr()) + { + } +#endif + + int32_t m_value; + }; + + // Integer arithmetic operations: + // + // Operations are typically two operand - operation(source, srcDst) + // For many operations the source may be an Imm32, the srcDst operand + // may often be a memory location (explictly described using an Address + // object). + + void addPtr(RegisterID src, RegisterID dest) + { +#if PLATFORM(X86_64) + m_assembler.addq_rr(src, dest); +#else + add32(src, dest); +#endif + } + + void addPtr(Imm32 imm, RegisterID srcDest) + { +#if PLATFORM(X86_64) + m_assembler.addq_ir(imm.m_value, srcDest); +#else + add32(imm, srcDest); +#endif + } + + void addPtr(ImmPtr imm, RegisterID dest) + { +#if PLATFORM(X86_64) + move(imm, scratchRegister); + m_assembler.addq_rr(scratchRegister, dest); +#else + add32(Imm32(imm), dest); +#endif + } + + void addPtr(Imm32 imm, RegisterID src, RegisterID dest) + { + m_assembler.leal_mr(imm.m_value, src, dest); + } + + void add32(RegisterID src, RegisterID dest) + { + m_assembler.addl_rr(src, dest); + } + + void add32(Imm32 imm, Address address) + { + m_assembler.addl_im(imm.m_value, address.offset, address.base); + } + + void add32(Imm32 imm, RegisterID dest) + { + m_assembler.addl_ir(imm.m_value, dest); + } + + void add32(Imm32 imm, AbsoluteAddress address) + { +#if PLATFORM(X86_64) + move(ImmPtr(address.m_ptr), scratchRegister); + add32(imm, Address(scratchRegister)); +#else + m_assembler.addl_im(imm.m_value, address.m_ptr); +#endif + } + + void add32(Address src, RegisterID dest) + { + m_assembler.addl_mr(src.offset, src.base, dest); + } + + void andPtr(RegisterID src, RegisterID dest) + { +#if PLATFORM(X86_64) + m_assembler.andq_rr(src, dest); +#else + and32(src, dest); +#endif + } + + void andPtr(Imm32 imm, RegisterID srcDest) + { +#if PLATFORM(X86_64) + m_assembler.andq_ir(imm.m_value, srcDest); +#else + and32(imm, srcDest); +#endif + } + + void and32(RegisterID src, RegisterID dest) + { + m_assembler.andl_rr(src, dest); + } + + void and32(Imm32 imm, RegisterID dest) + { + m_assembler.andl_ir(imm.m_value, dest); + } + + void lshift32(Imm32 imm, RegisterID dest) + { + m_assembler.shll_i8r(imm.m_value, dest); + } + + void lshift32(RegisterID shift_amount, RegisterID dest) + { + // On x86 we can only shift by ecx; if asked to shift by another register we'll + // need rejig the shift amount into ecx first, and restore the registers afterwards. + if (shift_amount != X86::ecx) { + swap(shift_amount, X86::ecx); + + // E.g. transform "shll %eax, %eax" -> "xchgl %eax, %ecx; shll %ecx, %ecx; xchgl %eax, %ecx" + if (dest == shift_amount) + m_assembler.shll_CLr(X86::ecx); + // E.g. transform "shll %eax, %ecx" -> "xchgl %eax, %ecx; shll %ecx, %eax; xchgl %eax, %ecx" + else if (dest == X86::ecx) + m_assembler.shll_CLr(shift_amount); + // E.g. transform "shll %eax, %ebx" -> "xchgl %eax, %ecx; shll %ecx, %ebx; xchgl %eax, %ecx" + else + m_assembler.shll_CLr(dest); + + swap(shift_amount, X86::ecx); + } else + m_assembler.shll_CLr(dest); + } + + // Take the value from dividend, divide it by divisor, and put the remainder in remainder. + // For now, this operation has specific register requirements, and the three register must + // be unique. It is unfortunate to expose this in the MacroAssembler interface, however + // given the complexity to fix, the fact that it is not uncommmon for processors to have + // specific register requirements on this operation (e.g. Mips result in 'hi'), or to not + // support a hardware divide at all, it may not be + void mod32(RegisterID divisor, RegisterID dividend, RegisterID remainder) + { +#ifdef NDEBUG +#pragma unused(dividend,remainder) +#else + ASSERT((dividend == X86::eax) && (remainder == X86::edx)); + ASSERT((dividend != divisor) && (remainder != divisor)); +#endif + + m_assembler.cdq(); + m_assembler.idivl_r(divisor); + } + + void mul32(RegisterID src, RegisterID dest) + { + m_assembler.imull_rr(src, dest); + } + + void mul32(Imm32 imm, RegisterID src, RegisterID dest) + { + m_assembler.imull_i32r(src, imm.m_value, dest); + } + + void not32(RegisterID srcDest) + { + m_assembler.notl_r(srcDest); + } + + void orPtr(RegisterID src, RegisterID dest) + { +#if PLATFORM(X86_64) + m_assembler.orq_rr(src, dest); +#else + or32(src, dest); +#endif + } + + void orPtr(ImmPtr imm, RegisterID dest) + { +#if PLATFORM(X86_64) + move(imm, scratchRegister); + m_assembler.orq_rr(scratchRegister, dest); +#else + or32(Imm32(imm), dest); +#endif + } + + void orPtr(Imm32 imm, RegisterID dest) + { +#if PLATFORM(X86_64) + m_assembler.orq_ir(imm.m_value, dest); +#else + or32(imm, dest); +#endif + } + + void or32(RegisterID src, RegisterID dest) + { + m_assembler.orl_rr(src, dest); + } + + void or32(Imm32 imm, RegisterID dest) + { + m_assembler.orl_ir(imm.m_value, dest); + } + + void rshiftPtr(RegisterID shift_amount, RegisterID dest) + { +#if PLATFORM(X86_64) + // On x86 we can only shift by ecx; if asked to shift by another register we'll + // need rejig the shift amount into ecx first, and restore the registers afterwards. + if (shift_amount != X86::ecx) { + swap(shift_amount, X86::ecx); + + // E.g. transform "shll %eax, %eax" -> "xchgl %eax, %ecx; shll %ecx, %ecx; xchgl %eax, %ecx" + if (dest == shift_amount) + m_assembler.sarq_CLr(X86::ecx); + // E.g. transform "shll %eax, %ecx" -> "xchgl %eax, %ecx; shll %ecx, %eax; xchgl %eax, %ecx" + else if (dest == X86::ecx) + m_assembler.sarq_CLr(shift_amount); + // E.g. transform "shll %eax, %ebx" -> "xchgl %eax, %ecx; shll %ecx, %ebx; xchgl %eax, %ecx" + else + m_assembler.sarq_CLr(dest); + + swap(shift_amount, X86::ecx); + } else + m_assembler.sarq_CLr(dest); +#else + rshift32(shift_amount, dest); +#endif + } + + void rshiftPtr(Imm32 imm, RegisterID dest) + { +#if PLATFORM(X86_64) + m_assembler.sarq_i8r(imm.m_value, dest); +#else + rshift32(imm, dest); +#endif + } + + void rshift32(RegisterID shift_amount, RegisterID dest) + { + // On x86 we can only shift by ecx; if asked to shift by another register we'll + // need rejig the shift amount into ecx first, and restore the registers afterwards. + if (shift_amount != X86::ecx) { + swap(shift_amount, X86::ecx); + + // E.g. transform "shll %eax, %eax" -> "xchgl %eax, %ecx; shll %ecx, %ecx; xchgl %eax, %ecx" + if (dest == shift_amount) + m_assembler.sarl_CLr(X86::ecx); + // E.g. transform "shll %eax, %ecx" -> "xchgl %eax, %ecx; shll %ecx, %eax; xchgl %eax, %ecx" + else if (dest == X86::ecx) + m_assembler.sarl_CLr(shift_amount); + // E.g. transform "shll %eax, %ebx" -> "xchgl %eax, %ecx; shll %ecx, %ebx; xchgl %eax, %ecx" + else + m_assembler.sarl_CLr(dest); + + swap(shift_amount, X86::ecx); + } else + m_assembler.sarl_CLr(dest); + } + + void rshift32(Imm32 imm, RegisterID dest) + { + m_assembler.sarl_i8r(imm.m_value, dest); + } + + void subPtr(RegisterID src, RegisterID dest) + { +#if PLATFORM(X86_64) + m_assembler.subq_rr(src, dest); +#else + sub32(src, dest); +#endif + } + + void subPtr(Imm32 imm, RegisterID dest) + { +#if PLATFORM(X86_64) + m_assembler.subq_ir(imm.m_value, dest); +#else + sub32(imm, dest); +#endif + } + + void subPtr(ImmPtr imm, RegisterID dest) + { +#if PLATFORM(X86_64) + move(imm, scratchRegister); + m_assembler.subq_rr(scratchRegister, dest); +#else + sub32(Imm32(imm), dest); +#endif + } + + void sub32(RegisterID src, RegisterID dest) + { + m_assembler.subl_rr(src, dest); + } + + void sub32(Imm32 imm, RegisterID dest) + { + m_assembler.subl_ir(imm.m_value, dest); + } + + void sub32(Imm32 imm, Address address) + { + m_assembler.subl_im(imm.m_value, address.offset, address.base); + } + + void sub32(Imm32 imm, AbsoluteAddress address) + { +#if PLATFORM(X86_64) + move(ImmPtr(address.m_ptr), scratchRegister); + sub32(imm, Address(scratchRegister)); +#else + m_assembler.subl_im(imm.m_value, address.m_ptr); +#endif + } + + void sub32(Address src, RegisterID dest) + { + m_assembler.subl_mr(src.offset, src.base, dest); + } + + void xorPtr(RegisterID src, RegisterID dest) + { +#if PLATFORM(X86_64) + m_assembler.xorq_rr(src, dest); +#else + xor32(src, dest); +#endif + } + + void xorPtr(Imm32 imm, RegisterID srcDest) + { +#if PLATFORM(X86_64) + m_assembler.xorq_ir(imm.m_value, srcDest); +#else + xor32(imm, srcDest); +#endif + } + + void xor32(RegisterID src, RegisterID dest) + { + m_assembler.xorl_rr(src, dest); + } + + void xor32(Imm32 imm, RegisterID srcDest) + { + m_assembler.xorl_ir(imm.m_value, srcDest); + } + + + // Memory access operations: + // + // Loads are of the form load(address, destination) and stores of the form + // store(source, address). The source for a store may be an Imm32. Address + // operand objects to loads and store will be implicitly constructed if a + // register is passed. + + void loadPtr(ImplicitAddress address, RegisterID dest) + { +#if PLATFORM(X86_64) + m_assembler.movq_mr(address.offset, address.base, dest); +#else + load32(address, dest); +#endif + } + + DataLabel32 loadPtrWithAddressOffsetPatch(Address address, RegisterID dest) + { +#if PLATFORM(X86_64) + m_assembler.movq_mr_disp32(address.offset, address.base, dest); + return DataLabel32(this); +#else + m_assembler.movl_mr_disp32(address.offset, address.base, dest); + return DataLabel32(this); +#endif + } + + void loadPtr(BaseIndex address, RegisterID dest) + { +#if PLATFORM(X86_64) + m_assembler.movq_mr(address.offset, address.base, address.index, address.scale, dest); +#else + load32(address, dest); +#endif + } + + void loadPtr(void* address, RegisterID dest) + { +#if PLATFORM(X86_64) + if (dest == X86::eax) + m_assembler.movq_mEAX(address); + else { + move(X86::eax, dest); + m_assembler.movq_mEAX(address); + swap(X86::eax, dest); + } +#else + load32(address, dest); +#endif + } + + void load32(ImplicitAddress address, RegisterID dest) + { + m_assembler.movl_mr(address.offset, address.base, dest); + } + + void load32(BaseIndex address, RegisterID dest) + { + m_assembler.movl_mr(address.offset, address.base, address.index, address.scale, dest); + } + + void load32(void* address, RegisterID dest) + { +#if PLATFORM(X86_64) + if (dest == X86::eax) + m_assembler.movl_mEAX(address); + else { + move(X86::eax, dest); + m_assembler.movl_mEAX(address); + swap(X86::eax, dest); + } +#else + m_assembler.movl_mr(address, dest); +#endif + } + + void load16(BaseIndex address, RegisterID dest) + { + m_assembler.movzwl_mr(address.offset, address.base, address.index, address.scale, dest); + } + + void storePtr(RegisterID src, ImplicitAddress address) + { +#if PLATFORM(X86_64) + m_assembler.movq_rm(src, address.offset, address.base); +#else + store32(src, address); +#endif + } + + DataLabel32 storePtrWithAddressOffsetPatch(RegisterID src, Address address) + { +#if PLATFORM(X86_64) + m_assembler.movq_rm_disp32(src, address.offset, address.base); + return DataLabel32(this); +#else + m_assembler.movl_rm_disp32(src, address.offset, address.base); + return DataLabel32(this); +#endif + } + + void storePtr(RegisterID src, BaseIndex address) + { +#if PLATFORM(X86_64) + m_assembler.movq_rm(src, address.offset, address.base, address.index, address.scale); +#else + store32(src, address); +#endif + } + + void storePtr(ImmPtr imm, ImplicitAddress address) + { +#if PLATFORM(X86_64) + move(imm, scratchRegister); + storePtr(scratchRegister, address); +#else + m_assembler.movl_i32m(imm.asIntptr(), address.offset, address.base); +#endif + } + +#if !PLATFORM(X86_64) + void storePtr(ImmPtr imm, void* address) + { + store32(Imm32(imm), address); + } +#endif + + DataLabelPtr storePtrWithPatch(Address address) + { +#if PLATFORM(X86_64) + m_assembler.movq_i64r(0, scratchRegister); + DataLabelPtr label(this); + storePtr(scratchRegister, address); + return label; +#else + m_assembler.movl_i32m(0, address.offset, address.base); + return DataLabelPtr(this); +#endif + } + + void store32(RegisterID src, ImplicitAddress address) + { + m_assembler.movl_rm(src, address.offset, address.base); + } + + void store32(RegisterID src, BaseIndex address) + { + m_assembler.movl_rm(src, address.offset, address.base, address.index, address.scale); + } + + void store32(Imm32 imm, ImplicitAddress address) + { + m_assembler.movl_i32m(imm.m_value, address.offset, address.base); + } + + void store32(Imm32 imm, void* address) + { +#if PLATFORM(X86_64) + move(X86::eax, scratchRegister); + move(imm, X86::eax); + m_assembler.movl_EAXm(address); + move(scratchRegister, X86::eax); +#else + m_assembler.movl_i32m(imm.m_value, address); +#endif + } + + + // Stack manipulation operations: + // + // The ABI is assumed to provide a stack abstraction to memory, + // containing machine word sized units of data. Push and pop + // operations add and remove a single register sized unit of data + // to or from the stack. Peek and poke operations read or write + // values on the stack, without moving the current stack position. + + void pop(RegisterID dest) + { + m_assembler.pop_r(dest); + } + + void push(RegisterID src) + { + m_assembler.push_r(src); + } + + void push(Address address) + { + m_assembler.push_m(address.offset, address.base); + } + + void push(Imm32 imm) + { + m_assembler.push_i32(imm.m_value); + } + + void pop() + { + addPtr(Imm32(sizeof(void*)), X86::esp); + } + + void peek(RegisterID dest, int index = 0) + { + loadPtr(Address(X86::esp, (index * sizeof(void *))), dest); + } + + void poke(RegisterID src, int index = 0) + { + storePtr(src, Address(X86::esp, (index * sizeof(void *)))); + } + + void poke(Imm32 value, int index = 0) + { + store32(value, Address(X86::esp, (index * sizeof(void *)))); + } + + void poke(ImmPtr imm, int index = 0) + { + storePtr(imm, Address(X86::esp, (index * sizeof(void *)))); + } + + // Register move operations: + // + // Move values in registers. + + void move(Imm32 imm, RegisterID dest) + { + // Note: on 64-bit the Imm32 value is zero extended into the register, it + // may be useful to have a separate version that sign extends the value? + if (!imm.m_value) + m_assembler.xorl_rr(dest, dest); + else + m_assembler.movl_i32r(imm.m_value, dest); + } + + void move(RegisterID src, RegisterID dest) + { + // Note: on 64-bit this is is a full register move; perhaps it would be + // useful to have separate move32 & movePtr, with move32 zero extending? +#if PLATFORM(X86_64) + m_assembler.movq_rr(src, dest); +#else + m_assembler.movl_rr(src, dest); +#endif + } + + void move(ImmPtr imm, RegisterID dest) + { +#if PLATFORM(X86_64) + if (CAN_SIGN_EXTEND_U32_64(imm.asIntptr())) + m_assembler.movl_i32r(static_cast<int32_t>(imm.asIntptr()), dest); + else + m_assembler.movq_i64r(imm.asIntptr(), dest); +#else + m_assembler.movl_i32r(imm.asIntptr(), dest); +#endif + } + + void swap(RegisterID reg1, RegisterID reg2) + { +#if PLATFORM(X86_64) + m_assembler.xchgq_rr(reg1, reg2); +#else + m_assembler.xchgl_rr(reg1, reg2); +#endif + } + + void signExtend32ToPtr(RegisterID src, RegisterID dest) + { +#if PLATFORM(X86_64) + m_assembler.movsxd_rr(src, dest); +#else + if (src != dest) + move(src, dest); +#endif + } + + void zeroExtend32ToPtr(RegisterID src, RegisterID dest) + { +#if PLATFORM(X86_64) + m_assembler.movl_rr(src, dest); +#else + if (src != dest) + move(src, dest); +#endif + } + + + // Forwards / external control flow operations: + // + // This set of jump and conditional branch operations return a Jump + // object which may linked at a later point, allow forwards jump, + // or jumps that will require external linkage (after the code has been + // relocated). + // + // For branches, signed <, >, <= and >= are denoted as l, g, le, and ge + // respecitvely, for unsigned comparisons the names b, a, be, and ae are + // used (representing the names 'below' and 'above'). + // + // Operands to the comparision are provided in the expected order, e.g. + // jle32(reg1, Imm32(5)) will branch if the value held in reg1, when + // treated as a signed 32bit value, is less than or equal to 5. + // + // jz and jnz test whether the first operand is equal to zero, and take + // an optional second operand of a mask under which to perform the test. + +private: + void compareImm32ForBranch(RegisterID left, int32_t right) + { + m_assembler.cmpl_ir(right, left); + } + + void compareImm32ForBranchEquality(RegisterID reg, int32_t imm) + { + if (!imm) + m_assembler.testl_rr(reg, reg); + else + m_assembler.cmpl_ir(imm, reg); + } + + void compareImm32ForBranchEquality(Address address, int32_t imm) + { + m_assembler.cmpl_im(imm, address.offset, address.base); + } + + void testImm32(RegisterID reg, Imm32 mask) + { + // if we are only interested in the low seven bits, this can be tested with a testb + if (mask.m_value == -1) + m_assembler.testl_rr(reg, reg); + else if ((mask.m_value & ~0x7f) == 0) + m_assembler.testb_i8r(mask.m_value, reg); + else + m_assembler.testl_i32r(mask.m_value, reg); + } + + void testImm32(Address address, Imm32 mask) + { + if (mask.m_value == -1) + m_assembler.cmpl_im(0, address.offset, address.base); + else + m_assembler.testl_i32m(mask.m_value, address.offset, address.base); + } + + void testImm32(BaseIndex address, Imm32 mask) + { + if (mask.m_value == -1) + m_assembler.cmpl_im(0, address.offset, address.base, address.index, address.scale); + else + m_assembler.testl_i32m(mask.m_value, address.offset, address.base, address.index, address.scale); + } + +#if PLATFORM(X86_64) + void compareImm64ForBranch(RegisterID left, int32_t right) + { + m_assembler.cmpq_ir(right, left); + } + + void compareImm64ForBranchEquality(RegisterID reg, int32_t imm) + { + if (!imm) + m_assembler.testq_rr(reg, reg); + else + m_assembler.cmpq_ir(imm, reg); + } + + void testImm64(RegisterID reg, Imm32 mask) + { + // if we are only interested in the low seven bits, this can be tested with a testb + 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); + } + + void testImm64(Address address, Imm32 mask) + { + if (mask.m_value == -1) + m_assembler.cmpq_im(0, address.offset, address.base); + else + m_assembler.testq_i32m(mask.m_value, address.offset, address.base); + } + + void testImm64(BaseIndex address, Imm32 mask) + { + if (mask.m_value == -1) + m_assembler.cmpq_im(0, address.offset, address.base, address.index, address.scale); + else + m_assembler.testq_i32m(mask.m_value, address.offset, address.base, address.index, address.scale); + } +#endif + +public: + Jump ja32(RegisterID left, Imm32 right) + { + compareImm32ForBranch(left, right.m_value); + return Jump(m_assembler.ja()); + } + + Jump jaePtr(RegisterID left, RegisterID right) + { +#if PLATFORM(X86_64) + m_assembler.cmpq_rr(right, left); + return Jump(m_assembler.jae()); +#else + return jae32(left, right); +#endif + } + + Jump jaePtr(RegisterID reg, ImmPtr ptr) + { +#if PLATFORM(X86_64) + intptr_t imm = ptr.asIntptr(); + if (CAN_SIGN_EXTEND_32_64(imm)) { + compareImm64ForBranch(reg, imm); + return Jump(m_assembler.jae()); + } else { + move(ptr, scratchRegister); + return jaePtr(reg, scratchRegister); + } +#else + return jae32(reg, Imm32(ptr)); +#endif + } + + Jump jae32(RegisterID left, RegisterID right) + { + m_assembler.cmpl_rr(right, left); + return Jump(m_assembler.jae()); + } + + Jump jae32(RegisterID left, Imm32 right) + { + compareImm32ForBranch(left, right.m_value); + return Jump(m_assembler.jae()); + } + + Jump jae32(RegisterID left, Address right) + { + m_assembler.cmpl_mr(right.offset, right.base, left); + return Jump(m_assembler.jae()); + } + + Jump jae32(Address left, RegisterID right) + { + m_assembler.cmpl_rm(right, left.offset, left.base); + return Jump(m_assembler.jae()); + } + + Jump jbPtr(RegisterID left, RegisterID right) + { +#if PLATFORM(X86_64) + m_assembler.cmpq_rr(right, left); + return Jump(m_assembler.jb()); +#else + return jb32(left, right); +#endif + } + + Jump jbPtr(RegisterID reg, ImmPtr ptr) + { +#if PLATFORM(X86_64) + intptr_t imm = ptr.asIntptr(); + if (CAN_SIGN_EXTEND_32_64(imm)) { + compareImm64ForBranch(reg, imm); + return Jump(m_assembler.jb()); + } else { + move(ptr, scratchRegister); + return jbPtr(reg, scratchRegister); + } +#else + return jb32(reg, Imm32(ptr)); +#endif + } + + Jump jb32(RegisterID left, RegisterID right) + { + m_assembler.cmpl_rr(right, left); + return Jump(m_assembler.jb()); + } + + Jump jb32(RegisterID left, Imm32 right) + { + compareImm32ForBranch(left, right.m_value); + return Jump(m_assembler.jb()); + } + + Jump jb32(RegisterID left, Address right) + { + m_assembler.cmpl_mr(right.offset, right.base, left); + return Jump(m_assembler.jb()); + } + + Jump jePtr(RegisterID op1, RegisterID op2) + { +#if PLATFORM(X86_64) + m_assembler.cmpq_rr(op1, op2); + return Jump(m_assembler.je()); +#else + return je32(op1, op2); +#endif + } + + Jump jePtr(RegisterID reg, Address address) + { +#if PLATFORM(X86_64) + m_assembler.cmpq_rm(reg, address.offset, address.base); +#else + m_assembler.cmpl_rm(reg, address.offset, address.base); +#endif + return Jump(m_assembler.je()); + } + + Jump jePtr(RegisterID reg, ImmPtr ptr) + { +#if PLATFORM(X86_64) + intptr_t imm = ptr.asIntptr(); + if (CAN_SIGN_EXTEND_32_64(imm)) { + compareImm64ForBranchEquality(reg, imm); + return Jump(m_assembler.je()); + } else { + move(ptr, scratchRegister); + return jePtr(scratchRegister, reg); + } +#else + return je32(reg, Imm32(ptr)); +#endif + } + + Jump jePtr(Address address, ImmPtr imm) + { +#if PLATFORM(X86_64) + move(imm, scratchRegister); + return jePtr(scratchRegister, address); +#else + return je32(address, Imm32(imm)); +#endif + } + + Jump je32(RegisterID op1, RegisterID op2) + { + m_assembler.cmpl_rr(op1, op2); + return Jump(m_assembler.je()); + } + + Jump je32(Address op1, RegisterID op2) + { + m_assembler.cmpl_mr(op1.offset, op1.base, op2); + return Jump(m_assembler.je()); + } + + Jump je32(RegisterID reg, Imm32 imm) + { + compareImm32ForBranchEquality(reg, imm.m_value); + return Jump(m_assembler.je()); + } + + Jump je32(Address address, Imm32 imm) + { + compareImm32ForBranchEquality(address, imm.m_value); + return Jump(m_assembler.je()); + } + + Jump je16(RegisterID op1, BaseIndex op2) + { + m_assembler.cmpw_rm(op1, op2.offset, op2.base, op2.index, op2.scale); + return Jump(m_assembler.je()); + } + + Jump jg32(RegisterID left, RegisterID right) + { + m_assembler.cmpl_rr(right, left); + return Jump(m_assembler.jg()); + } + + Jump jg32(RegisterID reg, Address address) + { + m_assembler.cmpl_mr(address.offset, address.base, reg); + return Jump(m_assembler.jg()); + } + + Jump jgePtr(RegisterID left, RegisterID right) + { +#if PLATFORM(X86_64) + m_assembler.cmpq_rr(right, left); + return Jump(m_assembler.jge()); +#else + return jge32(left, right); +#endif + } + + Jump jgePtr(RegisterID reg, ImmPtr ptr) + { +#if PLATFORM(X86_64) + intptr_t imm = ptr.asIntptr(); + if (CAN_SIGN_EXTEND_32_64(imm)) { + compareImm64ForBranch(reg, imm); + return Jump(m_assembler.jge()); + } else { + move(ptr, scratchRegister); + return jgePtr(reg, scratchRegister); + } +#else + return jge32(reg, Imm32(ptr)); +#endif + } + + Jump jge32(RegisterID left, RegisterID right) + { + m_assembler.cmpl_rr(right, left); + return Jump(m_assembler.jge()); + } + + Jump jge32(RegisterID left, Imm32 right) + { + compareImm32ForBranch(left, right.m_value); + return Jump(m_assembler.jge()); + } + + Jump jlPtr(RegisterID left, RegisterID right) + { +#if PLATFORM(X86_64) + m_assembler.cmpq_rr(right, left); + return Jump(m_assembler.jl()); +#else + return jl32(left, right); +#endif + } + + Jump jlPtr(RegisterID reg, ImmPtr ptr) + { +#if PLATFORM(X86_64) + intptr_t imm = ptr.asIntptr(); + if (CAN_SIGN_EXTEND_32_64(imm)) { + compareImm64ForBranch(reg, imm); + return Jump(m_assembler.jl()); + } else { + move(ptr, scratchRegister); + return jlPtr(reg, scratchRegister); + } +#else + return jl32(reg, Imm32(ptr)); +#endif + } + + Jump jl32(RegisterID left, RegisterID right) + { + m_assembler.cmpl_rr(right, left); + return Jump(m_assembler.jl()); + } + + Jump jl32(RegisterID left, Imm32 right) + { + compareImm32ForBranch(left, right.m_value); + return Jump(m_assembler.jl()); + } + + Jump jlePtr(RegisterID left, RegisterID right) + { +#if PLATFORM(X86_64) + m_assembler.cmpq_rr(right, left); + return Jump(m_assembler.jle()); +#else + return jle32(left, right); +#endif + } + + Jump jlePtr(RegisterID reg, ImmPtr ptr) + { +#if PLATFORM(X86_64) + intptr_t imm = ptr.asIntptr(); + if (CAN_SIGN_EXTEND_32_64(imm)) { + compareImm64ForBranch(reg, imm); + return Jump(m_assembler.jle()); + } else { + move(ptr, scratchRegister); + return jlePtr(reg, scratchRegister); + } +#else + return jle32(reg, Imm32(ptr)); +#endif + } + + Jump jle32(RegisterID left, RegisterID right) + { + m_assembler.cmpl_rr(right, left); + return Jump(m_assembler.jle()); + } + + Jump jle32(RegisterID left, Imm32 right) + { + compareImm32ForBranch(left, right.m_value); + return Jump(m_assembler.jle()); + } + + Jump jnePtr(RegisterID op1, RegisterID op2) + { +#if PLATFORM(X86_64) + m_assembler.cmpq_rr(op1, op2); + return Jump(m_assembler.jne()); +#else + return jne32(op1, op2); +#endif + } + + Jump jnePtr(RegisterID reg, Address address) + { +#if PLATFORM(X86_64) + m_assembler.cmpq_rm(reg, address.offset, address.base); +#else + m_assembler.cmpl_rm(reg, address.offset, address.base); +#endif + return Jump(m_assembler.jne()); + } + + Jump jnePtr(RegisterID reg, AbsoluteAddress address) + { +#if PLATFORM(X86_64) + move(ImmPtr(address.m_ptr), scratchRegister); + return jnePtr(reg, Address(scratchRegister)); +#else + m_assembler.cmpl_rm(reg, address.m_ptr); + return Jump(m_assembler.jne()); +#endif + } + + Jump jnePtr(RegisterID reg, ImmPtr ptr) + { +#if PLATFORM(X86_64) + intptr_t imm = ptr.asIntptr(); + if (CAN_SIGN_EXTEND_32_64(imm)) { + compareImm64ForBranchEquality(reg, imm); + return Jump(m_assembler.jne()); + } else { + move(ptr, scratchRegister); + return jnePtr(scratchRegister, reg); + } +#else + return jne32(reg, Imm32(ptr)); +#endif + } + + Jump jnePtr(Address address, ImmPtr imm) + { +#if PLATFORM(X86_64) + move(imm, scratchRegister); + return jnePtr(scratchRegister, address); +#else + return jne32(address, Imm32(imm)); +#endif + } + +#if !PLATFORM(X86_64) + Jump jnePtr(AbsoluteAddress address, ImmPtr imm) + { + m_assembler.cmpl_im(imm.asIntptr(), address.m_ptr); + return Jump(m_assembler.jne()); + } +#endif + + Jump jnePtrWithPatch(RegisterID reg, DataLabelPtr& dataLabel, ImmPtr initialValue = ImmPtr(0)) + { +#if PLATFORM(X86_64) + m_assembler.movq_i64r(initialValue.asIntptr(), scratchRegister); + dataLabel = DataLabelPtr(this); + return jnePtr(scratchRegister, reg); +#else + m_assembler.cmpl_ir_force32(initialValue.asIntptr(), reg); + dataLabel = DataLabelPtr(this); + return Jump(m_assembler.jne()); +#endif + } + + Jump jnePtrWithPatch(Address address, DataLabelPtr& dataLabel, ImmPtr initialValue = ImmPtr(0)) + { +#if PLATFORM(X86_64) + m_assembler.movq_i64r(initialValue.asIntptr(), scratchRegister); + dataLabel = DataLabelPtr(this); + return jnePtr(scratchRegister, address); +#else + m_assembler.cmpl_im_force32(initialValue.asIntptr(), address.offset, address.base); + dataLabel = DataLabelPtr(this); + return Jump(m_assembler.jne()); +#endif + } + + Jump jne32(RegisterID op1, RegisterID op2) + { + m_assembler.cmpl_rr(op1, op2); + return Jump(m_assembler.jne()); + } + + Jump jne32(RegisterID reg, Imm32 imm) + { + compareImm32ForBranchEquality(reg, imm.m_value); + return Jump(m_assembler.jne()); + } + + Jump jne32(Address address, Imm32 imm) + { + compareImm32ForBranchEquality(address, imm.m_value); + return Jump(m_assembler.jne()); + } + + Jump jne32(Address address, RegisterID reg) + { + m_assembler.cmpl_rm(reg, address.offset, address.base); + return Jump(m_assembler.jne()); + } + + Jump jnzPtr(RegisterID reg, RegisterID mask) + { +#if PLATFORM(X86_64) + m_assembler.testq_rr(reg, mask); + return Jump(m_assembler.jne()); +#else + return jnz32(reg, mask); +#endif + } + + Jump jnzPtr(RegisterID reg, Imm32 mask = Imm32(-1)) + { +#if PLATFORM(X86_64) + testImm64(reg, mask); + return Jump(m_assembler.jne()); +#else + return jnz32(reg, mask); +#endif + } + + Jump jnzPtr(RegisterID reg, ImmPtr mask) + { +#if PLATFORM(X86_64) + move(mask, scratchRegister); + m_assembler.testq_rr(scratchRegister, reg); + return Jump(m_assembler.jne()); +#else + return jnz32(reg, Imm32(mask)); +#endif + } + + Jump jnzPtr(Address address, Imm32 mask = Imm32(-1)) + { +#if PLATFORM(X86_64) + testImm64(address, mask); + return Jump(m_assembler.jne()); +#else + return jnz32(address, mask); +#endif + } + + Jump jnz32(RegisterID reg, RegisterID mask) + { + m_assembler.testl_rr(reg, mask); + return Jump(m_assembler.jne()); + } + + Jump jnz32(RegisterID reg, Imm32 mask = Imm32(-1)) + { + testImm32(reg, mask); + return Jump(m_assembler.jne()); + } + + Jump jnz32(Address address, Imm32 mask = Imm32(-1)) + { + testImm32(address, mask); + return Jump(m_assembler.jne()); + } + + Jump jzPtr(RegisterID reg, RegisterID mask) + { +#if PLATFORM(X86_64) + m_assembler.testq_rr(reg, mask); + return Jump(m_assembler.je()); +#else + return jz32(reg, mask); +#endif + } + + Jump jzPtr(RegisterID reg, Imm32 mask = Imm32(-1)) + { +#if PLATFORM(X86_64) + testImm64(reg, mask); + return Jump(m_assembler.je()); +#else + return jz32(reg, mask); +#endif + } + + Jump jzPtr(RegisterID reg, ImmPtr mask) + { +#if PLATFORM(X86_64) + move(mask, scratchRegister); + m_assembler.testq_rr(scratchRegister, reg); + return Jump(m_assembler.je()); +#else + return jz32(reg, Imm32(mask)); +#endif + } + + Jump jzPtr(Address address, Imm32 mask = Imm32(-1)) + { +#if PLATFORM(X86_64) + testImm64(address, mask); + return Jump(m_assembler.je()); +#else + return jz32(address, mask); +#endif + } + + Jump jzPtr(BaseIndex address, Imm32 mask = Imm32(-1)) + { +#if PLATFORM(X86_64) + testImm64(address, mask); + return Jump(m_assembler.je()); +#else + return jz32(address, mask); +#endif + } + + Jump jz32(RegisterID reg, RegisterID mask) + { + m_assembler.testl_rr(reg, mask); + return Jump(m_assembler.je()); + } + + Jump jz32(RegisterID reg, Imm32 mask = Imm32(-1)) + { + testImm32(reg, mask); + return Jump(m_assembler.je()); + } + + Jump jz32(Address address, Imm32 mask = Imm32(-1)) + { + testImm32(address, mask); + return Jump(m_assembler.je()); + } + + Jump jz32(BaseIndex address, Imm32 mask = Imm32(-1)) + { + testImm32(address, mask); + return Jump(m_assembler.je()); + } + + Jump jump() + { + return Jump(m_assembler.jmp()); + } + + + // Backwards, local control flow operations: + // + // These operations provide a shorter notation for local + // backwards branches, which may be both more convenient + // for the user, and for the programmer, and for the + // assembler (allowing shorter values to be used in + // relative offsets). + // + // The code sequence: + // + // Label topOfLoop(this); + // // ... + // jne32(reg1, reg2, topOfLoop); + // + // Is equivalent to the longer, potentially less efficient form: + // + // Label topOfLoop(this); + // // ... + // jne32(reg1, reg2).linkTo(topOfLoop); + + void jae32(RegisterID left, Address right, Label target) + { + jae32(left, right).linkTo(target, this); + } + + void je32(RegisterID op1, Imm32 imm, Label target) + { + je32(op1, imm).linkTo(target, this); + } + + void je16(RegisterID op1, BaseIndex op2, Label target) + { + je16(op1, op2).linkTo(target, this); + } + + void jl32(RegisterID left, Imm32 right, Label target) + { + jl32(left, right).linkTo(target, this); + } + + void jle32(RegisterID left, RegisterID right, Label target) + { + jle32(left, right).linkTo(target, this); + } + + void jnePtr(RegisterID op1, ImmPtr imm, Label target) + { + jnePtr(op1, imm).linkTo(target, this); + } + + void jne32(RegisterID op1, RegisterID op2, Label target) + { + jne32(op1, op2).linkTo(target, this); + } + + void jne32(RegisterID op1, Imm32 imm, Label target) + { + jne32(op1, imm).linkTo(target, this); + } + + void jzPtr(RegisterID reg, Label target) + { + jzPtr(reg).linkTo(target, this); + } + + void jump(Label target) + { + m_assembler.link(m_assembler.jmp(), target.m_label); + } + + void jump(RegisterID target) + { + m_assembler.jmp_r(target); + } + + // Address is a memory location containing the address to jump to + void jump(Address address) + { + m_assembler.jmp_m(address.offset, address.base); + } + + + // Arithmetic control flow operations: + // + // This set of conditional branch operations branch based + // on the result of an arithmetic operation. The operation + // is performed as normal, storing the result. + // + // * jz operations branch if the result is zero. + // * jo operations branch if the (signed) arithmetic + // operation caused an overflow to occur. + + Jump jnzSubPtr(Imm32 imm, RegisterID dest) + { + subPtr(imm, dest); + return Jump(m_assembler.jne()); + } + + Jump jnzSub32(Imm32 imm, RegisterID dest) + { + sub32(imm, dest); + return Jump(m_assembler.jne()); + } + + Jump joAddPtr(RegisterID src, RegisterID dest) + { + addPtr(src, dest); + return Jump(m_assembler.jo()); + } + + Jump joAdd32(RegisterID src, RegisterID dest) + { + add32(src, dest); + return Jump(m_assembler.jo()); + } + + Jump joAdd32(Imm32 imm, RegisterID dest) + { + add32(imm, dest); + return Jump(m_assembler.jo()); + } + + Jump joMul32(RegisterID src, RegisterID dest) + { + mul32(src, dest); + return Jump(m_assembler.jo()); + } + + Jump joMul32(Imm32 imm, RegisterID src, RegisterID dest) + { + mul32(imm, src, dest); + return Jump(m_assembler.jo()); + } + + Jump joSub32(RegisterID src, RegisterID dest) + { + sub32(src, dest); + return Jump(m_assembler.jo()); + } + + Jump joSub32(Imm32 imm, RegisterID dest) + { + sub32(imm, dest); + return Jump(m_assembler.jo()); + } + + Jump jzSubPtr(Imm32 imm, RegisterID dest) + { + subPtr(imm, dest); + return Jump(m_assembler.je()); + } + + Jump jzSub32(Imm32 imm, RegisterID dest) + { + sub32(imm, dest); + return Jump(m_assembler.je()); + } + + + // Miscellaneous operations: + + void breakpoint() + { + m_assembler.int3(); + } + + Jump call() + { + return Jump(m_assembler.call()); + } + + // FIXME: why does this return a Jump object? - it can't be linked. + // This may be to get a reference to the return address of the call. + // + // This should probably be handled by a separate label type to a regular + // jump. Todo: add a CallLabel type, for the regular call - can be linked + // like a jump (possibly a subclass of jump?, or possibly casts to a Jump). + // Also add a CallReturnLabel type for this to return (just a more JmpDsty + // form of label, can get the void* after the code has been linked, but can't + // try to link it like a Jump object), and let the CallLabel be cast into a + // CallReturnLabel. + Jump call(RegisterID target) + { + return Jump(m_assembler.call(target)); + } + + Label label() + { + return Label(this); + } + + Label align() + { + m_assembler.align(16); + return Label(this); + } + + ptrdiff_t differenceBetween(Label from, Jump to) + { + return X86Assembler::getDifferenceBetweenLabels(from.m_label, to.m_jmp); + } + + ptrdiff_t differenceBetween(Label from, Label to) + { + return X86Assembler::getDifferenceBetweenLabels(from.m_label, to.m_label); + } + + ptrdiff_t differenceBetween(Label from, DataLabelPtr to) + { + return X86Assembler::getDifferenceBetweenLabels(from.m_label, to.m_label); + } + + ptrdiff_t differenceBetween(Label from, DataLabel32 to) + { + return X86Assembler::getDifferenceBetweenLabels(from.m_label, to.m_label); + } + + ptrdiff_t differenceBetween(DataLabelPtr from, Jump to) + { + return X86Assembler::getDifferenceBetweenLabels(from.m_label, to.m_jmp); + } + + void ret() + { + m_assembler.ret(); + } + + void sete32(RegisterID src, RegisterID srcDest) + { + m_assembler.cmpl_rr(srcDest, src); + m_assembler.sete_r(srcDest); + m_assembler.movzbl_rr(srcDest, srcDest); + } + + void sete32(Imm32 imm, RegisterID srcDest) + { + compareImm32ForBranchEquality(srcDest, imm.m_value); + m_assembler.sete_r(srcDest); + m_assembler.movzbl_rr(srcDest, srcDest); + } + + void setne32(RegisterID src, RegisterID srcDest) + { + m_assembler.cmpl_rr(srcDest, src); + m_assembler.setne_r(srcDest); + m_assembler.movzbl_rr(srcDest, srcDest); + } + + void setne32(Imm32 imm, RegisterID srcDest) + { + compareImm32ForBranchEquality(srcDest, imm.m_value); + m_assembler.setne_r(srcDest); + m_assembler.movzbl_rr(srcDest, srcDest); + } + + // FIXME: + // The mask should be optional... paerhaps the argument order should be + // dest-src, operations always have a dest? ... possibly not true, considering + // asm ops like test, or pseudo ops like pop(). + void setnz32(Address address, Imm32 mask, RegisterID dest) + { + testImm32(address, mask); + m_assembler.setnz_r(dest); + m_assembler.movzbl_rr(dest, dest); + } + + void setz32(Address address, Imm32 mask, RegisterID dest) + { + testImm32(address, mask); + m_assembler.setz_r(dest); + m_assembler.movzbl_rr(dest, dest); + } +}; + +} // namespace JSC + +#endif // ENABLE(ASSEMBLER) + +#endif // MacroAssembler_h diff --git a/JavaScriptCore/assembler/X86Assembler.h b/JavaScriptCore/assembler/X86Assembler.h new file mode 100644 index 0000000..de23e45 --- /dev/null +++ b/JavaScriptCore/assembler/X86Assembler.h @@ -0,0 +1,1704 @@ +/* + * 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 X86Assembler_h +#define X86Assembler_h + +#include <wtf/Platform.h> + +#if ENABLE(ASSEMBLER) && (PLATFORM(X86) || PLATFORM(X86_64)) + +#include "AssemblerBuffer.h" +#include <stdint.h> +#include <wtf/Assertions.h> +#include <wtf/Vector.h> + +namespace JSC { + +inline bool CAN_SIGN_EXTEND_8_32(int32_t value) { return value == (int32_t)(signed char)value; } +#if PLATFORM(X86_64) +inline bool CAN_SIGN_EXTEND_32_64(intptr_t value) { return value == (intptr_t)(int32_t)value; } +inline bool CAN_SIGN_EXTEND_U32_64(intptr_t value) { return value == (intptr_t)(uint32_t)value; } +#endif + +namespace X86 { + typedef enum { + eax, + ecx, + edx, + ebx, + esp, + ebp, + esi, + edi, + +#if PLATFORM(X86_64) + r8, + r9, + r10, + r11, + r12, + r13, + r14, + r15, +#endif + } RegisterID; + + typedef enum { + xmm0, + xmm1, + xmm2, + xmm3, + xmm4, + xmm5, + xmm6, + xmm7, + } XMMRegisterID; +} + +class X86Assembler { +public: + typedef X86::RegisterID RegisterID; + typedef X86::XMMRegisterID XMMRegisterID; + + typedef enum { + OP_ADD_EvGv = 0x01, + OP_ADD_GvEv = 0x03, + OP_OR_EvGv = 0x09, + OP_OR_GvEv = 0x0B, + OP_2BYTE_ESCAPE = 0x0F, + OP_AND_EvGv = 0x21, + OP_SUB_EvGv = 0x29, + OP_SUB_GvEv = 0x2B, + PRE_PREDICT_BRANCH_NOT_TAKEN = 0x2E, + OP_XOR_EvGv = 0x31, + OP_CMP_EvGv = 0x39, + OP_CMP_GvEv = 0x3B, +#if PLATFORM(X86_64) + PRE_REX = 0x40, +#endif + OP_PUSH_EAX = 0x50, + OP_POP_EAX = 0x58, +#if PLATFORM(X86_64) + OP_MOVSXD_GvEv = 0x63, +#endif + PRE_OPERAND_SIZE = 0x66, + PRE_SSE_66 = 0x66, + OP_PUSH_Iz = 0x68, + OP_IMUL_GvEvIz = 0x69, + OP_GROUP1_EvIz = 0x81, + OP_GROUP1_EvIb = 0x83, + OP_TEST_EvGv = 0x85, + OP_XCHG_EvGv = 0x87, + OP_MOV_EvGv = 0x89, + OP_MOV_GvEv = 0x8B, + OP_LEA = 0x8D, + OP_GROUP1A_Ev = 0x8F, + OP_CDQ = 0x99, + OP_MOV_EAXOv = 0xA1, + OP_MOV_OvEAX = 0xA3, + OP_MOV_EAXIv = 0xB8, + OP_GROUP2_EvIb = 0xC1, + OP_RET = 0xC3, + OP_GROUP11_EvIz = 0xC7, + OP_INT3 = 0xCC, + OP_GROUP2_Ev1 = 0xD1, + OP_GROUP2_EvCL = 0xD3, + OP_CALL_rel32 = 0xE8, + OP_JMP_rel32 = 0xE9, + PRE_SSE_F2 = 0xF2, + OP_HLT = 0xF4, + OP_GROUP3_EbIb = 0xF6, + OP_GROUP3_Ev = 0xF7, + OP_GROUP3_EvIz = 0xF7, // OP_GROUP3_Ev has an immediate, when instruction is a test. + OP_GROUP5_Ev = 0xFF, + } OneByteOpcodeID; + + typedef enum { + OP2_MOVSD_VsdWsd = 0x10, + OP2_MOVSD_WsdVsd = 0x11, + OP2_CVTSI2SD_VsdEd = 0x2A, + OP2_CVTTSD2SI_GdWsd = 0x2C, + OP2_UCOMISD_VsdWsd = 0x2E, + OP2_ADDSD_VsdWsd = 0x58, + OP2_MULSD_VsdWsd = 0x59, + OP2_SUBSD_VsdWsd = 0x5C, + OP2_MOVD_VdEd = 0x6E, + OP2_MOVD_EdVd = 0x7E, + OP2_JO_rel32 = 0x80, + OP2_JB_rel32 = 0x82, + OP2_JAE_rel32 = 0x83, + OP2_JE_rel32 = 0x84, + OP2_JNE_rel32 = 0x85, + OP2_JBE_rel32 = 0x86, + OP2_JA_rel32 = 0x87, + OP2_JS_rel32 = 0x88, + OP2_JP_rel32 = 0x8A, + OP2_JL_rel32 = 0x8C, + OP2_JGE_rel32 = 0x8D, + OP2_JLE_rel32 = 0x8E, + OP2_JG_rel32 = 0x8F, + OP_SETE = 0x94, + OP_SETNE = 0x95, + OP2_IMUL_GvEv = 0xAF, + OP2_MOVZX_GvEb = 0xB6, + OP2_MOVZX_GvEw = 0xB7, + OP2_PEXTRW_GdUdIb = 0xC5, + } TwoByteOpcodeID; + + typedef enum { + GROUP1_OP_ADD = 0, + GROUP1_OP_OR = 1, + GROUP1_OP_AND = 4, + GROUP1_OP_SUB = 5, + GROUP1_OP_XOR = 6, + GROUP1_OP_CMP = 7, + + GROUP1A_OP_POP = 0, + + GROUP2_OP_SHL = 4, + GROUP2_OP_SAR = 7, + + GROUP3_OP_TEST = 0, + GROUP3_OP_NOT = 2, + GROUP3_OP_IDIV = 7, + + GROUP5_OP_CALLN = 2, + GROUP5_OP_JMPN = 4, + GROUP5_OP_PUSH = 6, + + GROUP11_MOV = 0, + } GroupOpcodeID; + + // Opaque label types + +private: + class X86InstructionFormatter; +public: + + class JmpSrc { + friend class X86Assembler; + friend class X86InstructionFormatter; + public: + JmpSrc() + : m_offset(-1) + { + } + + private: + JmpSrc(int offset) + : m_offset(offset) + { + } + + int m_offset; + }; + + class JmpDst { + friend class X86Assembler; + friend class X86InstructionFormatter; + public: + JmpDst() + : m_offset(-1) + { + } + + private: + JmpDst(int offset) + : m_offset(offset) + { + } + + int m_offset; + }; + + X86Assembler() + { + } + + size_t size() const { return m_formatter.size(); } + + // Stack operations: + + void push_r(RegisterID reg) + { + m_formatter.oneByteOp(OP_PUSH_EAX, reg); + } + + void pop_r(RegisterID reg) + { + m_formatter.oneByteOp(OP_POP_EAX, reg); + } + + void push_i32(int imm) + { + m_formatter.oneByteOp(OP_PUSH_Iz); + m_formatter.immediate32(imm); + } + + void push_m(int offset, RegisterID base) + { + m_formatter.oneByteOp(OP_GROUP5_Ev, GROUP5_OP_PUSH, base, offset); + } + + void pop_m(int offset, RegisterID base) + { + m_formatter.oneByteOp(OP_GROUP1A_Ev, GROUP1A_OP_POP, base, offset); + } + + // Arithmetic operations: + + void addl_rr(RegisterID src, RegisterID dst) + { + m_formatter.oneByteOp(OP_ADD_EvGv, src, dst); + } + + void addl_mr(int offset, RegisterID base, RegisterID dst) + { + m_formatter.oneByteOp(OP_ADD_GvEv, dst, base, offset); + } + + void addl_ir(int imm, RegisterID dst) + { + if (CAN_SIGN_EXTEND_8_32(imm)) { + m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_ADD, dst); + m_formatter.immediate8(imm); + } else { + m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_ADD, dst); + m_formatter.immediate32(imm); + } + } + + void addl_im(int imm, int offset, RegisterID base) + { + if (CAN_SIGN_EXTEND_8_32(imm)) { + m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_ADD, base, offset); + m_formatter.immediate8(imm); + } else { + m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_ADD, base, offset); + m_formatter.immediate32(imm); + } + } + +#if PLATFORM(X86_64) + void addq_rr(RegisterID src, RegisterID dst) + { + m_formatter.oneByteOp64(OP_ADD_EvGv, src, dst); + } + + void addq_ir(int imm, RegisterID dst) + { + if (CAN_SIGN_EXTEND_8_32(imm)) { + m_formatter.oneByteOp64(OP_GROUP1_EvIb, GROUP1_OP_ADD, dst); + m_formatter.immediate8(imm); + } else { + m_formatter.oneByteOp64(OP_GROUP1_EvIz, GROUP1_OP_ADD, dst); + m_formatter.immediate32(imm); + } + } +#else + void addl_im(int imm, void* addr) + { + if (CAN_SIGN_EXTEND_8_32(imm)) { + m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_ADD, addr); + m_formatter.immediate8(imm); + } else { + m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_ADD, addr); + m_formatter.immediate32(imm); + } + } +#endif + + void andl_rr(RegisterID src, RegisterID dst) + { + m_formatter.oneByteOp(OP_AND_EvGv, src, dst); + } + + void andl_ir(int imm, RegisterID dst) + { + if (CAN_SIGN_EXTEND_8_32(imm)) { + m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_AND, dst); + m_formatter.immediate8(imm); + } else { + m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_AND, dst); + m_formatter.immediate32(imm); + } + } + +#if PLATFORM(X86_64) + void andq_rr(RegisterID src, RegisterID dst) + { + m_formatter.oneByteOp64(OP_AND_EvGv, src, dst); + } + + void andq_ir(int imm, RegisterID dst) + { + if (CAN_SIGN_EXTEND_8_32(imm)) { + m_formatter.oneByteOp64(OP_GROUP1_EvIb, GROUP1_OP_AND, dst); + m_formatter.immediate8(imm); + } else { + m_formatter.oneByteOp64(OP_GROUP1_EvIz, GROUP1_OP_AND, dst); + m_formatter.immediate32(imm); + } + } +#endif + + void notl_r(RegisterID dst) + { + m_formatter.oneByteOp(OP_GROUP3_Ev, GROUP3_OP_NOT, dst); + } + + void orl_rr(RegisterID src, RegisterID dst) + { + m_formatter.oneByteOp(OP_OR_EvGv, src, dst); + } + + void orl_mr(int offset, RegisterID base, RegisterID dst) + { + m_formatter.oneByteOp(OP_OR_GvEv, dst, base, offset); + } + + void orl_ir(int imm, RegisterID dst) + { + if (CAN_SIGN_EXTEND_8_32(imm)) { + m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_OR, dst); + m_formatter.immediate8(imm); + } else { + m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_OR, dst); + m_formatter.immediate32(imm); + } + } + +#if PLATFORM(X86_64) + void orq_rr(RegisterID src, RegisterID dst) + { + m_formatter.oneByteOp64(OP_OR_EvGv, src, dst); + } + + void orq_ir(int imm, RegisterID dst) + { + if (CAN_SIGN_EXTEND_8_32(imm)) { + m_formatter.oneByteOp64(OP_GROUP1_EvIb, GROUP1_OP_OR, dst); + m_formatter.immediate8(imm); + } else { + m_formatter.oneByteOp64(OP_GROUP1_EvIz, GROUP1_OP_OR, dst); + m_formatter.immediate32(imm); + } + } +#endif + + void subl_rr(RegisterID src, RegisterID dst) + { + m_formatter.oneByteOp(OP_SUB_EvGv, src, dst); + } + + void subl_mr(int offset, RegisterID base, RegisterID dst) + { + m_formatter.oneByteOp(OP_SUB_GvEv, dst, base, offset); + } + + void subl_ir(int imm, RegisterID dst) + { + if (CAN_SIGN_EXTEND_8_32(imm)) { + m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_SUB, dst); + m_formatter.immediate8(imm); + } else { + m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_SUB, dst); + m_formatter.immediate32(imm); + } + } + + void subl_im(int imm, int offset, RegisterID base) + { + if (CAN_SIGN_EXTEND_8_32(imm)) { + m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_SUB, base, offset); + m_formatter.immediate8(imm); + } else { + m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_SUB, base, offset); + m_formatter.immediate32(imm); + } + } + +#if PLATFORM(X86_64) + void subq_rr(RegisterID src, RegisterID dst) + { + m_formatter.oneByteOp64(OP_SUB_EvGv, src, dst); + } + + void subq_ir(int imm, RegisterID dst) + { + if (CAN_SIGN_EXTEND_8_32(imm)) { + m_formatter.oneByteOp64(OP_GROUP1_EvIb, GROUP1_OP_SUB, dst); + m_formatter.immediate8(imm); + } else { + m_formatter.oneByteOp64(OP_GROUP1_EvIz, GROUP1_OP_SUB, dst); + m_formatter.immediate32(imm); + } + } +#else + void subl_im(int imm, void* addr) + { + if (CAN_SIGN_EXTEND_8_32(imm)) { + m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_SUB, addr); + m_formatter.immediate8(imm); + } else { + m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_SUB, addr); + m_formatter.immediate32(imm); + } + } +#endif + + void xorl_rr(RegisterID src, RegisterID dst) + { + m_formatter.oneByteOp(OP_XOR_EvGv, src, dst); + } + + void xorl_ir(int imm, RegisterID dst) + { + if (CAN_SIGN_EXTEND_8_32(imm)) { + m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_XOR, dst); + m_formatter.immediate8(imm); + } else { + m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_XOR, dst); + m_formatter.immediate32(imm); + } + } + +#if PLATFORM(X86_64) + void xorq_rr(RegisterID src, RegisterID dst) + { + m_formatter.oneByteOp64(OP_XOR_EvGv, src, dst); + } + + void xorq_ir(int imm, RegisterID dst) + { + if (CAN_SIGN_EXTEND_8_32(imm)) { + m_formatter.oneByteOp64(OP_GROUP1_EvIb, GROUP1_OP_XOR, dst); + m_formatter.immediate8(imm); + } else { + m_formatter.oneByteOp64(OP_GROUP1_EvIz, GROUP1_OP_XOR, dst); + m_formatter.immediate32(imm); + } + } +#endif + + void sarl_i8r(int imm, RegisterID dst) + { + if (imm == 1) + m_formatter.oneByteOp(OP_GROUP2_Ev1, GROUP2_OP_SAR, dst); + else { + m_formatter.oneByteOp(OP_GROUP2_EvIb, GROUP2_OP_SAR, dst); + m_formatter.immediate8(imm); + } + } + + void sarl_CLr(RegisterID dst) + { + m_formatter.oneByteOp(OP_GROUP2_EvCL, GROUP2_OP_SAR, dst); + } + + void shll_i8r(int imm, RegisterID dst) + { + if (imm == 1) + m_formatter.oneByteOp(OP_GROUP2_Ev1, GROUP2_OP_SHL, dst); + else { + m_formatter.oneByteOp(OP_GROUP2_EvIb, GROUP2_OP_SHL, dst); + m_formatter.immediate8(imm); + } + } + + void shll_CLr(RegisterID dst) + { + m_formatter.oneByteOp(OP_GROUP2_EvCL, GROUP2_OP_SHL, dst); + } + +#if PLATFORM(X86_64) + void sarq_CLr(RegisterID dst) + { + m_formatter.oneByteOp64(OP_GROUP2_EvCL, GROUP2_OP_SAR, dst); + } + + void sarq_i8r(int imm, RegisterID dst) + { + if (imm == 1) + m_formatter.oneByteOp64(OP_GROUP2_Ev1, GROUP2_OP_SAR, dst); + else { + m_formatter.oneByteOp64(OP_GROUP2_EvIb, GROUP2_OP_SAR, dst); + m_formatter.immediate8(imm); + } + } +#endif + + void imull_rr(RegisterID src, RegisterID dst) + { + m_formatter.twoByteOp(OP2_IMUL_GvEv, dst, src); + } + + void imull_i32r(RegisterID src, int32_t value, RegisterID dst) + { + m_formatter.oneByteOp(OP_IMUL_GvEvIz, dst, src); + m_formatter.immediate32(value); + } + + void idivl_r(RegisterID dst) + { + m_formatter.oneByteOp(OP_GROUP3_Ev, GROUP3_OP_IDIV, dst); + } + + // Comparisons: + + void cmpl_rr(RegisterID src, RegisterID dst) + { + m_formatter.oneByteOp(OP_CMP_EvGv, src, dst); + } + + void cmpl_rm(RegisterID src, int offset, RegisterID base) + { + m_formatter.oneByteOp(OP_CMP_EvGv, src, base, offset); + } + + void cmpl_mr(int offset, RegisterID base, RegisterID src) + { + m_formatter.oneByteOp(OP_CMP_GvEv, src, base, offset); + } + + void cmpl_ir(int imm, RegisterID dst) + { + if (CAN_SIGN_EXTEND_8_32(imm)) { + m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_CMP, dst); + m_formatter.immediate8(imm); + } else { + m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_CMP, dst); + m_formatter.immediate32(imm); + } + } + + void cmpl_ir_force32(int imm, RegisterID dst) + { + m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_CMP, dst); + m_formatter.immediate32(imm); + } + + void cmpl_im(int imm, int offset, RegisterID base) + { + if (CAN_SIGN_EXTEND_8_32(imm)) { + m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_CMP, base, offset); + m_formatter.immediate8(imm); + } else { + m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_CMP, base, offset); + m_formatter.immediate32(imm); + } + } + + void cmpl_im(int imm, int offset, RegisterID base, RegisterID index, int scale) + { + if (CAN_SIGN_EXTEND_8_32(imm)) { + m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_CMP, base, index, scale, offset); + m_formatter.immediate8(imm); + } else { + m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_CMP, base, index, scale, offset); + m_formatter.immediate32(imm); + } + } + + void cmpl_im_force32(int imm, int offset, RegisterID base) + { + m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_CMP, base, offset); + m_formatter.immediate32(imm); + } + +#if PLATFORM(X86_64) + void cmpq_rr(RegisterID src, RegisterID dst) + { + m_formatter.oneByteOp64(OP_CMP_EvGv, src, dst); + } + + void cmpq_rm(RegisterID src, int offset, RegisterID base) + { + m_formatter.oneByteOp64(OP_CMP_EvGv, src, base, offset); + } + + void cmpq_ir(int imm, RegisterID dst) + { + if (CAN_SIGN_EXTEND_8_32(imm)) { + m_formatter.oneByteOp64(OP_GROUP1_EvIb, GROUP1_OP_CMP, dst); + m_formatter.immediate8(imm); + } else { + m_formatter.oneByteOp64(OP_GROUP1_EvIz, GROUP1_OP_CMP, dst); + m_formatter.immediate32(imm); + } + } + + void cmpq_im(int imm, int offset, RegisterID base) + { + if (CAN_SIGN_EXTEND_8_32(imm)) { + m_formatter.oneByteOp64(OP_GROUP1_EvIb, GROUP1_OP_CMP, base, offset); + m_formatter.immediate8(imm); + } else { + m_formatter.oneByteOp64(OP_GROUP1_EvIz, GROUP1_OP_CMP, base, offset); + m_formatter.immediate32(imm); + } + } + + void cmpq_im(int imm, int offset, RegisterID base, RegisterID index, int scale) + { + if (CAN_SIGN_EXTEND_8_32(imm)) { + m_formatter.oneByteOp64(OP_GROUP1_EvIb, GROUP1_OP_CMP, base, index, scale, offset); + m_formatter.immediate8(imm); + } else { + m_formatter.oneByteOp64(OP_GROUP1_EvIz, GROUP1_OP_CMP, base, index, scale, offset); + m_formatter.immediate32(imm); + } + } +#else + void cmpl_rm(RegisterID reg, void* addr) + { + m_formatter.oneByteOp(OP_CMP_EvGv, reg, addr); + } + + void cmpl_im(int imm, void* addr) + { + if (CAN_SIGN_EXTEND_8_32(imm)) { + m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_CMP, addr); + m_formatter.immediate8(imm); + } else { + m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_CMP, addr); + m_formatter.immediate32(imm); + } + } +#endif + + void cmpw_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale) + { + m_formatter.prefix(PRE_OPERAND_SIZE); + m_formatter.oneByteOp(OP_CMP_EvGv, src, base, index, scale, offset); + } + + void testl_rr(RegisterID src, RegisterID dst) + { + m_formatter.oneByteOp(OP_TEST_EvGv, src, dst); + } + + void testl_i32r(int imm, RegisterID dst) + { + m_formatter.oneByteOp(OP_GROUP3_EvIz, GROUP3_OP_TEST, dst); + m_formatter.immediate32(imm); + } + + void testl_i32m(int imm, int offset, RegisterID base) + { + m_formatter.oneByteOp(OP_GROUP3_EvIz, GROUP3_OP_TEST, base, offset); + m_formatter.immediate32(imm); + } + + void testl_i32m(int imm, int offset, RegisterID base, RegisterID index, int scale) + { + m_formatter.oneByteOp(OP_GROUP3_EvIz, GROUP3_OP_TEST, base, index, scale, offset); + m_formatter.immediate32(imm); + } + +#if PLATFORM(X86_64) + void testq_rr(RegisterID src, RegisterID dst) + { + m_formatter.oneByteOp64(OP_TEST_EvGv, src, dst); + } + + void testq_i32r(int imm, RegisterID dst) + { + m_formatter.oneByteOp64(OP_GROUP3_EvIz, GROUP3_OP_TEST, dst); + m_formatter.immediate32(imm); + } + + void testq_i32m(int imm, int offset, RegisterID base) + { + m_formatter.oneByteOp64(OP_GROUP3_EvIz, GROUP3_OP_TEST, base, offset); + m_formatter.immediate32(imm); + } + + void testq_i32m(int imm, int offset, RegisterID base, RegisterID index, int scale) + { + m_formatter.oneByteOp64(OP_GROUP3_EvIz, GROUP3_OP_TEST, base, index, scale, offset); + m_formatter.immediate32(imm); + } +#endif + + void testb_i8r(int imm, RegisterID dst) + { + m_formatter.oneByteOp8(OP_GROUP3_EbIb, GROUP3_OP_TEST, dst); + m_formatter.immediate8(imm); + } + + void sete_r(RegisterID dst) + { + m_formatter.twoByteOp8(OP_SETE, (GroupOpcodeID)0, dst); + } + + void setz_r(RegisterID dst) + { + sete_r(dst); + } + + void setne_r(RegisterID dst) + { + m_formatter.twoByteOp8(OP_SETNE, (GroupOpcodeID)0, dst); + } + + void setnz_r(RegisterID dst) + { + setne_r(dst); + } + + // Various move ops: + + void cdq() + { + m_formatter.oneByteOp(OP_CDQ); + } + + void xchgl_rr(RegisterID src, RegisterID dst) + { + m_formatter.oneByteOp(OP_XCHG_EvGv, src, dst); + } + +#if PLATFORM(X86_64) + void xchgq_rr(RegisterID src, RegisterID dst) + { + m_formatter.oneByteOp64(OP_XCHG_EvGv, src, dst); + } +#endif + + void movl_rr(RegisterID src, RegisterID dst) + { + m_formatter.oneByteOp(OP_MOV_EvGv, src, dst); + } + + void movl_rm(RegisterID src, int offset, RegisterID base) + { + m_formatter.oneByteOp(OP_MOV_EvGv, src, base, offset); + } + + void movl_rm_disp32(RegisterID src, int offset, RegisterID base) + { + m_formatter.oneByteOp_disp32(OP_MOV_EvGv, src, base, offset); + } + + void movl_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale) + { + m_formatter.oneByteOp(OP_MOV_EvGv, src, base, index, scale, offset); + } + + void movl_mEAX(void* addr) + { + m_formatter.oneByteOp(OP_MOV_EAXOv); +#if PLATFORM(X86_64) + m_formatter.immediate64(reinterpret_cast<int64_t>(addr)); +#else + m_formatter.immediate32(reinterpret_cast<int>(addr)); +#endif + } + + void movl_mr(int offset, RegisterID base, RegisterID dst) + { + m_formatter.oneByteOp(OP_MOV_GvEv, dst, base, offset); + } + + void movl_mr_disp32(int offset, RegisterID base, RegisterID dst) + { + m_formatter.oneByteOp_disp32(OP_MOV_GvEv, dst, base, offset); + } + + void movl_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst) + { + m_formatter.oneByteOp(OP_MOV_GvEv, dst, base, index, scale, offset); + } + + void movl_i32r(int imm, RegisterID dst) + { + m_formatter.oneByteOp(OP_MOV_EAXIv, dst); + m_formatter.immediate32(imm); + } + + void movl_i32m(int imm, int offset, RegisterID base) + { + m_formatter.oneByteOp(OP_GROUP11_EvIz, GROUP11_MOV, base, offset); + m_formatter.immediate32(imm); + } + + void movl_EAXm(void* addr) + { + m_formatter.oneByteOp(OP_MOV_OvEAX); +#if PLATFORM(X86_64) + m_formatter.immediate64(reinterpret_cast<int64_t>(addr)); +#else + m_formatter.immediate32(reinterpret_cast<int>(addr)); +#endif + } + +#if PLATFORM(X86_64) + void movq_rr(RegisterID src, RegisterID dst) + { + m_formatter.oneByteOp64(OP_MOV_EvGv, src, dst); + } + + void movq_rm(RegisterID src, int offset, RegisterID base) + { + m_formatter.oneByteOp64(OP_MOV_EvGv, src, base, offset); + } + + void movq_rm_disp32(RegisterID src, int offset, RegisterID base) + { + m_formatter.oneByteOp64_disp32(OP_MOV_EvGv, src, base, offset); + } + + void movq_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale) + { + m_formatter.oneByteOp64(OP_MOV_EvGv, src, base, index, scale, offset); + } + + void movq_mEAX(void* addr) + { + m_formatter.oneByteOp64(OP_MOV_EAXOv); + m_formatter.immediate64(reinterpret_cast<int64_t>(addr)); + } + + void movq_mr(int offset, RegisterID base, RegisterID dst) + { + m_formatter.oneByteOp64(OP_MOV_GvEv, dst, base, offset); + } + + void movq_mr_disp32(int offset, RegisterID base, RegisterID dst) + { + m_formatter.oneByteOp64_disp32(OP_MOV_GvEv, dst, base, offset); + } + + void movq_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst) + { + m_formatter.oneByteOp64(OP_MOV_GvEv, dst, base, index, scale, offset); + } + + void movq_i64r(int64_t imm, RegisterID dst) + { + m_formatter.oneByteOp64(OP_MOV_EAXIv, dst); + m_formatter.immediate64(imm); + } + + void movsxd_rr(RegisterID src, RegisterID dst) + { + m_formatter.oneByteOp64(OP_MOVSXD_GvEv, dst, src); + } + + +#else + void movl_mr(void* addr, RegisterID dst) + { + if (dst == X86::eax) + movl_mEAX(addr); + else + m_formatter.oneByteOp(OP_MOV_GvEv, dst, addr); + } + + void movl_i32m(int imm, void* addr) + { + m_formatter.oneByteOp(OP_GROUP11_EvIz, GROUP11_MOV, addr); + m_formatter.immediate32(imm); + } +#endif + + void movzwl_mr(int offset, RegisterID base, RegisterID dst) + { + m_formatter.twoByteOp(OP2_MOVZX_GvEw, dst, base, offset); + } + + void movzwl_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst) + { + m_formatter.twoByteOp(OP2_MOVZX_GvEw, dst, base, index, scale, offset); + } + + void movzbl_rr(RegisterID src, RegisterID dst) + { + // In 64-bit, this may cause an unnecessary REX to be planted (if the dst register + // is in the range ESP-EDI, and the src would not have required a REX). Unneeded + // REX prefixes are defined to be silently ignored by the processor. + m_formatter.twoByteOp8(OP2_MOVZX_GvEb, dst, src); + } + + void leal_mr(int offset, RegisterID base, RegisterID dst) + { + m_formatter.oneByteOp(OP_LEA, dst, base, offset); + } + + // Flow control: + + JmpSrc call() + { + m_formatter.oneByteOp(OP_CALL_rel32); + return m_formatter.immediateRel32(); + } + + JmpSrc call(RegisterID dst) + { + m_formatter.oneByteOp(OP_GROUP5_Ev, GROUP5_OP_CALLN, dst); + return JmpSrc(m_formatter.size()); + } + + JmpSrc jmp() + { + m_formatter.oneByteOp(OP_JMP_rel32); + return m_formatter.immediateRel32(); + } + + void jmp_r(RegisterID dst) + { + m_formatter.oneByteOp(OP_GROUP5_Ev, GROUP5_OP_JMPN, dst); + } + + void jmp_m(int offset, RegisterID base) + { + m_formatter.oneByteOp(OP_GROUP5_Ev, GROUP5_OP_JMPN, base, offset); + } + + JmpSrc jne() + { + m_formatter.twoByteOp(OP2_JNE_rel32); + return m_formatter.immediateRel32(); + } + + JmpSrc jnz() + { + return jne(); + } + + JmpSrc je() + { + m_formatter.twoByteOp(OP2_JE_rel32); + return m_formatter.immediateRel32(); + } + + JmpSrc jl() + { + m_formatter.twoByteOp(OP2_JL_rel32); + return m_formatter.immediateRel32(); + } + + JmpSrc jb() + { + m_formatter.twoByteOp(OP2_JB_rel32); + return m_formatter.immediateRel32(); + } + + JmpSrc jle() + { + m_formatter.twoByteOp(OP2_JLE_rel32); + return m_formatter.immediateRel32(); + } + + JmpSrc jbe() + { + m_formatter.twoByteOp(OP2_JBE_rel32); + return m_formatter.immediateRel32(); + } + + JmpSrc jge() + { + m_formatter.twoByteOp(OP2_JGE_rel32); + return m_formatter.immediateRel32(); + } + + JmpSrc jg() + { + m_formatter.twoByteOp(OP2_JG_rel32); + return m_formatter.immediateRel32(); + } + + JmpSrc ja() + { + m_formatter.twoByteOp(OP2_JA_rel32); + return m_formatter.immediateRel32(); + } + + JmpSrc jae() + { + m_formatter.twoByteOp(OP2_JAE_rel32); + return m_formatter.immediateRel32(); + } + + JmpSrc jo() + { + m_formatter.twoByteOp(OP2_JO_rel32); + return m_formatter.immediateRel32(); + } + + JmpSrc jp() + { + m_formatter.twoByteOp(OP2_JP_rel32); + return m_formatter.immediateRel32(); + } + + JmpSrc js() + { + m_formatter.twoByteOp(OP2_JS_rel32); + return m_formatter.immediateRel32(); + } + + // SSE operations: + + void addsd_rr(XMMRegisterID src, XMMRegisterID dst) + { + m_formatter.prefix(PRE_SSE_F2); + m_formatter.twoByteOp(OP2_ADDSD_VsdWsd, (RegisterID)dst, (RegisterID)src); + } + + void addsd_mr(int offset, RegisterID base, XMMRegisterID dst) + { + m_formatter.prefix(PRE_SSE_F2); + m_formatter.twoByteOp(OP2_ADDSD_VsdWsd, (RegisterID)dst, base, offset); + } + + void cvtsi2sd_rr(RegisterID src, XMMRegisterID dst) + { + m_formatter.prefix(PRE_SSE_F2); + m_formatter.twoByteOp(OP2_CVTSI2SD_VsdEd, (RegisterID)dst, src); + } + + void cvttsd2si_rr(XMMRegisterID src, RegisterID dst) + { + m_formatter.prefix(PRE_SSE_F2); + m_formatter.twoByteOp(OP2_CVTTSD2SI_GdWsd, dst, (RegisterID)src); + } + + void movd_rr(XMMRegisterID src, RegisterID dst) + { + m_formatter.prefix(PRE_SSE_66); + m_formatter.twoByteOp(OP2_MOVD_EdVd, (RegisterID)src, dst); + } + +#if PLATFORM(X86_64) + void movq_rr(XMMRegisterID src, RegisterID dst) + { + m_formatter.prefix(PRE_SSE_66); + m_formatter.twoByteOp64(OP2_MOVD_EdVd, (RegisterID)src, dst); + } + + void movq_rr(RegisterID src, XMMRegisterID dst) + { + m_formatter.prefix(PRE_SSE_66); + m_formatter.twoByteOp64(OP2_MOVD_VdEd, (RegisterID)dst, src); + } +#endif + + void movsd_rm(XMMRegisterID src, int offset, RegisterID base) + { + m_formatter.prefix(PRE_SSE_F2); + m_formatter.twoByteOp(OP2_MOVSD_WsdVsd, (RegisterID)src, base, offset); + } + + void movsd_mr(int offset, RegisterID base, XMMRegisterID dst) + { + m_formatter.prefix(PRE_SSE_F2); + m_formatter.twoByteOp(OP2_MOVSD_VsdWsd, (RegisterID)dst, base, offset); + } + + void mulsd_rr(XMMRegisterID src, XMMRegisterID dst) + { + m_formatter.prefix(PRE_SSE_F2); + m_formatter.twoByteOp(OP2_MULSD_VsdWsd, (RegisterID)dst, (RegisterID)src); + } + + void mulsd_mr(int offset, RegisterID base, XMMRegisterID dst) + { + m_formatter.prefix(PRE_SSE_F2); + m_formatter.twoByteOp(OP2_MULSD_VsdWsd, (RegisterID)dst, base, offset); + } + + void pextrw_irr(int whichWord, XMMRegisterID src, RegisterID dst) + { + m_formatter.prefix(PRE_SSE_66); + m_formatter.twoByteOp(OP2_PEXTRW_GdUdIb, (RegisterID)dst, (RegisterID)src); + m_formatter.immediate8(whichWord); + } + + void subsd_rr(XMMRegisterID src, XMMRegisterID dst) + { + m_formatter.prefix(PRE_SSE_F2); + m_formatter.twoByteOp(OP2_SUBSD_VsdWsd, (RegisterID)dst, (RegisterID)src); + } + + void subsd_mr(int offset, RegisterID base, XMMRegisterID dst) + { + m_formatter.prefix(PRE_SSE_F2); + m_formatter.twoByteOp(OP2_SUBSD_VsdWsd, (RegisterID)dst, base, offset); + } + + void ucomisd_rr(XMMRegisterID src, XMMRegisterID dst) + { + m_formatter.prefix(PRE_SSE_66); + m_formatter.twoByteOp(OP2_UCOMISD_VsdWsd, (RegisterID)dst, (RegisterID)src); + } + + // Misc instructions: + + void int3() + { + m_formatter.oneByteOp(OP_INT3); + } + + void ret() + { + m_formatter.oneByteOp(OP_RET); + } + + void predictNotTaken() + { + m_formatter.prefix(PRE_PREDICT_BRANCH_NOT_TAKEN); + } + + // Assembler admin methods: + + JmpDst label() + { + return JmpDst(m_formatter.size()); + } + + JmpDst align(int alignment) + { + while (!m_formatter.isAligned(alignment)) + m_formatter.oneByteOp(OP_HLT); + + return label(); + } + + // Linking & patching: + + void link(JmpSrc from, JmpDst to) + { + ASSERT(to.m_offset != -1); + ASSERT(from.m_offset != -1); + + reinterpret_cast<int*>(reinterpret_cast<ptrdiff_t>(m_formatter.data()) + from.m_offset)[-1] = to.m_offset - from.m_offset; + } + + static void patchAddress(void* code, JmpDst position, void* value) + { + ASSERT(position.m_offset != -1); + + reinterpret_cast<void**>(reinterpret_cast<ptrdiff_t>(code) + position.m_offset)[-1] = value; + } + + static void link(void* code, JmpSrc from, void* to) + { + ASSERT(from.m_offset != -1); + + reinterpret_cast<int*>(reinterpret_cast<ptrdiff_t>(code) + from.m_offset)[-1] = reinterpret_cast<ptrdiff_t>(to) - (reinterpret_cast<ptrdiff_t>(code) + from.m_offset); + } + + static void* getRelocatedAddress(void* code, JmpSrc jump) + { + return reinterpret_cast<void*>(reinterpret_cast<ptrdiff_t>(code) + jump.m_offset); + } + + static void* getRelocatedAddress(void* code, JmpDst destination) + { + ASSERT(destination.m_offset != -1); + + return reinterpret_cast<void*>(reinterpret_cast<ptrdiff_t>(code) + destination.m_offset); + } + + static int getDifferenceBetweenLabels(JmpDst src, JmpDst dst) + { + return dst.m_offset - src.m_offset; + } + + static int getDifferenceBetweenLabels(JmpDst src, JmpSrc dst) + { + return dst.m_offset - src.m_offset; + } + + static int getDifferenceBetweenLabels(JmpSrc src, JmpDst dst) + { + return dst.m_offset - src.m_offset; + } + + static void patchImmediate(intptr_t where, int32_t value) + { + reinterpret_cast<int32_t*>(where)[-1] = value; + } + + static void patchPointer(intptr_t where, intptr_t value) + { + reinterpret_cast<intptr_t*>(where)[-1] = value; + } + + static void patchBranchOffset(intptr_t where, void* destination) + { + intptr_t offset = reinterpret_cast<intptr_t>(destination) - where; + ASSERT(offset == static_cast<int32_t>(offset)); + reinterpret_cast<int32_t*>(where)[-1] = static_cast<int32_t>(offset); + } + + void* executableCopy(ExecutablePool* allocator) + { + void* copy = m_formatter.executableCopy(allocator); + ASSERT(copy); + return copy; + } + +private: + + class X86InstructionFormatter { + + static const int maxInstructionSize = 16; + + public: + + // Legacy prefix bytes: + // + // These are emmitted prior to the instruction. + + void prefix(OneByteOpcodeID pre) + { + m_buffer.putByte(pre); + } + + // Word-sized operands / no operand instruction formatters. + // + // In addition to the opcode, the following operand permutations are supported: + // * None - instruction takes no operands. + // * One register - the low three bits of the RegisterID are added into the opcode. + // * Two registers - encode a register form ModRm (for all ModRm formats, the reg field is passed first, and a GroupOpcodeID may be passed in its place). + // * Three argument ModRM - a register, and a register and an offset describing a memory operand. + // * Five argument ModRM - a register, and a base register, an index, scale, and offset describing a memory operand. + // + // For 32-bit x86 targets, the address operand may also be provided as a void*. + // On 64-bit targets REX prefixes will be planted as necessary, where high numbered registers are used. + // + // The twoByteOp methods plant two-byte Intel instructions sequences (first opcode byte 0x0F). + + void oneByteOp(OneByteOpcodeID opcode) + { + m_buffer.ensureSpace(maxInstructionSize); + m_buffer.putByteUnchecked(opcode); + } + + void oneByteOp(OneByteOpcodeID opcode, RegisterID reg) + { + m_buffer.ensureSpace(maxInstructionSize); + emitRexIfNeeded(0, 0, reg); + m_buffer.putByteUnchecked(opcode + (reg & 7)); + } + + void oneByteOp(OneByteOpcodeID opcode, int reg, RegisterID rm) + { + m_buffer.ensureSpace(maxInstructionSize); + emitRexIfNeeded(reg, 0, rm); + m_buffer.putByteUnchecked(opcode); + registerModRM(reg, rm); + } + + void oneByteOp(OneByteOpcodeID opcode, int reg, RegisterID base, int offset) + { + m_buffer.ensureSpace(maxInstructionSize); + emitRexIfNeeded(reg, 0, base); + m_buffer.putByteUnchecked(opcode); + memoryModRM(reg, base, offset); + } + + void oneByteOp_disp32(OneByteOpcodeID opcode, int reg, RegisterID base, int offset) + { + m_buffer.ensureSpace(maxInstructionSize); + emitRexIfNeeded(reg, 0, base); + m_buffer.putByteUnchecked(opcode); + memoryModRM_disp32(reg, base, offset); + } + + void oneByteOp(OneByteOpcodeID opcode, int reg, RegisterID base, RegisterID index, int scale, int offset) + { + m_buffer.ensureSpace(maxInstructionSize); + emitRexIfNeeded(reg, index, base); + m_buffer.putByteUnchecked(opcode); + memoryModRM(reg, base, index, scale, offset); + } + +#if !PLATFORM(X86_64) + void oneByteOp(OneByteOpcodeID opcode, int reg, void* address) + { + m_buffer.ensureSpace(maxInstructionSize); + m_buffer.putByteUnchecked(opcode); + memoryModRM(reg, address); + } +#endif + + void twoByteOp(TwoByteOpcodeID opcode) + { + m_buffer.ensureSpace(maxInstructionSize); + m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE); + m_buffer.putByteUnchecked(opcode); + } + + void twoByteOp(TwoByteOpcodeID opcode, int reg, RegisterID rm) + { + m_buffer.ensureSpace(maxInstructionSize); + emitRexIfNeeded(reg, 0, rm); + m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE); + m_buffer.putByteUnchecked(opcode); + registerModRM(reg, rm); + } + + void twoByteOp(TwoByteOpcodeID opcode, int reg, RegisterID base, int offset) + { + m_buffer.ensureSpace(maxInstructionSize); + emitRexIfNeeded(reg, 0, base); + m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE); + m_buffer.putByteUnchecked(opcode); + memoryModRM(reg, base, offset); + } + + void twoByteOp(TwoByteOpcodeID opcode, int reg, RegisterID base, RegisterID index, int scale, int offset) + { + m_buffer.ensureSpace(maxInstructionSize); + emitRexIfNeeded(reg, index, base); + m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE); + m_buffer.putByteUnchecked(opcode); + memoryModRM(reg, base, index, scale, offset); + } + +#if PLATFORM(X86_64) + // Quad-word-sized operands: + // + // Used to format 64-bit operantions, planting a REX.w prefix. + // When planting d64 or f64 instructions, not requiring a REX.w prefix, + // the normal (non-'64'-postfixed) formatters should be used. + + void oneByteOp64(OneByteOpcodeID opcode) + { + m_buffer.ensureSpace(maxInstructionSize); + emitRexW(0, 0, 0); + m_buffer.putByteUnchecked(opcode); + } + + void oneByteOp64(OneByteOpcodeID opcode, RegisterID reg) + { + m_buffer.ensureSpace(maxInstructionSize); + emitRexW(0, 0, reg); + m_buffer.putByteUnchecked(opcode + (reg & 7)); + } + + void oneByteOp64(OneByteOpcodeID opcode, int reg, RegisterID rm) + { + m_buffer.ensureSpace(maxInstructionSize); + emitRexW(reg, 0, rm); + m_buffer.putByteUnchecked(opcode); + registerModRM(reg, rm); + } + + void oneByteOp64(OneByteOpcodeID opcode, int reg, RegisterID base, int offset) + { + m_buffer.ensureSpace(maxInstructionSize); + emitRexW(reg, 0, base); + m_buffer.putByteUnchecked(opcode); + memoryModRM(reg, base, offset); + } + + void oneByteOp64_disp32(OneByteOpcodeID opcode, int reg, RegisterID base, int offset) + { + m_buffer.ensureSpace(maxInstructionSize); + emitRexW(reg, 0, base); + m_buffer.putByteUnchecked(opcode); + memoryModRM_disp32(reg, base, offset); + } + + void oneByteOp64(OneByteOpcodeID opcode, int reg, RegisterID base, RegisterID index, int scale, int offset) + { + m_buffer.ensureSpace(maxInstructionSize); + emitRexW(reg, index, base); + m_buffer.putByteUnchecked(opcode); + memoryModRM(reg, base, index, scale, offset); + } + + void twoByteOp64(TwoByteOpcodeID opcode, int reg, RegisterID rm) + { + m_buffer.ensureSpace(maxInstructionSize); + emitRexW(reg, 0, rm); + m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE); + m_buffer.putByteUnchecked(opcode); + registerModRM(reg, rm); + } +#endif + + // Byte-operands: + // + // These methods format byte operations. Byte operations differ from the normal + // formatters in the circumstances under which they will decide to emit REX prefixes. + // These should be used where any register operand signifies a byte register. + // + // The disctinction is due to the handling of register numbers in the range 4..7 on + // x86-64. These register numbers may either represent the second byte of the first + // four registers (ah..bh) or the first byte of the second four registers (spl..dil). + // + // Since ah..bh cannot be used in all permutations of operands (specifically cannot + // be accessed where a REX prefix is present), these are likely best treated as + // deprecated. In order to ensure the correct registers spl..dil are selected a + // REX prefix will be emitted for any byte register operand in the range 4..15. + // + // These formatters may be used in instructions where a mix of operand sizes, in which + // case an unnecessary REX will be emitted, for example: + // movzbl %al, %edi + // In this case a REX will be planted since edi is 7 (and were this a byte operand + // a REX would be required to specify dil instead of bh). Unneeded REX prefixes will + // be silently ignored by the processor. + // + // Address operands should still be checked using regRequiresRex(), while byteRegRequiresRex() + // is provided to check byte register operands. + + void oneByteOp8(OneByteOpcodeID opcode, GroupOpcodeID groupOp, RegisterID rm) + { + m_buffer.ensureSpace(maxInstructionSize); + emitRexIf(byteRegRequiresRex(rm), 0, 0, rm); + m_buffer.putByteUnchecked(opcode); + registerModRM(groupOp, rm); + } + + void twoByteOp8(TwoByteOpcodeID opcode, RegisterID reg, RegisterID rm) + { + m_buffer.ensureSpace(maxInstructionSize); + emitRexIf(byteRegRequiresRex(reg)|byteRegRequiresRex(rm), reg, 0, rm); + m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE); + m_buffer.putByteUnchecked(opcode); + registerModRM(reg, rm); + } + + void twoByteOp8(TwoByteOpcodeID opcode, GroupOpcodeID groupOp, RegisterID rm) + { + m_buffer.ensureSpace(maxInstructionSize); + emitRexIf(byteRegRequiresRex(rm), 0, 0, rm); + m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE); + m_buffer.putByteUnchecked(opcode); + registerModRM(groupOp, rm); + } + + // Immediates: + // + // An immedaite should be appended where appropriate after an op has been emitted. + // The writes are unchecked since the opcode formatters above will have ensured space. + + void immediate8(int imm) + { + m_buffer.putByteUnchecked(imm); + } + + void immediate32(int imm) + { + m_buffer.putIntUnchecked(imm); + } + + void immediate64(int64_t imm) + { + m_buffer.putInt64Unchecked(imm); + } + + JmpSrc immediateRel32() + { + m_buffer.putIntUnchecked(0); + return JmpSrc(m_buffer.size()); + } + + // Administrative methods: + + size_t size() const { return m_buffer.size(); } + bool isAligned(int alignment) const { return m_buffer.isAligned(alignment); } + void* data() const { return m_buffer.data(); } + void* executableCopy(ExecutablePool* allocator) { return m_buffer.executableCopy(allocator); } + + private: + + // Internals; ModRm and REX formatters. + + static const RegisterID noBase = X86::ebp; + static const RegisterID hasSib = X86::esp; + static const RegisterID noIndex = X86::esp; +#if PLATFORM(X86_64) + static const RegisterID noBase2 = X86::r13; + static const RegisterID hasSib2 = X86::r12; + + // Registers r8 & above require a REX prefixe. + inline bool regRequiresRex(int reg) + { + return (reg >= X86::r8); + } + + // Byte operand register spl & above require a REX prefix (to prevent the 'H' registers be accessed). + inline bool byteRegRequiresRex(int reg) + { + return (reg >= X86::esp); + } + + // Format a REX prefix byte. + inline void emitRex(bool w, int r, int x, int b) + { + m_buffer.putByteUnchecked(PRE_REX | ((int)w << 3) | ((r>>3)<<2) | ((x>>3)<<1) | (b>>3)); + } + + // Used to plant a REX byte with REX.w set (for 64-bit operations). + inline void emitRexW(int r, int x, int b) + { + emitRex(true, r, x, b); + } + + // Used for operations with byte operands - use byteRegRequiresRex() to check register operands, + // regRequiresRex() to check other registers (i.e. address base & index). + inline void emitRexIf(bool condition, int r, int x, int b) + { + if (condition) emitRex(false, r, x, b); + } + + // Used for word sized operations, will plant a REX prefix if necessary (if any register is r8 or above). + inline void emitRexIfNeeded(int r, int x, int b) + { + emitRexIf(regRequiresRex(r) || regRequiresRex(x) || regRequiresRex(b), r, x, b); + } +#else + // No REX prefix bytes on 32-bit x86. + inline bool regRequiresRex(int) { return false; } + inline bool byteRegRequiresRex(int) { return false; } + inline void emitRexIf(bool, int, int, int) {} + inline void emitRexIfNeeded(int, int, int) {} +#endif + + enum ModRmMode { + ModRmMemoryNoDisp, + ModRmMemoryDisp8, + ModRmMemoryDisp32, + ModRmRegister, + }; + + void putModRm(ModRmMode mode, int reg, RegisterID rm) + { + m_buffer.putByteUnchecked((mode << 6) | ((reg & 7) << 3) | (rm & 7)); + } + + void putModRmSib(ModRmMode mode, int reg, RegisterID base, RegisterID index, int scale) + { + ASSERT(mode != ModRmRegister); + + // Encode sacle of (1,2,4,8) -> (0,1,2,3) + int shift = 0; + while (scale >>= 1) + shift++; + + putModRm(mode, reg, hasSib); + m_buffer.putByteUnchecked((shift << 6) | ((index & 7) << 3) | (base & 7)); + } + + void registerModRM(int reg, RegisterID rm) + { + putModRm(ModRmRegister, reg, rm); + } + + void memoryModRM(int reg, RegisterID base, int offset) + { + // A base of esp or r12 would be interpreted as a sib, so force a sib with no index & put the base in there. +#if PLATFORM(X86_64) + if ((base == hasSib) || (base == hasSib2)) { +#else + if (base == hasSib) { +#endif + if (!offset) // No need to check if the base is noBase, since we know it is hasSib! + putModRmSib(ModRmMemoryNoDisp, reg, base, noIndex, 0); + else if (CAN_SIGN_EXTEND_8_32(offset)) { + putModRmSib(ModRmMemoryDisp8, reg, base, noIndex, 0); + m_buffer.putByteUnchecked(offset); + } else { + putModRmSib(ModRmMemoryDisp32, reg, base, noIndex, 0); + m_buffer.putIntUnchecked(offset); + } + } else { +#if PLATFORM(X86_64) + if (!offset && (base != noBase) && (base != noBase2)) +#else + if (!offset && (base != noBase)) +#endif + putModRm(ModRmMemoryNoDisp, reg, base); + else if (CAN_SIGN_EXTEND_8_32(offset)) { + putModRm(ModRmMemoryDisp8, reg, base); + m_buffer.putByteUnchecked(offset); + } else { + putModRm(ModRmMemoryDisp32, reg, base); + m_buffer.putIntUnchecked(offset); + } + } + } + + void memoryModRM_disp32(int reg, RegisterID base, int offset) + { + // A base of esp or r12 would be interpreted as a sib, so force a sib with no index & put the base in there. +#if PLATFORM(X86_64) + if ((base == hasSib) || (base == hasSib2)) { +#else + if (base == hasSib) { +#endif + putModRmSib(ModRmMemoryDisp32, reg, base, noIndex, 0); + m_buffer.putIntUnchecked(offset); + } else { + putModRm(ModRmMemoryDisp32, reg, base); + m_buffer.putIntUnchecked(offset); + } + } + + void memoryModRM(int reg, RegisterID base, RegisterID index, int scale, int offset) + { + ASSERT(index != noIndex); + +#if PLATFORM(X86_64) + if (!offset && (base != noBase) && (base != noBase2)) +#else + if (!offset && (base != noBase)) +#endif + putModRmSib(ModRmMemoryNoDisp, reg, base, index, scale); + else if (CAN_SIGN_EXTEND_8_32(offset)) { + putModRmSib(ModRmMemoryDisp8, reg, base, index, scale); + m_buffer.putByteUnchecked(offset); + } else { + putModRmSib(ModRmMemoryDisp32, reg, base, index, scale); + m_buffer.putIntUnchecked(offset); + } + } + +#if !PLATFORM(X86_64) + void memoryModRM(int reg, void* address) + { + // noBase + ModRmMemoryNoDisp means noBase + ModRmMemoryDisp32! + putModRm(ModRmMemoryNoDisp, reg, noBase); + m_buffer.putIntUnchecked(reinterpret_cast<int32_t>(address)); + } +#endif + + AssemblerBuffer m_buffer; + } m_formatter; +}; + +} // namespace JSC + +#endif // ENABLE(ASSEMBLER) && PLATFORM(X86) + +#endif // X86Assembler_h diff --git a/JavaScriptCore/bytecode/CodeBlock.cpp b/JavaScriptCore/bytecode/CodeBlock.cpp new file mode 100644 index 0000000..be060d0 --- /dev/null +++ b/JavaScriptCore/bytecode/CodeBlock.cpp @@ -0,0 +1,1686 @@ +/* + * Copyright (C) 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca> + * + * 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 "CodeBlock.h" + +#include "JIT.h" +#include "JSValue.h" +#include "Interpreter.h" +#include "Debugger.h" +#include "BytecodeGenerator.h" +#include <stdio.h> +#include <wtf/StringExtras.h> + +#define DUMP_CODE_BLOCK_STATISTICS 0 + +namespace JSC { + +#if !defined(NDEBUG) || ENABLE(OPCODE_SAMPLING) + +static UString escapeQuotes(const UString& str) +{ + UString result = str; + int pos = 0; + while ((pos = result.find('\"', pos)) >= 0) { + result = result.substr(0, pos) + "\"\\\"\"" + result.substr(pos + 1); + pos += 4; + } + return result; +} + +static UString valueToSourceString(ExecState* exec, JSValuePtr val) +{ + if (val.isString()) { + UString result("\""); + result += escapeQuotes(val.toString(exec)) + "\""; + return result; + } + + return val.toString(exec); +} + +static CString registerName(int r) +{ + if (r == missingThisObjectMarker()) + return "<null>"; + + return (UString("r") + UString::from(r)).UTF8String(); +} + +static CString constantName(ExecState* exec, int k, JSValuePtr value) +{ + return (valueToSourceString(exec, value) + "(@k" + UString::from(k) + ")").UTF8String(); +} + +static CString idName(int id0, const Identifier& ident) +{ + return (ident.ustring() + "(@id" + UString::from(id0) +")").UTF8String(); +} + +static UString regexpToSourceString(RegExp* regExp) +{ + UString pattern = UString("/") + regExp->pattern() + "/"; + if (regExp->global()) + pattern += "g"; + if (regExp->ignoreCase()) + pattern += "i"; + if (regExp->multiline()) + pattern += "m"; + + return pattern; +} + +static CString regexpName(int re, RegExp* regexp) +{ + return (regexpToSourceString(regexp) + "(@re" + UString::from(re) + ")").UTF8String(); +} + +static UString pointerToSourceString(void* p) +{ + char buffer[2 + 2 * sizeof(void*) + 1]; // 0x [two characters per byte] \0 + snprintf(buffer, sizeof(buffer), "%p", p); + return buffer; +} + +NEVER_INLINE static const char* debugHookName(int debugHookID) +{ + switch (static_cast<DebugHookID>(debugHookID)) { + case DidEnterCallFrame: + return "didEnterCallFrame"; + case WillLeaveCallFrame: + return "willLeaveCallFrame"; + case WillExecuteStatement: + return "willExecuteStatement"; + case WillExecuteProgram: + return "willExecuteProgram"; + case DidExecuteProgram: + return "didExecuteProgram"; + case DidReachBreakpoint: + return "didReachBreakpoint"; + } + + ASSERT_NOT_REACHED(); + return ""; +} + +static int locationForOffset(const Vector<Instruction>::const_iterator& begin, Vector<Instruction>::const_iterator& it, int offset) +{ + return it - begin + offset; +} + +static void printUnaryOp(int location, Vector<Instruction>::const_iterator& it, const char* op) +{ + int r0 = (++it)->u.operand; + int r1 = (++it)->u.operand; + + printf("[%4d] %s\t\t %s, %s\n", location, op, registerName(r0).c_str(), registerName(r1).c_str()); +} + +static void printBinaryOp(int location, Vector<Instruction>::const_iterator& it, const char* op) +{ + int r0 = (++it)->u.operand; + int r1 = (++it)->u.operand; + int r2 = (++it)->u.operand; + printf("[%4d] %s\t\t %s, %s, %s\n", location, op, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str()); +} + +static void printConditionalJump(const Vector<Instruction>::const_iterator& begin, Vector<Instruction>::const_iterator& it, int location, const char* op) +{ + int r0 = (++it)->u.operand; + int offset = (++it)->u.operand; + printf("[%4d] %s\t\t %s, %d(->%d)\n", location, op, registerName(r0).c_str(), offset, locationForOffset(begin, it, offset)); +} + +static void printGetByIdOp(int location, Vector<Instruction>::const_iterator& it, const Vector<Identifier>& m_identifiers, const char* op) +{ + int r0 = (++it)->u.operand; + int r1 = (++it)->u.operand; + int id0 = (++it)->u.operand; + printf("[%4d] %s\t %s, %s, %s\n", location, op, registerName(r0).c_str(), registerName(r1).c_str(), idName(id0, m_identifiers[id0]).c_str()); + it += 4; +} + +static void printPutByIdOp(int location, Vector<Instruction>::const_iterator& it, const Vector<Identifier>& m_identifiers, const char* op) +{ + int r0 = (++it)->u.operand; + int id0 = (++it)->u.operand; + int r1 = (++it)->u.operand; + printf("[%4d] %s\t %s, %s, %s\n", location, op, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str(), registerName(r1).c_str()); + it += 4; +} + +#if ENABLE(JIT) +static bool isGlobalResolve(OpcodeID opcodeID) +{ + return opcodeID == op_resolve_global; +} + +static bool isPropertyAccess(OpcodeID opcodeID) +{ + switch (opcodeID) { + case op_get_by_id_self: + case op_get_by_id_proto: + case op_get_by_id_chain: + case op_get_by_id_self_list: + case op_get_by_id_proto_list: + case op_put_by_id_transition: + case op_put_by_id_replace: + case op_get_by_id: + case op_put_by_id: + case op_get_by_id_generic: + case op_put_by_id_generic: + case op_get_array_length: + case op_get_string_length: + return true; + default: + return false; + } +} + +static unsigned instructionOffsetForNth(ExecState* exec, const Vector<Instruction>& instructions, int nth, bool (*predicate)(OpcodeID)) +{ + size_t i = 0; + while (i < instructions.size()) { + OpcodeID currentOpcode = exec->interpreter()->getOpcodeID(instructions[i].u.opcode); + if (predicate(currentOpcode)) { + if (!--nth) + return i; + } + i += opcodeLengths[currentOpcode]; + } + + ASSERT_NOT_REACHED(); + return 0; +} + +static void printGlobalResolveInfo(const GlobalResolveInfo& resolveInfo, unsigned instructionOffset) +{ + printf(" [%4d] %s: %s\n", instructionOffset, "resolve_global", pointerToSourceString(resolveInfo.structure).UTF8String().c_str()); +} + +static void printStructureStubInfo(const StructureStubInfo& stubInfo, unsigned instructionOffset) +{ + switch (stubInfo.opcodeID) { + case op_get_by_id_self: + printf(" [%4d] %s: %s\n", instructionOffset, "get_by_id_self", pointerToSourceString(stubInfo.u.getByIdSelf.baseObjectStructure).UTF8String().c_str()); + return; + case op_get_by_id_proto: + printf(" [%4d] %s: %s, %s\n", instructionOffset, "get_by_id_proto", pointerToSourceString(stubInfo.u.getByIdProto.baseObjectStructure).UTF8String().c_str(), pointerToSourceString(stubInfo.u.getByIdProto.prototypeStructure).UTF8String().c_str()); + return; + case op_get_by_id_chain: + printf(" [%4d] %s: %s, %s\n", instructionOffset, "get_by_id_chain", pointerToSourceString(stubInfo.u.getByIdChain.baseObjectStructure).UTF8String().c_str(), pointerToSourceString(stubInfo.u.getByIdChain.chain).UTF8String().c_str()); + return; + case op_get_by_id_self_list: + printf(" [%4d] %s: %s (%d)\n", instructionOffset, "op_get_by_id_self_list", pointerToSourceString(stubInfo.u.getByIdSelfList.structureList).UTF8String().c_str(), stubInfo.u.getByIdSelfList.listSize); + return; + case op_get_by_id_proto_list: + printf(" [%4d] %s: %s (%d)\n", instructionOffset, "op_get_by_id_proto_list", pointerToSourceString(stubInfo.u.getByIdProtoList.structureList).UTF8String().c_str(), stubInfo.u.getByIdProtoList.listSize); + return; + case op_put_by_id_transition: + printf(" [%4d] %s: %s, %s, %s\n", instructionOffset, "put_by_id_transition", pointerToSourceString(stubInfo.u.putByIdTransition.previousStructure).UTF8String().c_str(), pointerToSourceString(stubInfo.u.putByIdTransition.structure).UTF8String().c_str(), pointerToSourceString(stubInfo.u.putByIdTransition.chain).UTF8String().c_str()); + return; + case op_put_by_id_replace: + printf(" [%4d] %s: %s\n", instructionOffset, "put_by_id_replace", pointerToSourceString(stubInfo.u.putByIdReplace.baseObjectStructure).UTF8String().c_str()); + return; + case op_get_by_id: + printf(" [%4d] %s\n", instructionOffset, "get_by_id"); + return; + case op_put_by_id: + printf(" [%4d] %s\n", instructionOffset, "put_by_id"); + return; + case op_get_by_id_generic: + printf(" [%4d] %s\n", instructionOffset, "op_get_by_id_generic"); + return; + case op_put_by_id_generic: + printf(" [%4d] %s\n", instructionOffset, "op_put_by_id_generic"); + return; + case op_get_array_length: + printf(" [%4d] %s\n", instructionOffset, "op_get_array_length"); + return; + case op_get_string_length: + printf(" [%4d] %s\n", instructionOffset, "op_get_string_length"); + return; + default: + ASSERT_NOT_REACHED(); + } +} +#endif + +void CodeBlock::printStructure(const char* name, const Instruction* vPC, int operand) const +{ + unsigned instructionOffset = vPC - m_instructions.begin(); + printf(" [%4d] %s: %s\n", instructionOffset, name, pointerToSourceString(vPC[operand].u.structure).UTF8String().c_str()); +} + +void CodeBlock::printStructures(const Instruction* vPC) const +{ + Interpreter* interpreter = m_globalData->interpreter; + unsigned instructionOffset = vPC - m_instructions.begin(); + + if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id)) { + printStructure("get_by_id", vPC, 4); + return; + } + if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self)) { + printStructure("get_by_id_self", vPC, 4); + return; + } + if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto)) { + printf(" [%4d] %s: %s, %s\n", instructionOffset, "get_by_id_proto", pointerToSourceString(vPC[4].u.structure).UTF8String().c_str(), pointerToSourceString(vPC[5].u.structure).UTF8String().c_str()); + return; + } + if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_transition)) { + printf(" [%4d] %s: %s, %s, %s\n", instructionOffset, "put_by_id_transition", pointerToSourceString(vPC[4].u.structure).UTF8String().c_str(), pointerToSourceString(vPC[5].u.structure).UTF8String().c_str(), pointerToSourceString(vPC[6].u.structureChain).UTF8String().c_str()); + return; + } + if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_chain)) { + printf(" [%4d] %s: %s, %s\n", instructionOffset, "get_by_id_chain", pointerToSourceString(vPC[4].u.structure).UTF8String().c_str(), pointerToSourceString(vPC[5].u.structureChain).UTF8String().c_str()); + return; + } + if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id)) { + printStructure("put_by_id", vPC, 4); + return; + } + if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_replace)) { + printStructure("put_by_id_replace", vPC, 4); + return; + } + if (vPC[0].u.opcode == interpreter->getOpcode(op_resolve_global)) { + printStructure("resolve_global", vPC, 4); + return; + } + + // These m_instructions doesn't ref Structures. + ASSERT(vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_generic) || vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_generic) || vPC[0].u.opcode == interpreter->getOpcode(op_call) || vPC[0].u.opcode == interpreter->getOpcode(op_call_eval) || vPC[0].u.opcode == interpreter->getOpcode(op_construct)); +} + +void CodeBlock::dump(ExecState* exec) const +{ + if (m_instructions.isEmpty()) { + printf("No instructions available.\n"); + return; + } + + size_t instructionCount = 0; + + for (size_t i = 0; i < m_instructions.size(); i += opcodeLengths[exec->interpreter()->getOpcodeID(m_instructions[i].u.opcode)]) + ++instructionCount; + + printf("%lu m_instructions; %lu bytes at %p; %d parameter(s); %d callee register(s)\n\n", + static_cast<unsigned long>(instructionCount), + static_cast<unsigned long>(m_instructions.size() * sizeof(Instruction)), + this, m_numParameters, m_numCalleeRegisters); + + Vector<Instruction>::const_iterator begin = m_instructions.begin(); + Vector<Instruction>::const_iterator end = m_instructions.end(); + for (Vector<Instruction>::const_iterator it = begin; it != end; ++it) + dump(exec, begin, it); + + if (!m_identifiers.isEmpty()) { + printf("\nIdentifiers:\n"); + size_t i = 0; + do { + printf(" id%u = %s\n", static_cast<unsigned>(i), m_identifiers[i].ascii()); + ++i; + } while (i != m_identifiers.size()); + } + + if (!m_constantRegisters.isEmpty()) { + printf("\nConstants:\n"); + unsigned registerIndex = m_numVars; + size_t i = 0; + do { + printf(" r%u = %s\n", registerIndex, valueToSourceString(exec, m_constantRegisters[i].jsValue(exec)).ascii()); + ++i; + ++registerIndex; + } while (i < m_constantRegisters.size()); + } + + if (m_rareData && !m_rareData->m_unexpectedConstants.isEmpty()) { + printf("\nUnexpected Constants:\n"); + size_t i = 0; + do { + printf(" k%u = %s\n", static_cast<unsigned>(i), valueToSourceString(exec, m_rareData->m_unexpectedConstants[i]).ascii()); + ++i; + } while (i < m_rareData->m_unexpectedConstants.size()); + } + + if (m_rareData && !m_rareData->m_regexps.isEmpty()) { + printf("\nm_regexps:\n"); + size_t i = 0; + do { + printf(" re%u = %s\n", static_cast<unsigned>(i), regexpToSourceString(m_rareData->m_regexps[i].get()).ascii()); + ++i; + } while (i < m_rareData->m_regexps.size()); + } + +#if ENABLE(JIT) + if (!m_globalResolveInfos.isEmpty() || !m_structureStubInfos.isEmpty()) + printf("\nStructures:\n"); + + if (!m_globalResolveInfos.isEmpty()) { + size_t i = 0; + do { + printGlobalResolveInfo(m_globalResolveInfos[i], instructionOffsetForNth(exec, m_instructions, i + 1, isGlobalResolve)); + ++i; + } while (i < m_globalResolveInfos.size()); + } + if (!m_structureStubInfos.isEmpty()) { + size_t i = 0; + do { + printStructureStubInfo(m_structureStubInfos[i], instructionOffsetForNth(exec, m_instructions, i + 1, isPropertyAccess)); + ++i; + } while (i < m_structureStubInfos.size()); + } +#else + if (!m_globalResolveInstructions.isEmpty() || !m_propertyAccessInstructions.isEmpty()) + printf("\nStructures:\n"); + + if (!m_globalResolveInstructions.isEmpty()) { + size_t i = 0; + do { + printStructures(&m_instructions[m_globalResolveInstructions[i]]); + ++i; + } while (i < m_globalResolveInstructions.size()); + } + if (!m_propertyAccessInstructions.isEmpty()) { + size_t i = 0; + do { + printStructures(&m_instructions[m_propertyAccessInstructions[i]]); + ++i; + } while (i < m_propertyAccessInstructions.size()); + } +#endif + + if (m_rareData && !m_rareData->m_exceptionHandlers.isEmpty()) { + printf("\nException Handlers:\n"); + unsigned i = 0; + do { + printf("\t %d: { start: [%4d] end: [%4d] target: [%4d] }\n", i + 1, m_rareData->m_exceptionHandlers[i].start, m_rareData->m_exceptionHandlers[i].end, m_rareData->m_exceptionHandlers[i].target); + ++i; + } while (i < m_rareData->m_exceptionHandlers.size()); + } + + if (m_rareData && !m_rareData->m_immediateSwitchJumpTables.isEmpty()) { + printf("Immediate Switch Jump Tables:\n"); + unsigned i = 0; + do { + printf(" %1d = {\n", i); + int entry = 0; + Vector<int32_t>::const_iterator end = m_rareData->m_immediateSwitchJumpTables[i].branchOffsets.end(); + for (Vector<int32_t>::const_iterator iter = m_rareData->m_immediateSwitchJumpTables[i].branchOffsets.begin(); iter != end; ++iter, ++entry) { + if (!*iter) + continue; + printf("\t\t%4d => %04d\n", entry + m_rareData->m_immediateSwitchJumpTables[i].min, *iter); + } + printf(" }\n"); + ++i; + } while (i < m_rareData->m_immediateSwitchJumpTables.size()); + } + + if (m_rareData && !m_rareData->m_characterSwitchJumpTables.isEmpty()) { + printf("\nCharacter Switch Jump Tables:\n"); + unsigned i = 0; + do { + printf(" %1d = {\n", i); + int entry = 0; + Vector<int32_t>::const_iterator end = m_rareData->m_characterSwitchJumpTables[i].branchOffsets.end(); + for (Vector<int32_t>::const_iterator iter = m_rareData->m_characterSwitchJumpTables[i].branchOffsets.begin(); iter != end; ++iter, ++entry) { + if (!*iter) + continue; + ASSERT(!((i + m_rareData->m_characterSwitchJumpTables[i].min) & ~0xFFFF)); + UChar ch = static_cast<UChar>(entry + m_rareData->m_characterSwitchJumpTables[i].min); + printf("\t\t\"%s\" => %04d\n", UString(&ch, 1).ascii(), *iter); + } + printf(" }\n"); + ++i; + } while (i < m_rareData->m_characterSwitchJumpTables.size()); + } + + if (m_rareData && !m_rareData->m_stringSwitchJumpTables.isEmpty()) { + printf("\nString Switch Jump Tables:\n"); + unsigned i = 0; + do { + printf(" %1d = {\n", i); + StringJumpTable::StringOffsetTable::const_iterator end = m_rareData->m_stringSwitchJumpTables[i].offsetTable.end(); + for (StringJumpTable::StringOffsetTable::const_iterator iter = m_rareData->m_stringSwitchJumpTables[i].offsetTable.begin(); iter != end; ++iter) + printf("\t\t\"%s\" => %04d\n", UString(iter->first).ascii(), iter->second.branchOffset); + printf(" }\n"); + ++i; + } while (i < m_rareData->m_stringSwitchJumpTables.size()); + } + + printf("\n"); +} + +void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& begin, Vector<Instruction>::const_iterator& it) const +{ + int location = it - begin; + switch (exec->interpreter()->getOpcodeID(it->u.opcode)) { + case op_enter: { + printf("[%4d] enter\n", location); + break; + } + case op_enter_with_activation: { + int r0 = (++it)->u.operand; + printf("[%4d] enter_with_activation %s\n", location, registerName(r0).c_str()); + break; + } + case op_create_arguments: { + printf("[%4d] create_arguments\n", location); + break; + } + case op_convert_this: { + int r0 = (++it)->u.operand; + printf("[%4d] convert_this %s\n", location, registerName(r0).c_str()); + break; + } + case op_unexpected_load: { + int r0 = (++it)->u.operand; + int k0 = (++it)->u.operand; + printf("[%4d] unexpected_load\t %s, %s\n", location, registerName(r0).c_str(), constantName(exec, k0, unexpectedConstant(k0)).c_str()); + break; + } + case op_new_object: { + int r0 = (++it)->u.operand; + printf("[%4d] new_object\t %s\n", location, registerName(r0).c_str()); + break; + } + case op_new_array: { + int dst = (++it)->u.operand; + int argv = (++it)->u.operand; + int argc = (++it)->u.operand; + printf("[%4d] new_array\t %s, %s, %d\n", location, registerName(dst).c_str(), registerName(argv).c_str(), argc); + break; + } + case op_new_regexp: { + int r0 = (++it)->u.operand; + int re0 = (++it)->u.operand; + printf("[%4d] new_regexp\t %s, %s\n", location, registerName(r0).c_str(), regexpName(re0, regexp(re0)).c_str()); + break; + } + case op_mov: { + int r0 = (++it)->u.operand; + int r1 = (++it)->u.operand; + printf("[%4d] mov\t\t %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str()); + break; + } + case op_not: { + printUnaryOp(location, it, "not"); + break; + } + case op_eq: { + printBinaryOp(location, it, "eq"); + break; + } + case op_eq_null: { + printUnaryOp(location, it, "eq_null"); + break; + } + case op_neq: { + printBinaryOp(location, it, "neq"); + break; + } + case op_neq_null: { + printUnaryOp(location, it, "neq_null"); + break; + } + case op_stricteq: { + printBinaryOp(location, it, "stricteq"); + break; + } + case op_nstricteq: { + printBinaryOp(location, it, "nstricteq"); + break; + } + case op_less: { + printBinaryOp(location, it, "less"); + break; + } + case op_lesseq: { + printBinaryOp(location, it, "lesseq"); + break; + } + case op_pre_inc: { + int r0 = (++it)->u.operand; + printf("[%4d] pre_inc\t\t %s\n", location, registerName(r0).c_str()); + break; + } + case op_pre_dec: { + int r0 = (++it)->u.operand; + printf("[%4d] pre_dec\t\t %s\n", location, registerName(r0).c_str()); + break; + } + case op_post_inc: { + printUnaryOp(location, it, "post_inc"); + break; + } + case op_post_dec: { + printUnaryOp(location, it, "post_dec"); + break; + } + case op_to_jsnumber: { + printUnaryOp(location, it, "to_jsnumber"); + break; + } + case op_negate: { + printUnaryOp(location, it, "negate"); + break; + } + case op_add: { + printBinaryOp(location, it, "add"); + ++it; + break; + } + case op_mul: { + printBinaryOp(location, it, "mul"); + ++it; + break; + } + case op_div: { + printBinaryOp(location, it, "div"); + break; + } + case op_mod: { + printBinaryOp(location, it, "mod"); + break; + } + case op_sub: { + printBinaryOp(location, it, "sub"); + ++it; + break; + } + case op_lshift: { + printBinaryOp(location, it, "lshift"); + break; + } + case op_rshift: { + printBinaryOp(location, it, "rshift"); + break; + } + case op_urshift: { + printBinaryOp(location, it, "urshift"); + break; + } + case op_bitand: { + printBinaryOp(location, it, "bitand"); + ++it; + break; + } + case op_bitxor: { + printBinaryOp(location, it, "bitxor"); + ++it; + break; + } + case op_bitor: { + printBinaryOp(location, it, "bitor"); + ++it; + break; + } + case op_bitnot: { + printUnaryOp(location, it, "bitnot"); + break; + } + case op_instanceof: { + int r0 = (++it)->u.operand; + int r1 = (++it)->u.operand; + int r2 = (++it)->u.operand; + int r3 = (++it)->u.operand; + printf("[%4d] instanceof\t\t %s, %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str(), registerName(r3).c_str()); + break; + } + case op_typeof: { + printUnaryOp(location, it, "typeof"); + break; + } + case op_is_undefined: { + printUnaryOp(location, it, "is_undefined"); + break; + } + case op_is_boolean: { + printUnaryOp(location, it, "is_boolean"); + break; + } + case op_is_number: { + printUnaryOp(location, it, "is_number"); + break; + } + case op_is_string: { + printUnaryOp(location, it, "is_string"); + break; + } + case op_is_object: { + printUnaryOp(location, it, "is_object"); + break; + } + case op_is_function: { + printUnaryOp(location, it, "is_function"); + break; + } + case op_in: { + printBinaryOp(location, it, "in"); + break; + } + case op_resolve: { + int r0 = (++it)->u.operand; + int id0 = (++it)->u.operand; + printf("[%4d] resolve\t\t %s, %s\n", location, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str()); + break; + } + case op_resolve_skip: { + int r0 = (++it)->u.operand; + int id0 = (++it)->u.operand; + int skipLevels = (++it)->u.operand; + printf("[%4d] resolve_skip\t %s, %s, %d\n", location, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str(), skipLevels); + break; + } + case op_resolve_global: { + int r0 = (++it)->u.operand; + JSValuePtr scope = JSValuePtr((++it)->u.jsCell); + int id0 = (++it)->u.operand; + printf("[%4d] resolve_global\t %s, %s, %s\n", location, registerName(r0).c_str(), valueToSourceString(exec, scope).ascii(), idName(id0, m_identifiers[id0]).c_str()); + it += 2; + break; + } + case op_get_scoped_var: { + int r0 = (++it)->u.operand; + int index = (++it)->u.operand; + int skipLevels = (++it)->u.operand; + printf("[%4d] get_scoped_var\t %s, %d, %d\n", location, registerName(r0).c_str(), index, skipLevels); + break; + } + case op_put_scoped_var: { + int index = (++it)->u.operand; + int skipLevels = (++it)->u.operand; + int r0 = (++it)->u.operand; + printf("[%4d] put_scoped_var\t %d, %d, %s\n", location, index, skipLevels, registerName(r0).c_str()); + break; + } + case op_get_global_var: { + int r0 = (++it)->u.operand; + JSValuePtr scope = JSValuePtr((++it)->u.jsCell); + int index = (++it)->u.operand; + printf("[%4d] get_global_var\t %s, %s, %d\n", location, registerName(r0).c_str(), valueToSourceString(exec, scope).ascii(), index); + break; + } + case op_put_global_var: { + JSValuePtr scope = JSValuePtr((++it)->u.jsCell); + int index = (++it)->u.operand; + int r0 = (++it)->u.operand; + printf("[%4d] put_global_var\t %s, %d, %s\n", location, valueToSourceString(exec, scope).ascii(), index, registerName(r0).c_str()); + break; + } + case op_resolve_base: { + int r0 = (++it)->u.operand; + int id0 = (++it)->u.operand; + printf("[%4d] resolve_base\t %s, %s\n", location, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str()); + break; + } + case op_resolve_with_base: { + int r0 = (++it)->u.operand; + int r1 = (++it)->u.operand; + int id0 = (++it)->u.operand; + printf("[%4d] resolve_with_base %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), idName(id0, m_identifiers[id0]).c_str()); + break; + } + case op_resolve_func: { + int r0 = (++it)->u.operand; + int r1 = (++it)->u.operand; + int id0 = (++it)->u.operand; + printf("[%4d] resolve_func\t %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), idName(id0, m_identifiers[id0]).c_str()); + break; + } + case op_get_by_id: { + printGetByIdOp(location, it, m_identifiers, "get_by_id"); + break; + } + case op_get_by_id_self: { + printGetByIdOp(location, it, m_identifiers, "get_by_id_self"); + break; + } + case op_get_by_id_self_list: { + printGetByIdOp(location, it, m_identifiers, "get_by_id_self_list"); + break; + } + case op_get_by_id_proto: { + printGetByIdOp(location, it, m_identifiers, "get_by_id_proto"); + break; + } + case op_get_by_id_proto_list: { + printGetByIdOp(location, it, m_identifiers, "op_get_by_id_proto_list"); + break; + } + case op_get_by_id_chain: { + printGetByIdOp(location, it, m_identifiers, "get_by_id_chain"); + break; + } + case op_get_by_id_generic: { + printGetByIdOp(location, it, m_identifiers, "get_by_id_generic"); + break; + } + case op_get_array_length: { + printGetByIdOp(location, it, m_identifiers, "get_array_length"); + break; + } + case op_get_string_length: { + printGetByIdOp(location, it, m_identifiers, "get_string_length"); + break; + } + case op_put_by_id: { + printPutByIdOp(location, it, m_identifiers, "put_by_id"); + break; + } + case op_put_by_id_replace: { + printPutByIdOp(location, it, m_identifiers, "put_by_id_replace"); + break; + } + case op_put_by_id_transition: { + printPutByIdOp(location, it, m_identifiers, "put_by_id_transition"); + break; + } + case op_put_by_id_generic: { + printPutByIdOp(location, it, m_identifiers, "put_by_id_generic"); + break; + } + case op_put_getter: { + int r0 = (++it)->u.operand; + int id0 = (++it)->u.operand; + int r1 = (++it)->u.operand; + printf("[%4d] put_getter\t %s, %s, %s\n", location, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str(), registerName(r1).c_str()); + break; + } + case op_put_setter: { + int r0 = (++it)->u.operand; + int id0 = (++it)->u.operand; + int r1 = (++it)->u.operand; + printf("[%4d] put_setter\t %s, %s, %s\n", location, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str(), registerName(r1).c_str()); + break; + } + case op_del_by_id: { + int r0 = (++it)->u.operand; + int r1 = (++it)->u.operand; + int id0 = (++it)->u.operand; + printf("[%4d] del_by_id\t %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), idName(id0, m_identifiers[id0]).c_str()); + break; + } + case op_get_by_val: { + int r0 = (++it)->u.operand; + int r1 = (++it)->u.operand; + int r2 = (++it)->u.operand; + printf("[%4d] get_by_val\t %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str()); + break; + } + case op_put_by_val: { + int r0 = (++it)->u.operand; + int r1 = (++it)->u.operand; + int r2 = (++it)->u.operand; + printf("[%4d] put_by_val\t %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str()); + break; + } + case op_del_by_val: { + int r0 = (++it)->u.operand; + int r1 = (++it)->u.operand; + int r2 = (++it)->u.operand; + printf("[%4d] del_by_val\t %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str()); + break; + } + case op_put_by_index: { + int r0 = (++it)->u.operand; + unsigned n0 = (++it)->u.operand; + int r1 = (++it)->u.operand; + printf("[%4d] put_by_index\t %s, %u, %s\n", location, registerName(r0).c_str(), n0, registerName(r1).c_str()); + break; + } + case op_jmp: { + int offset = (++it)->u.operand; + printf("[%4d] jmp\t\t %d(->%d)\n", location, offset, locationForOffset(begin, it, offset)); + break; + } + case op_loop: { + int offset = (++it)->u.operand; + printf("[%4d] loop\t\t %d(->%d)\n", location, offset, locationForOffset(begin, it, offset)); + break; + } + case op_jtrue: { + printConditionalJump(begin, it, location, "jtrue"); + break; + } + case op_loop_if_true: { + printConditionalJump(begin, it, location, "loop_if_true"); + break; + } + case op_jfalse: { + printConditionalJump(begin, it, location, "jfalse"); + break; + } + case op_jeq_null: { + printConditionalJump(begin, it, location, "jeq_null"); + break; + } + case op_jneq_null: { + printConditionalJump(begin, it, location, "jneq_null"); + break; + } + case op_jnless: { + int r0 = (++it)->u.operand; + int r1 = (++it)->u.operand; + int offset = (++it)->u.operand; + printf("[%4d] jnless\t\t %s, %s, %d(->%d)\n", location, registerName(r0).c_str(), registerName(r1).c_str(), offset, locationForOffset(begin, it, offset)); + break; + } + case op_loop_if_less: { + int r0 = (++it)->u.operand; + int r1 = (++it)->u.operand; + int offset = (++it)->u.operand; + printf("[%4d] loop_if_less\t %s, %s, %d(->%d)\n", location, registerName(r0).c_str(), registerName(r1).c_str(), offset, locationForOffset(begin, it, offset)); + break; + } + case op_loop_if_lesseq: { + int r0 = (++it)->u.operand; + int r1 = (++it)->u.operand; + int offset = (++it)->u.operand; + printf("[%4d] loop_if_lesseq\t %s, %s, %d(->%d)\n", location, registerName(r0).c_str(), registerName(r1).c_str(), offset, locationForOffset(begin, it, offset)); + break; + } + case op_switch_imm: { + int tableIndex = (++it)->u.operand; + int defaultTarget = (++it)->u.operand; + int scrutineeRegister = (++it)->u.operand; + printf("[%4d] switch_imm\t %d, %d(->%d), %s\n", location, tableIndex, defaultTarget, locationForOffset(begin, it, defaultTarget), registerName(scrutineeRegister).c_str()); + break; + } + case op_switch_char: { + int tableIndex = (++it)->u.operand; + int defaultTarget = (++it)->u.operand; + int scrutineeRegister = (++it)->u.operand; + printf("[%4d] switch_char\t %d, %d(->%d), %s\n", location, tableIndex, defaultTarget, locationForOffset(begin, it, defaultTarget), registerName(scrutineeRegister).c_str()); + break; + } + case op_switch_string: { + int tableIndex = (++it)->u.operand; + int defaultTarget = (++it)->u.operand; + int scrutineeRegister = (++it)->u.operand; + printf("[%4d] switch_string\t %d, %d(->%d), %s\n", location, tableIndex, defaultTarget, locationForOffset(begin, it, defaultTarget), registerName(scrutineeRegister).c_str()); + break; + } + case op_new_func: { + int r0 = (++it)->u.operand; + int f0 = (++it)->u.operand; + printf("[%4d] new_func\t\t %s, f%d\n", location, registerName(r0).c_str(), f0); + break; + } + case op_new_func_exp: { + int r0 = (++it)->u.operand; + int f0 = (++it)->u.operand; + printf("[%4d] new_func_exp\t %s, f%d\n", location, registerName(r0).c_str(), f0); + break; + } + case op_call: { + int dst = (++it)->u.operand; + int func = (++it)->u.operand; + int argCount = (++it)->u.operand; + int registerOffset = (++it)->u.operand; + printf("[%4d] call\t\t %s, %s, %d, %d\n", location, registerName(dst).c_str(), registerName(func).c_str(), argCount, registerOffset); + break; + } + case op_call_eval: { + int dst = (++it)->u.operand; + int func = (++it)->u.operand; + int argCount = (++it)->u.operand; + int registerOffset = (++it)->u.operand; + printf("[%4d] call_eval\t %s, %s, %d, %d\n", location, registerName(dst).c_str(), registerName(func).c_str(), argCount, registerOffset); + break; + } + case op_tear_off_activation: { + int r0 = (++it)->u.operand; + printf("[%4d] tear_off_activation\t %s\n", location, registerName(r0).c_str()); + break; + } + case op_tear_off_arguments: { + printf("[%4d] tear_off_arguments\n", location); + break; + } + case op_ret: { + int r0 = (++it)->u.operand; + printf("[%4d] ret\t\t %s\n", location, registerName(r0).c_str()); + break; + } + case op_construct: { + int dst = (++it)->u.operand; + int func = (++it)->u.operand; + int argCount = (++it)->u.operand; + int registerOffset = (++it)->u.operand; + int proto = (++it)->u.operand; + int thisRegister = (++it)->u.operand; + printf("[%4d] construct\t %s, %s, %d, %d, %s, %s\n", location, registerName(dst).c_str(), registerName(func).c_str(), argCount, registerOffset, registerName(proto).c_str(), registerName(thisRegister).c_str()); + break; + } + case op_construct_verify: { + int r0 = (++it)->u.operand; + int r1 = (++it)->u.operand; + printf("[%4d] construct_verify\t %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str()); + break; + } + case op_get_pnames: { + int r0 = (++it)->u.operand; + int r1 = (++it)->u.operand; + printf("[%4d] get_pnames\t %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str()); + break; + } + case op_next_pname: { + int dest = (++it)->u.operand; + int iter = (++it)->u.operand; + int offset = (++it)->u.operand; + printf("[%4d] next_pname\t %s, %s, %d(->%d)\n", location, registerName(dest).c_str(), registerName(iter).c_str(), offset, locationForOffset(begin, it, offset)); + break; + } + case op_push_scope: { + int r0 = (++it)->u.operand; + printf("[%4d] push_scope\t %s\n", location, registerName(r0).c_str()); + break; + } + case op_pop_scope: { + printf("[%4d] pop_scope\n", location); + break; + } + case op_push_new_scope: { + int r0 = (++it)->u.operand; + int id0 = (++it)->u.operand; + int r1 = (++it)->u.operand; + printf("[%4d] push_new_scope \t%s, %s, %s\n", location, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str(), registerName(r1).c_str()); + break; + } + case op_jmp_scopes: { + int scopeDelta = (++it)->u.operand; + int offset = (++it)->u.operand; + printf("[%4d] jmp_scopes\t^%d, %d(->%d)\n", location, scopeDelta, offset, locationForOffset(begin, it, offset)); + break; + } + case op_catch: { + int r0 = (++it)->u.operand; + printf("[%4d] catch\t\t %s\n", location, registerName(r0).c_str()); + break; + } + case op_throw: { + int r0 = (++it)->u.operand; + printf("[%4d] throw\t\t %s\n", location, registerName(r0).c_str()); + break; + } + case op_new_error: { + int r0 = (++it)->u.operand; + int errorType = (++it)->u.operand; + int k0 = (++it)->u.operand; + printf("[%4d] new_error\t %s, %d, %s\n", location, registerName(r0).c_str(), errorType, constantName(exec, k0, unexpectedConstant(k0)).c_str()); + break; + } + case op_jsr: { + int retAddrDst = (++it)->u.operand; + int offset = (++it)->u.operand; + printf("[%4d] jsr\t\t %s, %d(->%d)\n", location, registerName(retAddrDst).c_str(), offset, locationForOffset(begin, it, offset)); + break; + } + case op_sret: { + int retAddrSrc = (++it)->u.operand; + printf("[%4d] sret\t\t %s\n", location, registerName(retAddrSrc).c_str()); + break; + } + case op_debug: { + int debugHookID = (++it)->u.operand; + int firstLine = (++it)->u.operand; + int lastLine = (++it)->u.operand; + printf("[%4d] debug\t\t %s, %d, %d\n", location, debugHookName(debugHookID), firstLine, lastLine); + break; + } + case op_profile_will_call: { + int function = (++it)->u.operand; + printf("[%4d] profile_will_call %s\n", location, registerName(function).c_str()); + break; + } + case op_profile_did_call: { + int function = (++it)->u.operand; + printf("[%4d] profile_did_call\t %s\n", location, registerName(function).c_str()); + break; + } + case op_end: { + int r0 = (++it)->u.operand; + printf("[%4d] end\t\t %s\n", location, registerName(r0).c_str()); + break; + } + } +} + +#endif // !defined(NDEBUG) || ENABLE(OPCODE_SAMPLING) + +#if DUMP_CODE_BLOCK_STATISTICS +static HashSet<CodeBlock*> liveCodeBlockSet; +#endif + +#define FOR_EACH_MEMBER_VECTOR(macro) \ + macro(instructions) \ + macro(globalResolveInfos) \ + macro(structureStubInfos) \ + macro(callLinkInfos) \ + macro(linkedCallerList) \ + macro(identifiers) \ + macro(functionExpressions) \ + macro(constantRegisters) + +#define FOR_EACH_MEMBER_VECTOR_RARE_DATA(macro) \ + macro(regexps) \ + macro(functions) \ + macro(unexpectedConstants) \ + macro(exceptionHandlers) \ + macro(immediateSwitchJumpTables) \ + macro(characterSwitchJumpTables) \ + macro(stringSwitchJumpTables) \ + macro(functionRegisterInfos) + +#define FOR_EACH_MEMBER_VECTOR_EXCEPTION_INFO(macro) \ + macro(expressionInfo) \ + macro(lineInfo) \ + macro(getByIdExceptionInfo) \ + macro(pcVector) + +template<typename T> +static size_t sizeInBytes(const Vector<T>& vector) +{ + return vector.capacity() * sizeof(T); +} + +void CodeBlock::dumpStatistics() +{ +#if DUMP_CODE_BLOCK_STATISTICS + #define DEFINE_VARS(name) size_t name##IsNotEmpty = 0; size_t name##TotalSize = 0; + FOR_EACH_MEMBER_VECTOR(DEFINE_VARS) + FOR_EACH_MEMBER_VECTOR_RARE_DATA(DEFINE_VARS) + FOR_EACH_MEMBER_VECTOR_EXCEPTION_INFO(DEFINE_VARS) + #undef DEFINE_VARS + + // Non-vector data members + size_t evalCodeCacheIsNotEmpty = 0; + + size_t symbolTableIsNotEmpty = 0; + size_t symbolTableTotalSize = 0; + + size_t hasExceptionInfo = 0; + size_t hasRareData = 0; + + size_t isFunctionCode = 0; + size_t isGlobalCode = 0; + size_t isEvalCode = 0; + + HashSet<CodeBlock*>::const_iterator end = liveCodeBlockSet.end(); + for (HashSet<CodeBlock*>::const_iterator it = liveCodeBlockSet.begin(); it != end; ++it) { + CodeBlock* codeBlock = *it; + + #define GET_STATS(name) if (!codeBlock->m_##name.isEmpty()) { name##IsNotEmpty++; name##TotalSize += sizeInBytes(codeBlock->m_##name); } + FOR_EACH_MEMBER_VECTOR(GET_STATS) + #undef GET_STATS + + if (!codeBlock->m_symbolTable.isEmpty()) { + symbolTableIsNotEmpty++; + symbolTableTotalSize += (codeBlock->m_symbolTable.capacity() * (sizeof(SymbolTable::KeyType) + sizeof(SymbolTable::MappedType))); + } + + if (codeBlock->m_exceptionInfo) { + hasExceptionInfo++; + #define GET_STATS(name) if (!codeBlock->m_exceptionInfo->m_##name.isEmpty()) { name##IsNotEmpty++; name##TotalSize += sizeInBytes(codeBlock->m_exceptionInfo->m_##name); } + FOR_EACH_MEMBER_VECTOR_EXCEPTION_INFO(GET_STATS) + #undef GET_STATS + } + + if (codeBlock->m_rareData) { + hasRareData++; + #define GET_STATS(name) if (!codeBlock->m_rareData->m_##name.isEmpty()) { name##IsNotEmpty++; name##TotalSize += sizeInBytes(codeBlock->m_rareData->m_##name); } + FOR_EACH_MEMBER_VECTOR_RARE_DATA(GET_STATS) + #undef GET_STATS + + if (!codeBlock->m_rareData->m_evalCodeCache.isEmpty()) + evalCodeCacheIsNotEmpty++; + } + + switch (codeBlock->codeType()) { + case FunctionCode: + ++isFunctionCode; + break; + case GlobalCode: + ++isGlobalCode; + break; + case EvalCode: + ++isEvalCode; + break; + } + } + + size_t totalSize = 0; + + #define GET_TOTAL_SIZE(name) totalSize += name##TotalSize; + FOR_EACH_MEMBER_VECTOR(GET_TOTAL_SIZE) + FOR_EACH_MEMBER_VECTOR_RARE_DATA(GET_TOTAL_SIZE) + FOR_EACH_MEMBER_VECTOR_EXCEPTION_INFO(GET_TOTAL_SIZE) + #undef GET_TOTAL_SIZE + + totalSize += symbolTableTotalSize; + totalSize += (liveCodeBlockSet.size() * sizeof(CodeBlock)); + + printf("Number of live CodeBlocks: %d\n", liveCodeBlockSet.size()); + printf("Size of a single CodeBlock [sizeof(CodeBlock)]: %zu\n", sizeof(CodeBlock)); + printf("Size of all CodeBlocks: %zu\n", totalSize); + printf("Average size of a CodeBlock: %zu\n", totalSize / liveCodeBlockSet.size()); + + printf("Number of FunctionCode CodeBlocks: %zu (%.3f%%)\n", isFunctionCode, static_cast<double>(isFunctionCode) * 100.0 / liveCodeBlockSet.size()); + printf("Number of GlobalCode CodeBlocks: %zu (%.3f%%)\n", isGlobalCode, static_cast<double>(isGlobalCode) * 100.0 / liveCodeBlockSet.size()); + printf("Number of EvalCode CodeBlocks: %zu (%.3f%%)\n", isEvalCode, static_cast<double>(isEvalCode) * 100.0 / liveCodeBlockSet.size()); + + printf("Number of CodeBlocks with exception info: %zu (%.3f%%)\n", hasExceptionInfo, static_cast<double>(hasExceptionInfo) * 100.0 / liveCodeBlockSet.size()); + printf("Number of CodeBlocks with rare data: %zu (%.3f%%)\n", hasRareData, static_cast<double>(hasRareData) * 100.0 / liveCodeBlockSet.size()); + + #define PRINT_STATS(name) printf("Number of CodeBlocks with " #name ": %zu\n", name##IsNotEmpty); printf("Size of all " #name ": %zu\n", name##TotalSize); + FOR_EACH_MEMBER_VECTOR(PRINT_STATS) + FOR_EACH_MEMBER_VECTOR_RARE_DATA(PRINT_STATS) + FOR_EACH_MEMBER_VECTOR_EXCEPTION_INFO(PRINT_STATS) + #undef PRINT_STATS + + printf("Number of CodeBlocks with evalCodeCache: %zu\n", evalCodeCacheIsNotEmpty); + printf("Number of CodeBlocks with symbolTable: %zu\n", symbolTableIsNotEmpty); + + printf("Size of all symbolTables: %zu\n", symbolTableTotalSize); + +#else + printf("Dumping CodeBlock statistics is not enabled.\n"); +#endif +} + + +CodeBlock::CodeBlock(ScopeNode* ownerNode, CodeType codeType, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset) + : m_numCalleeRegisters(0) + , m_numConstants(0) + , m_numVars(0) + , m_numParameters(0) + , m_ownerNode(ownerNode) + , m_globalData(0) +#ifndef NDEBUG + , m_instructionCount(0) +#endif + , m_needsFullScopeChain(ownerNode->needsActivation()) + , m_usesEval(ownerNode->usesEval()) + , m_isNumericCompareFunction(false) + , m_codeType(codeType) + , m_source(sourceProvider) + , m_sourceOffset(sourceOffset) + , m_exceptionInfo(new ExceptionInfo) +{ + ASSERT(m_source); + +#if DUMP_CODE_BLOCK_STATISTICS + liveCodeBlockSet.add(this); +#endif +} + +CodeBlock::~CodeBlock() +{ +#if !ENABLE(JIT) + for (size_t size = m_globalResolveInstructions.size(), i = 0; i < size; ++i) + derefStructures(&m_instructions[m_globalResolveInstructions[i]]); + + for (size_t size = m_propertyAccessInstructions.size(), i = 0; i < size; ++i) + derefStructures(&m_instructions[m_propertyAccessInstructions[i]]); +#else + for (size_t size = m_globalResolveInfos.size(), i = 0; i < size; ++i) { + if (m_globalResolveInfos[i].structure) + m_globalResolveInfos[i].structure->deref(); + } + + for (size_t size = m_structureStubInfos.size(), i = 0; i < size; ++i) + m_structureStubInfos[i].deref(); + + for (size_t size = m_callLinkInfos.size(), i = 0; i < size; ++i) { + CallLinkInfo* callLinkInfo = &m_callLinkInfos[i]; + if (callLinkInfo->isLinked()) + callLinkInfo->callee->removeCaller(callLinkInfo); + } + + unlinkCallers(); +#endif + +#if DUMP_CODE_BLOCK_STATISTICS + liveCodeBlockSet.remove(this); +#endif +} + +#if ENABLE(JIT) +void CodeBlock::unlinkCallers() +{ + size_t size = m_linkedCallerList.size(); + for (size_t i = 0; i < size; ++i) { + CallLinkInfo* currentCaller = m_linkedCallerList[i]; + JIT::unlinkCall(currentCaller); + currentCaller->setUnlinked(); + } + m_linkedCallerList.clear(); +} +#endif + +void CodeBlock::derefStructures(Instruction* vPC) const +{ + Interpreter* interpreter = m_globalData->interpreter; + + if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self)) { + vPC[4].u.structure->deref(); + return; + } + if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto)) { + vPC[4].u.structure->deref(); + vPC[5].u.structure->deref(); + return; + } + if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_chain)) { + vPC[4].u.structure->deref(); + vPC[5].u.structureChain->deref(); + return; + } + if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_transition)) { + vPC[4].u.structure->deref(); + vPC[5].u.structure->deref(); + vPC[6].u.structureChain->deref(); + return; + } + if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_replace)) { + vPC[4].u.structure->deref(); + return; + } + if (vPC[0].u.opcode == interpreter->getOpcode(op_resolve_global)) { + if(vPC[4].u.structure) + vPC[4].u.structure->deref(); + return; + } + if ((vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto_list)) + || (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self_list))) { + PolymorphicAccessStructureList* polymorphicStructures = vPC[4].u.polymorphicStructures; + polymorphicStructures->derefStructures(vPC[5].u.operand); + delete polymorphicStructures; + return; + } + + // These instructions don't ref their Structures. + ASSERT(vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id) || vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_generic) || vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_generic) || vPC[0].u.opcode == interpreter->getOpcode(op_get_array_length) || vPC[0].u.opcode == interpreter->getOpcode(op_get_string_length)); +} + +void CodeBlock::refStructures(Instruction* vPC) const +{ + Interpreter* interpreter = m_globalData->interpreter; + + if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self)) { + vPC[4].u.structure->ref(); + return; + } + if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto)) { + vPC[4].u.structure->ref(); + vPC[5].u.structure->ref(); + return; + } + if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_chain)) { + vPC[4].u.structure->ref(); + vPC[5].u.structureChain->ref(); + return; + } + if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_transition)) { + vPC[4].u.structure->ref(); + vPC[5].u.structure->ref(); + vPC[6].u.structureChain->ref(); + return; + } + if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_replace)) { + vPC[4].u.structure->ref(); + return; + } + + // These instructions don't ref their Structures. + ASSERT(vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id) || vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_generic) || vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_generic)); +} + +void CodeBlock::mark() +{ + for (size_t i = 0; i < m_constantRegisters.size(); ++i) + if (!m_constantRegisters[i].marked()) + m_constantRegisters[i].mark(); + + for (size_t i = 0; i < m_functionExpressions.size(); ++i) + m_functionExpressions[i]->body()->mark(); + + if (m_rareData) { + for (size_t i = 0; i < m_rareData->m_functions.size(); ++i) + m_rareData->m_functions[i]->body()->mark(); + + for (size_t i = 0; i < m_rareData->m_unexpectedConstants.size(); ++i) { + if (!m_rareData->m_unexpectedConstants[i].marked()) + m_rareData->m_unexpectedConstants[i].mark(); + } + m_rareData->m_evalCodeCache.mark(); + } +} + +void CodeBlock::reparseForExceptionInfoIfNecessary(CallFrame* callFrame) +{ + if (m_exceptionInfo) + return; + + ScopeChainNode* scopeChain = callFrame->scopeChain(); + if (m_needsFullScopeChain) { + ScopeChain sc(scopeChain); + int scopeDelta = sc.localDepth(); + if (m_codeType == EvalCode) + scopeDelta -= static_cast<EvalCodeBlock*>(this)->baseScopeDepth(); + else if (m_codeType == FunctionCode) + scopeDelta++; // Compilation of function code assumes activation is not on the scope chain yet. + ASSERT(scopeDelta >= 0); + while (scopeDelta--) + scopeChain = scopeChain->next; + } + + switch (m_codeType) { + case FunctionCode: { + FunctionBodyNode* ownerFunctionBodyNode = static_cast<FunctionBodyNode*>(m_ownerNode); + RefPtr<FunctionBodyNode> newFunctionBody = m_globalData->parser->reparse<FunctionBodyNode>(m_globalData, ownerFunctionBodyNode); + ASSERT(newFunctionBody); + newFunctionBody->finishParsing(ownerFunctionBodyNode->copyParameters(), ownerFunctionBodyNode->parameterCount()); + + m_globalData->scopeNodeBeingReparsed = newFunctionBody.get(); + + CodeBlock& newCodeBlock = newFunctionBody->bytecodeForExceptionInfoReparse(scopeChain, this); + ASSERT(newCodeBlock.m_exceptionInfo); + ASSERT(newCodeBlock.m_instructionCount == m_instructionCount); + +#if ENABLE(JIT) + JIT::compile(m_globalData, &newCodeBlock); + ASSERT(newCodeBlock.m_jitCode.codeSize == m_jitCode.codeSize); +#endif + + m_exceptionInfo.set(newCodeBlock.m_exceptionInfo.release()); + + m_globalData->scopeNodeBeingReparsed = 0; + + break; + } + case EvalCode: { + EvalNode* ownerEvalNode = static_cast<EvalNode*>(m_ownerNode); + RefPtr<EvalNode> newEvalBody = m_globalData->parser->reparse<EvalNode>(m_globalData, ownerEvalNode); + + m_globalData->scopeNodeBeingReparsed = newEvalBody.get(); + + EvalCodeBlock& newCodeBlock = newEvalBody->bytecodeForExceptionInfoReparse(scopeChain, this); + ASSERT(newCodeBlock.m_exceptionInfo); + ASSERT(newCodeBlock.m_instructionCount == m_instructionCount); + +#if ENABLE(JIT) + JIT::compile(m_globalData, &newCodeBlock); + ASSERT(newCodeBlock.m_jitCode.codeSize == m_jitCode.codeSize); +#endif + + m_exceptionInfo.set(newCodeBlock.m_exceptionInfo.release()); + + m_globalData->scopeNodeBeingReparsed = 0; + + break; + } + default: + // CodeBlocks for Global code blocks are transient and therefore to not gain from + // from throwing out there exception information. + ASSERT_NOT_REACHED(); + } +} + +HandlerInfo* CodeBlock::handlerForBytecodeOffset(unsigned bytecodeOffset) +{ + ASSERT(bytecodeOffset < m_instructionCount); + + if (!m_rareData) + return 0; + + Vector<HandlerInfo>& exceptionHandlers = m_rareData->m_exceptionHandlers; + for (size_t i = 0; i < exceptionHandlers.size(); ++i) { + // Handlers are ordered innermost first, so the first handler we encounter + // that contains the source address is the correct handler to use. + if (exceptionHandlers[i].start <= bytecodeOffset && exceptionHandlers[i].end >= bytecodeOffset) + return &exceptionHandlers[i]; + } + + return 0; +} + +int CodeBlock::lineNumberForBytecodeOffset(CallFrame* callFrame, unsigned bytecodeOffset) +{ + ASSERT(bytecodeOffset < m_instructionCount); + + reparseForExceptionInfoIfNecessary(callFrame); + ASSERT(m_exceptionInfo); + + if (!m_exceptionInfo->m_lineInfo.size()) + return m_ownerNode->source().firstLine(); // Empty function + + int low = 0; + int high = m_exceptionInfo->m_lineInfo.size(); + while (low < high) { + int mid = low + (high - low) / 2; + if (m_exceptionInfo->m_lineInfo[mid].instructionOffset <= bytecodeOffset) + low = mid + 1; + else + high = mid; + } + + if (!low) + return m_ownerNode->source().firstLine(); + return m_exceptionInfo->m_lineInfo[low - 1].lineNumber; +} + +int CodeBlock::expressionRangeForBytecodeOffset(CallFrame* callFrame, unsigned bytecodeOffset, int& divot, int& startOffset, int& endOffset) +{ + ASSERT(bytecodeOffset < m_instructionCount); + + reparseForExceptionInfoIfNecessary(callFrame); + ASSERT(m_exceptionInfo); + + if (!m_exceptionInfo->m_expressionInfo.size()) { + // We didn't think anything could throw. Apparently we were wrong. + startOffset = 0; + endOffset = 0; + divot = 0; + return lineNumberForBytecodeOffset(callFrame, bytecodeOffset); + } + + int low = 0; + int high = m_exceptionInfo->m_expressionInfo.size(); + while (low < high) { + int mid = low + (high - low) / 2; + if (m_exceptionInfo->m_expressionInfo[mid].instructionOffset <= bytecodeOffset) + low = mid + 1; + else + high = mid; + } + + ASSERT(low); + if (!low) { + startOffset = 0; + endOffset = 0; + divot = 0; + return lineNumberForBytecodeOffset(callFrame, bytecodeOffset); + } + + startOffset = m_exceptionInfo->m_expressionInfo[low - 1].startOffset; + endOffset = m_exceptionInfo->m_expressionInfo[low - 1].endOffset; + divot = m_exceptionInfo->m_expressionInfo[low - 1].divotPoint + m_sourceOffset; + return lineNumberForBytecodeOffset(callFrame, bytecodeOffset); +} + +bool CodeBlock::getByIdExceptionInfoForBytecodeOffset(CallFrame* callFrame, unsigned bytecodeOffset, OpcodeID& opcodeID) +{ + ASSERT(bytecodeOffset < m_instructionCount); + + reparseForExceptionInfoIfNecessary(callFrame); + ASSERT(m_exceptionInfo); + + if (!m_exceptionInfo->m_getByIdExceptionInfo.size()) + return false; + + int low = 0; + int high = m_exceptionInfo->m_getByIdExceptionInfo.size(); + while (low < high) { + int mid = low + (high - low) / 2; + if (m_exceptionInfo->m_getByIdExceptionInfo[mid].bytecodeOffset <= bytecodeOffset) + low = mid + 1; + else + high = mid; + } + + if (!low || m_exceptionInfo->m_getByIdExceptionInfo[low - 1].bytecodeOffset != bytecodeOffset) + return false; + + opcodeID = m_exceptionInfo->m_getByIdExceptionInfo[low - 1].isOpConstruct ? op_construct : op_instanceof; + return true; +} + +#if ENABLE(JIT) +bool CodeBlock::functionRegisterForBytecodeOffset(unsigned bytecodeOffset, int& functionRegisterIndex) +{ + ASSERT(bytecodeOffset < m_instructionCount); + + if (!m_rareData || !m_rareData->m_functionRegisterInfos.size()) + return false; + + int low = 0; + int high = m_rareData->m_functionRegisterInfos.size(); + while (low < high) { + int mid = low + (high - low) / 2; + if (m_rareData->m_functionRegisterInfos[mid].bytecodeOffset <= bytecodeOffset) + low = mid + 1; + else + high = mid; + } + + if (!low || m_rareData->m_functionRegisterInfos[low - 1].bytecodeOffset != bytecodeOffset) + return false; + + functionRegisterIndex = m_rareData->m_functionRegisterInfos[low - 1].functionRegisterIndex; + return true; +} +#endif + +#if !ENABLE(JIT) +bool CodeBlock::hasGlobalResolveInstructionAtBytecodeOffset(unsigned bytecodeOffset) +{ + if (m_globalResolveInstructions.isEmpty()) + return false; + + int low = 0; + int high = m_globalResolveInstructions.size(); + while (low < high) { + int mid = low + (high - low) / 2; + if (m_globalResolveInstructions[mid] <= bytecodeOffset) + low = mid + 1; + else + high = mid; + } + + if (!low || m_globalResolveInstructions[low - 1] != bytecodeOffset) + return false; + return true; +} +#else +bool CodeBlock::hasGlobalResolveInfoAtBytecodeOffset(unsigned bytecodeOffset) +{ + if (m_globalResolveInfos.isEmpty()) + return false; + + int low = 0; + int high = m_globalResolveInfos.size(); + while (low < high) { + int mid = low + (high - low) / 2; + if (m_globalResolveInfos[mid].bytecodeOffset <= bytecodeOffset) + low = mid + 1; + else + high = mid; + } + + if (!low || m_globalResolveInfos[low - 1].bytecodeOffset != bytecodeOffset) + return false; + return true; +} +#endif + +#if ENABLE(JIT) +void CodeBlock::setJITCode(JITCodeRef& jitCode) +{ + m_jitCode = jitCode; +#if !ENABLE(OPCODE_SAMPLING) + if (!BytecodeGenerator::dumpsGeneratedCode()) + m_instructions.clear(); +#endif +} +#endif + +void CodeBlock::shrinkToFit() +{ + m_instructions.shrinkToFit(); + +#if !ENABLE(JIT) + m_propertyAccessInstructions.shrinkToFit(); + m_globalResolveInstructions.shrinkToFit(); +#else + m_structureStubInfos.shrinkToFit(); + m_globalResolveInfos.shrinkToFit(); + m_callLinkInfos.shrinkToFit(); + m_linkedCallerList.shrinkToFit(); +#endif + + m_identifiers.shrinkToFit(); + m_functionExpressions.shrinkToFit(); + m_constantRegisters.shrinkToFit(); + + if (m_exceptionInfo) { + m_exceptionInfo->m_expressionInfo.shrinkToFit(); + m_exceptionInfo->m_lineInfo.shrinkToFit(); + m_exceptionInfo->m_getByIdExceptionInfo.shrinkToFit(); + } + + if (m_rareData) { + m_rareData->m_exceptionHandlers.shrinkToFit(); + m_rareData->m_functions.shrinkToFit(); + m_rareData->m_unexpectedConstants.shrinkToFit(); + m_rareData->m_regexps.shrinkToFit(); + m_rareData->m_immediateSwitchJumpTables.shrinkToFit(); + m_rareData->m_characterSwitchJumpTables.shrinkToFit(); + m_rareData->m_stringSwitchJumpTables.shrinkToFit(); +#if ENABLE(JIT) + m_rareData->m_functionRegisterInfos.shrinkToFit(); +#endif + } +} + +} // namespace JSC diff --git a/JavaScriptCore/bytecode/CodeBlock.h b/JavaScriptCore/bytecode/CodeBlock.h new file mode 100644 index 0000000..e5d78d3 --- /dev/null +++ b/JavaScriptCore/bytecode/CodeBlock.h @@ -0,0 +1,584 @@ +/* + * Copyright (C) 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca> + * + * 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 CodeBlock_h +#define CodeBlock_h + +#include "EvalCodeCache.h" +#include "Instruction.h" +#include "JSGlobalObject.h" +#include "JumpTable.h" +#include "Nodes.h" +#include "RegExp.h" +#include "UString.h" +#include <wtf/RefPtr.h> +#include <wtf/Vector.h> + +#if ENABLE(JIT) +#include "StructureStubInfo.h" +#endif + +namespace JSC { + + class ExecState; + + enum CodeType { GlobalCode, EvalCode, FunctionCode }; + + static ALWAYS_INLINE int missingThisObjectMarker() { return std::numeric_limits<int>::max(); } + + struct HandlerInfo { + uint32_t start; + uint32_t end; + uint32_t target; + uint32_t scopeDepth; +#if ENABLE(JIT) + void* nativeCode; +#endif + }; + +#if ENABLE(JIT) + // The code, and the associated pool from which it was allocated. + struct JITCodeRef { + void* code; +#ifndef NDEBUG + unsigned codeSize; +#endif + RefPtr<ExecutablePool> executablePool; + + JITCodeRef() + : code(0) +#ifndef NDEBUG + , codeSize(0) +#endif + { + } + + JITCodeRef(void* code, PassRefPtr<ExecutablePool> executablePool) + : code(code) +#ifndef NDEBUG + , codeSize(0) +#endif + , executablePool(executablePool) + { + } + }; +#endif + + struct ExpressionRangeInfo { + enum { + MaxOffset = (1 << 7) - 1, + MaxDivot = (1 << 25) - 1 + }; + uint32_t instructionOffset : 25; + uint32_t divotPoint : 25; + uint32_t startOffset : 7; + uint32_t endOffset : 7; + }; + + struct LineInfo { + uint32_t instructionOffset; + int32_t lineNumber; + }; + + // Both op_construct and op_instanceof require a use of op_get_by_id to get + // the prototype property from an object. The exception messages for exceptions + // thrown by these instances op_get_by_id need to reflect this. + struct GetByIdExceptionInfo { + unsigned bytecodeOffset : 31; + bool isOpConstruct : 1; + }; + +#if ENABLE(JIT) + struct CallLinkInfo { + CallLinkInfo() + : callReturnLocation(0) + , hotPathBegin(0) + , hotPathOther(0) + , coldPathOther(0) + , callee(0) + { + } + + unsigned bytecodeIndex; + void* callReturnLocation; + void* hotPathBegin; + void* hotPathOther; + void* coldPathOther; + CodeBlock* callee; + unsigned position; + + void setUnlinked() { callee = 0; } + bool isLinked() { return callee; } + }; + + struct FunctionRegisterInfo { + FunctionRegisterInfo(unsigned bytecodeOffset, int functionRegisterIndex) + : bytecodeOffset(bytecodeOffset) + , functionRegisterIndex(functionRegisterIndex) + { + } + + unsigned bytecodeOffset; + int functionRegisterIndex; + }; + + struct GlobalResolveInfo { + GlobalResolveInfo(unsigned bytecodeOffset) + : structure(0) + , offset(0) + , bytecodeOffset(bytecodeOffset) + { + } + + Structure* structure; + unsigned offset; + unsigned bytecodeOffset; + }; + + struct PC { + PC(ptrdiff_t nativePCOffset, unsigned bytecodeIndex) + : nativePCOffset(nativePCOffset) + , bytecodeIndex(bytecodeIndex) + { + } + + ptrdiff_t nativePCOffset; + unsigned bytecodeIndex; + }; + + // valueAtPosition helpers for the binaryChop algorithm below. + + inline void* getStructureStubInfoReturnLocation(StructureStubInfo* structureStubInfo) + { + return structureStubInfo->callReturnLocation; + } + + inline void* getCallLinkInfoReturnLocation(CallLinkInfo* callLinkInfo) + { + return callLinkInfo->callReturnLocation; + } + + inline ptrdiff_t getNativePCOffset(PC* pc) + { + return pc->nativePCOffset; + } + + // Binary chop algorithm, calls valueAtPosition on pre-sorted elements in array, + // compares result with key (KeyTypes should be comparable with '--', '<', '>'). + // Optimized for cases where the array contains the key, checked by assertions. + template<typename ArrayType, typename KeyType, KeyType(*valueAtPosition)(ArrayType*)> + inline ArrayType* binaryChop(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. + while (size > 1) { + // Pick an element to check, half way through the array, and read the value. + int pos = (size - 1) >> 1; + KeyType val = valueAtPosition(&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); + } + + // '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 == valueAtPosition(&array[0])); + return &array[0]; + } +#endif + + class CodeBlock { + friend class JIT; + public: + CodeBlock(ScopeNode* ownerNode, CodeType, PassRefPtr<SourceProvider>, unsigned sourceOffset); + ~CodeBlock(); + + void mark(); + void refStructures(Instruction* vPC) const; + void derefStructures(Instruction* vPC) const; +#if ENABLE(JIT) + void unlinkCallers(); +#endif + + static void dumpStatistics(); + +#if !defined(NDEBUG) || ENABLE_OPCODE_SAMPLING + void dump(ExecState*) const; + void printStructures(const Instruction*) const; + void printStructure(const char* name, const Instruction*, int operand) const; +#endif + + inline bool isKnownNotImmediate(int index) + { + if (index == m_thisRegister) + return true; + + if (isConstantRegisterIndex(index)) + return getConstant(index).isCell(); + + return false; + } + + ALWAYS_INLINE bool isConstantRegisterIndex(int index) + { + return index >= m_numVars && index < m_numVars + m_numConstants; + } + + ALWAYS_INLINE JSValuePtr getConstant(int index) + { + return m_constantRegisters[index - m_numVars].getJSValue(); + } + + ALWAYS_INLINE bool isTemporaryRegisterIndex(int index) + { + return index >= m_numVars + m_numConstants; + } + + HandlerInfo* handlerForBytecodeOffset(unsigned bytecodeOffset); + int lineNumberForBytecodeOffset(CallFrame*, unsigned bytecodeOffset); + int expressionRangeForBytecodeOffset(CallFrame*, unsigned bytecodeOffset, int& divot, int& startOffset, int& endOffset); + bool getByIdExceptionInfoForBytecodeOffset(CallFrame*, unsigned bytecodeOffset, OpcodeID&); + +#if ENABLE(JIT) + void addCaller(CallLinkInfo* caller) + { + caller->callee = this; + caller->position = m_linkedCallerList.size(); + m_linkedCallerList.append(caller); + } + + void removeCaller(CallLinkInfo* caller) + { + unsigned pos = caller->position; + unsigned lastPos = m_linkedCallerList.size() - 1; + + if (pos != lastPos) { + m_linkedCallerList[pos] = m_linkedCallerList[lastPos]; + m_linkedCallerList[pos]->position = pos; + } + m_linkedCallerList.shrink(lastPos); + } + + StructureStubInfo& getStubInfo(void* returnAddress) + { + return *(binaryChop<StructureStubInfo, void*, getStructureStubInfoReturnLocation>(m_structureStubInfos.begin(), m_structureStubInfos.size(), returnAddress)); + } + + CallLinkInfo& getCallLinkInfo(void* returnAddress) + { + return *(binaryChop<CallLinkInfo, void*, getCallLinkInfoReturnLocation>(m_callLinkInfos.begin(), m_callLinkInfos.size(), returnAddress)); + } + + unsigned getBytecodeIndex(CallFrame* callFrame, void* nativePC) + { + reparseForExceptionInfoIfNecessary(callFrame); + ptrdiff_t nativePCOffset = reinterpret_cast<void**>(nativePC) - reinterpret_cast<void**>(m_jitCode.code); + return binaryChop<PC, ptrdiff_t, getNativePCOffset>(m_exceptionInfo->m_pcVector.begin(), m_exceptionInfo->m_pcVector.size(), nativePCOffset)->bytecodeIndex; + } + + bool functionRegisterForBytecodeOffset(unsigned bytecodeOffset, int& functionRegisterIndex); +#endif + + void setIsNumericCompareFunction(bool isNumericCompareFunction) { m_isNumericCompareFunction = isNumericCompareFunction; } + bool isNumericCompareFunction() { return m_isNumericCompareFunction; } + + Vector<Instruction>& instructions() { return m_instructions; } +#ifndef NDEBUG + void setInstructionCount(unsigned instructionCount) { m_instructionCount = instructionCount; } +#endif + +#if ENABLE(JIT) + void setJITCode(JITCodeRef& jitCode); + void* jitCode() { return m_jitCode.code; } + ExecutablePool* executablePool() { return m_jitCode.executablePool.get(); } +#endif + + ScopeNode* ownerNode() const { return m_ownerNode; } + + void setGlobalData(JSGlobalData* globalData) { m_globalData = globalData; } + + void setThisRegister(int thisRegister) { m_thisRegister = thisRegister; } + int thisRegister() const { return m_thisRegister; } + + void setNeedsFullScopeChain(bool needsFullScopeChain) { m_needsFullScopeChain = needsFullScopeChain; } + bool needsFullScopeChain() const { return m_needsFullScopeChain; } + void setUsesEval(bool usesEval) { m_usesEval = usesEval; } + bool usesEval() const { return m_usesEval; } + void setUsesArguments(bool usesArguments) { m_usesArguments = usesArguments; } + bool usesArguments() const { return m_usesArguments; } + + CodeType codeType() const { return m_codeType; } + + SourceProvider* source() const { return m_source.get(); } + unsigned sourceOffset() const { return m_sourceOffset; } + + size_t numberOfJumpTargets() const { return m_jumpTargets.size(); } + void addJumpTarget(unsigned jumpTarget) { m_jumpTargets.append(jumpTarget); } + unsigned jumpTarget(int index) const { return m_jumpTargets[index]; } + unsigned lastJumpTarget() const { return m_jumpTargets.last(); } + +#if !ENABLE(JIT) + void addPropertyAccessInstruction(unsigned propertyAccessInstruction) { m_propertyAccessInstructions.append(propertyAccessInstruction); } + void addGlobalResolveInstruction(unsigned globalResolveInstruction) { m_globalResolveInstructions.append(globalResolveInstruction); } + bool hasGlobalResolveInstructionAtBytecodeOffset(unsigned bytecodeOffset); +#else + size_t numberOfStructureStubInfos() const { return m_structureStubInfos.size(); } + void addStructureStubInfo(const StructureStubInfo& stubInfo) { m_structureStubInfos.append(stubInfo); } + StructureStubInfo& structureStubInfo(int index) { return m_structureStubInfos[index]; } + + void addGlobalResolveInfo(unsigned globalResolveInstruction) { m_globalResolveInfos.append(GlobalResolveInfo(globalResolveInstruction)); } + GlobalResolveInfo& globalResolveInfo(int index) { return m_globalResolveInfos[index]; } + bool hasGlobalResolveInfoAtBytecodeOffset(unsigned bytecodeOffset); + + size_t numberOfCallLinkInfos() const { return m_callLinkInfos.size(); } + void addCallLinkInfo() { m_callLinkInfos.append(CallLinkInfo()); } + CallLinkInfo& callLinkInfo(int index) { return m_callLinkInfos[index]; } + + void addFunctionRegisterInfo(unsigned bytecodeOffset, int functionIndex) { createRareDataIfNecessary(); m_rareData->m_functionRegisterInfos.append(FunctionRegisterInfo(bytecodeOffset, functionIndex)); } +#endif + + // Exception handling support + + size_t numberOfExceptionHandlers() const { return m_rareData ? m_rareData->m_exceptionHandlers.size() : 0; } + void addExceptionHandler(const HandlerInfo& hanler) { createRareDataIfNecessary(); return m_rareData->m_exceptionHandlers.append(hanler); } + HandlerInfo& exceptionHandler(int index) { ASSERT(m_rareData); return m_rareData->m_exceptionHandlers[index]; } + + bool hasExceptionInfo() const { return m_exceptionInfo; } + void clearExceptionInfo() { m_exceptionInfo.clear(); } + + void addExpressionInfo(const ExpressionRangeInfo& expressionInfo) { ASSERT(m_exceptionInfo); m_exceptionInfo->m_expressionInfo.append(expressionInfo); } + void addGetByIdExceptionInfo(const GetByIdExceptionInfo& info) { ASSERT(m_exceptionInfo); m_exceptionInfo->m_getByIdExceptionInfo.append(info); } + + size_t numberOfLineInfos() const { ASSERT(m_exceptionInfo); return m_exceptionInfo->m_lineInfo.size(); } + void addLineInfo(const LineInfo& lineInfo) { ASSERT(m_exceptionInfo); m_exceptionInfo->m_lineInfo.append(lineInfo); } + LineInfo& lastLineInfo() { ASSERT(m_exceptionInfo); return m_exceptionInfo->m_lineInfo.last(); } + +#if ENABLE(JIT) + Vector<PC>& pcVector() { ASSERT(m_exceptionInfo); return m_exceptionInfo->m_pcVector; } +#endif + + // Constant Pool + + size_t numberOfIdentifiers() const { return m_identifiers.size(); } + void addIdentifier(const Identifier& i) { return m_identifiers.append(i); } + Identifier& identifier(int index) { return m_identifiers[index]; } + + size_t numberOfConstantRegisters() const { return m_constantRegisters.size(); } + void addConstantRegister(const Register& r) { return m_constantRegisters.append(r); } + Register& constantRegister(int index) { return m_constantRegisters[index]; } + + unsigned addFunctionExpression(FuncExprNode* n) { unsigned size = m_functionExpressions.size(); m_functionExpressions.append(n); return size; } + FuncExprNode* functionExpression(int index) const { return m_functionExpressions[index].get(); } + + unsigned addFunction(FuncDeclNode* n) { createRareDataIfNecessary(); unsigned size = m_rareData->m_functions.size(); m_rareData->m_functions.append(n); return size; } + FuncDeclNode* function(int index) const { ASSERT(m_rareData); return m_rareData->m_functions[index].get(); } + + bool hasFunctions() const { return m_functionExpressions.size() || (m_rareData && m_rareData->m_functions.size()); } + + unsigned addUnexpectedConstant(JSValuePtr v) { createRareDataIfNecessary(); unsigned size = m_rareData->m_unexpectedConstants.size(); m_rareData->m_unexpectedConstants.append(v); return size; } + JSValuePtr unexpectedConstant(int index) const { ASSERT(m_rareData); return m_rareData->m_unexpectedConstants[index]; } + + unsigned addRegExp(RegExp* r) { createRareDataIfNecessary(); unsigned size = m_rareData->m_regexps.size(); m_rareData->m_regexps.append(r); return size; } + RegExp* regexp(int index) const { ASSERT(m_rareData); return m_rareData->m_regexps[index].get(); } + + + // Jump Tables + + size_t numberOfImmediateSwitchJumpTables() const { return m_rareData ? m_rareData->m_immediateSwitchJumpTables.size() : 0; } + SimpleJumpTable& addImmediateSwitchJumpTable() { createRareDataIfNecessary(); m_rareData->m_immediateSwitchJumpTables.append(SimpleJumpTable()); return m_rareData->m_immediateSwitchJumpTables.last(); } + SimpleJumpTable& immediateSwitchJumpTable(int tableIndex) { ASSERT(m_rareData); return m_rareData->m_immediateSwitchJumpTables[tableIndex]; } + + size_t numberOfCharacterSwitchJumpTables() const { return m_rareData ? m_rareData->m_characterSwitchJumpTables.size() : 0; } + SimpleJumpTable& addCharacterSwitchJumpTable() { createRareDataIfNecessary(); m_rareData->m_characterSwitchJumpTables.append(SimpleJumpTable()); return m_rareData->m_characterSwitchJumpTables.last(); } + SimpleJumpTable& characterSwitchJumpTable(int tableIndex) { ASSERT(m_rareData); return m_rareData->m_characterSwitchJumpTables[tableIndex]; } + + size_t numberOfStringSwitchJumpTables() const { return m_rareData ? m_rareData->m_stringSwitchJumpTables.size() : 0; } + StringJumpTable& addStringSwitchJumpTable() { createRareDataIfNecessary(); m_rareData->m_stringSwitchJumpTables.append(StringJumpTable()); return m_rareData->m_stringSwitchJumpTables.last(); } + StringJumpTable& stringSwitchJumpTable(int tableIndex) { ASSERT(m_rareData); return m_rareData->m_stringSwitchJumpTables[tableIndex]; } + + + SymbolTable& symbolTable() { return m_symbolTable; } + + EvalCodeCache& evalCodeCache() { createRareDataIfNecessary(); return m_rareData->m_evalCodeCache; } + + void shrinkToFit(); + + // FIXME: Make these remaining members private. + + int m_numCalleeRegisters; + // NOTE: numConstants holds the number of constant registers allocated + // by the code generator, not the number of constant registers used. + // (Duplicate constants are uniqued during code generation, and spare + // constant registers may be allocated.) + int m_numConstants; + int m_numVars; + int m_numParameters; + + private: +#if !defined(NDEBUG) || ENABLE(OPCODE_SAMPLING) + void dump(ExecState*, const Vector<Instruction>::const_iterator& begin, Vector<Instruction>::const_iterator&) const; +#endif + + void reparseForExceptionInfoIfNecessary(CallFrame*); + + void createRareDataIfNecessary() + { + if (!m_rareData) + m_rareData.set(new RareData); + } + + ScopeNode* m_ownerNode; + JSGlobalData* m_globalData; + + Vector<Instruction> m_instructions; +#ifndef NDEBUG + unsigned m_instructionCount; +#endif +#if ENABLE(JIT) + JITCodeRef m_jitCode; +#endif + + int m_thisRegister; + + bool m_needsFullScopeChain; + bool m_usesEval; + bool m_usesArguments; + bool m_isNumericCompareFunction; + + CodeType m_codeType; + + RefPtr<SourceProvider> m_source; + unsigned m_sourceOffset; + +#if !ENABLE(JIT) + Vector<unsigned> m_propertyAccessInstructions; + Vector<unsigned> m_globalResolveInstructions; +#else + Vector<StructureStubInfo> m_structureStubInfos; + Vector<GlobalResolveInfo> m_globalResolveInfos; + Vector<CallLinkInfo> m_callLinkInfos; + Vector<CallLinkInfo*> m_linkedCallerList; +#endif + + Vector<unsigned> m_jumpTargets; + + // Constant Pool + Vector<Identifier> m_identifiers; + Vector<Register> m_constantRegisters; + Vector<RefPtr<FuncExprNode> > m_functionExpressions; + + SymbolTable m_symbolTable; + + struct ExceptionInfo { + Vector<ExpressionRangeInfo> m_expressionInfo; + Vector<LineInfo> m_lineInfo; + Vector<GetByIdExceptionInfo> m_getByIdExceptionInfo; + +#if ENABLE(JIT) + Vector<PC> m_pcVector; +#endif + }; + OwnPtr<ExceptionInfo> m_exceptionInfo; + + struct RareData { + Vector<HandlerInfo> m_exceptionHandlers; + + // Rare Constants + Vector<RefPtr<FuncDeclNode> > m_functions; + Vector<JSValuePtr> m_unexpectedConstants; + Vector<RefPtr<RegExp> > m_regexps; + + // Jump Tables + Vector<SimpleJumpTable> m_immediateSwitchJumpTables; + Vector<SimpleJumpTable> m_characterSwitchJumpTables; + Vector<StringJumpTable> m_stringSwitchJumpTables; + + EvalCodeCache m_evalCodeCache; + +#if ENABLE(JIT) + Vector<FunctionRegisterInfo> m_functionRegisterInfos; +#endif + }; + OwnPtr<RareData> m_rareData; + }; + + // Program code is not marked by any function, so we make the global object + // responsible for marking it. + + class ProgramCodeBlock : public CodeBlock { + public: + ProgramCodeBlock(ScopeNode* ownerNode, CodeType codeType, JSGlobalObject* globalObject, PassRefPtr<SourceProvider> sourceProvider) + : CodeBlock(ownerNode, codeType, sourceProvider, 0) + , m_globalObject(globalObject) + { + m_globalObject->codeBlocks().add(this); + } + + ~ProgramCodeBlock() + { + if (m_globalObject) + m_globalObject->codeBlocks().remove(this); + } + + void clearGlobalObject() { m_globalObject = 0; } + + private: + JSGlobalObject* m_globalObject; // For program and eval nodes, the global object that marks the constant pool. + }; + + class EvalCodeBlock : public ProgramCodeBlock { + public: + EvalCodeBlock(ScopeNode* ownerNode, JSGlobalObject* globalObject, PassRefPtr<SourceProvider> sourceProvider, int baseScopeDepth) + : ProgramCodeBlock(ownerNode, EvalCode, globalObject, sourceProvider) + , m_baseScopeDepth(baseScopeDepth) + { + } + + int baseScopeDepth() const { return m_baseScopeDepth; } + + private: + int m_baseScopeDepth; + }; + +} // namespace JSC + +#endif // CodeBlock_h diff --git a/JavaScriptCore/bytecode/EvalCodeCache.h b/JavaScriptCore/bytecode/EvalCodeCache.h new file mode 100644 index 0000000..2d6f7dc --- /dev/null +++ b/JavaScriptCore/bytecode/EvalCodeCache.h @@ -0,0 +1,87 @@ +/* + * 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. + * 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 EvalCodeCache_h +#define EvalCodeCache_h + +#include "JSGlobalObject.h" +#include "Nodes.h" +#include "Parser.h" +#include "SourceCode.h" +#include "UString.h" +#include <wtf/HashMap.h> +#include <wtf/RefPtr.h> + +namespace JSC { + + class EvalCodeCache { + public: + PassRefPtr<EvalNode> get(ExecState* exec, const UString& evalSource, ScopeChainNode* scopeChain, JSValuePtr& exceptionValue) + { + RefPtr<EvalNode> evalNode; + + if (evalSource.size() < maxCacheableSourceLength && (*scopeChain->begin())->isVariableObject()) + evalNode = m_cacheMap.get(evalSource.rep()); + + if (!evalNode) { + int errorLine; + UString errorMessage; + + SourceCode source = makeSource(evalSource); + evalNode = exec->globalData().parser->parse<EvalNode>(exec, exec->dynamicGlobalObject()->debugger(), source, &errorLine, &errorMessage); + if (evalNode) { + if (evalSource.size() < maxCacheableSourceLength && (*scopeChain->begin())->isVariableObject() && m_cacheMap.size() < maxCacheEntries) + m_cacheMap.set(evalSource.rep(), evalNode); + } else { + exceptionValue = Error::create(exec, SyntaxError, errorMessage, errorLine, source.provider()->asID(), 0); + return 0; + } + } + + return evalNode.release(); + } + + bool isEmpty() const { return m_cacheMap.isEmpty(); } + + void mark() + { + EvalCacheMap::iterator end = m_cacheMap.end(); + for (EvalCacheMap::iterator ptr = m_cacheMap.begin(); ptr != end; ++ptr) + ptr->second->mark(); + } + private: + static const int maxCacheableSourceLength = 256; + static const int maxCacheEntries = 64; + + typedef HashMap<RefPtr<UString::Rep>, RefPtr<EvalNode> > EvalCacheMap; + EvalCacheMap m_cacheMap; + }; + +} // namespace JSC + +#endif // EvalCodeCache_h diff --git a/JavaScriptCore/bytecode/Instruction.h b/JavaScriptCore/bytecode/Instruction.h new file mode 100644 index 0000000..1fab106 --- /dev/null +++ b/JavaScriptCore/bytecode/Instruction.h @@ -0,0 +1,155 @@ +/* + * 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 Instruction_h +#define Instruction_h + +#include "Opcode.h" +#include "Structure.h" +#include <wtf/VectorTraits.h> + +#define POLYMORPHIC_LIST_CACHE_SIZE 4 + +namespace JSC { + + class JSCell; + class Structure; + class StructureChain; + + // Structure used by op_get_by_id_self_list and op_get_by_id_proto_list instruction to hold data off the main opcode stream. + struct PolymorphicAccessStructureList { + struct PolymorphicStubInfo { + bool isChain; + void* stubRoutine; + Structure* base; + union { + Structure* proto; + StructureChain* chain; + } u; + + void set(void* _stubRoutine, Structure* _base) + { + stubRoutine = _stubRoutine; + base = _base; + u.proto = 0; + isChain = false; + } + + void set(void* _stubRoutine, Structure* _base, Structure* _proto) + { + stubRoutine = _stubRoutine; + base = _base; + u.proto = _proto; + isChain = false; + } + + void set(void* _stubRoutine, Structure* _base, StructureChain* _chain) + { + stubRoutine = _stubRoutine; + base = _base; + u.chain = _chain; + isChain = true; + } + } list[POLYMORPHIC_LIST_CACHE_SIZE]; + + PolymorphicAccessStructureList(void* stubRoutine, Structure* firstBase) + { + list[0].set(stubRoutine, firstBase); + } + + PolymorphicAccessStructureList(void* stubRoutine, Structure* firstBase, Structure* firstProto) + { + list[0].set(stubRoutine, firstBase, firstProto); + } + + PolymorphicAccessStructureList(void* stubRoutine, Structure* firstBase, StructureChain* firstChain) + { + list[0].set(stubRoutine, firstBase, firstChain); + } + + void derefStructures(int count) + { + for (int i = 0; i < count; ++i) { + PolymorphicStubInfo& info = list[i]; + + ASSERT(info.base); + info.base->deref(); + + if (info.u.proto) { + if (info.isChain) + info.u.chain->deref(); + else + info.u.proto->deref(); + } + } + } + }; + + struct Instruction { + Instruction(Opcode opcode) + { +#if !HAVE(COMPUTED_GOTO) + // We have to initialize one of the pointer members to ensure that + // the entire struct is initialized, when opcode is not a pointer. + u.jsCell = 0; +#endif + u.opcode = opcode; + } + + Instruction(int operand) + { + // We have to initialize one of the pointer members to ensure that + // the entire struct is initialized in 64-bit. + u.jsCell = 0; + u.operand = operand; + } + + Instruction(Structure* structure) { u.structure = structure; } + Instruction(StructureChain* structureChain) { u.structureChain = structureChain; } + Instruction(JSCell* jsCell) { u.jsCell = jsCell; } + Instruction(PolymorphicAccessStructureList* polymorphicStructures) { u.polymorphicStructures = polymorphicStructures; } + + union { + Opcode opcode; + int operand; + Structure* structure; + StructureChain* structureChain; + JSCell* jsCell; + PolymorphicAccessStructureList* polymorphicStructures; + } u; + }; + +} // namespace JSC + +namespace WTF { + + template<> struct VectorTraits<JSC::Instruction> : VectorTraitsBase<true, JSC::Instruction> { }; + +} // namespace WTF + +#endif // Instruction_h diff --git a/JavaScriptCore/VM/Instruction.h b/JavaScriptCore/bytecode/JumpTable.cpp index 6e32c06..175c1b3 100644 --- a/JavaScriptCore/VM/Instruction.h +++ b/JavaScriptCore/bytecode/JumpTable.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2008 Apple Inc. All rights reserved. + * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,49 +27,19 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef Instruction_h -#define Instruction_h - -#include "Opcode.h" -#include "ResultType.h" -#include <wtf/VectorTraits.h> +#include "config.h" +#include "JumpTable.h" namespace JSC { - class JSCell; - class StructureID; - class StructureIDChain; - - struct Instruction { - Instruction(Opcode opcode) { u.opcode = opcode; } - Instruction(int operand) - { - // We have to initialize one of the pointer members to ensure that - // the entire struct is initialised in 64-bit. - u.jsCell = 0; - u.operand = operand; - } - - Instruction(StructureID* structureID) { u.structureID = structureID; } - Instruction(StructureIDChain* structureIDChain) { u.structureIDChain = structureIDChain; } - Instruction(JSCell* jsCell) { u.jsCell = jsCell; } - - union { - Opcode opcode; - int operand; - StructureID* structureID; - StructureIDChain* structureIDChain; - JSCell* jsCell; - ResultType::Type resultType; - } u; - }; +int32_t SimpleJumpTable::offsetForValue(int32_t value, int32_t defaultOffset) +{ + if (value >= min && static_cast<uint32_t>(value - min) < branchOffsets.size()) { + int32_t offset = branchOffsets[value - min]; + if (offset) + return offset; + } + return defaultOffset; +} } // namespace JSC - -namespace WTF { - - template<> struct VectorTraits<JSC::Instruction> : VectorTraitsBase<true, JSC::Instruction> { }; - -} // namespace WTF - -#endif // Instruction_h diff --git a/JavaScriptCore/bytecode/JumpTable.h b/JavaScriptCore/bytecode/JumpTable.h new file mode 100644 index 0000000..44e224d --- /dev/null +++ b/JavaScriptCore/bytecode/JumpTable.h @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2008 Apple Inc. All rights reserved. + * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca> + * + * 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 JumpTable_h +#define JumpTable_h + +#include "UString.h" +#include <wtf/HashMap.h> +#include <wtf/Vector.h> + +namespace JSC { + + struct OffsetLocation { + int32_t branchOffset; +#if ENABLE(JIT) + void* ctiOffset; +#endif + }; + + struct StringJumpTable { + typedef HashMap<RefPtr<UString::Rep>, OffsetLocation> StringOffsetTable; + StringOffsetTable offsetTable; +#if ENABLE(JIT) + void* ctiDefault; // FIXME: it should not be necessary to store this. +#endif + + inline int32_t offsetForValue(UString::Rep* value, int32_t defaultOffset) + { + StringOffsetTable::const_iterator end = offsetTable.end(); + StringOffsetTable::const_iterator loc = offsetTable.find(value); + if (loc == end) + return defaultOffset; + return loc->second.branchOffset; + } + +#if ENABLE(JIT) + inline void* ctiForValue(UString::Rep* value) + { + StringOffsetTable::const_iterator end = offsetTable.end(); + StringOffsetTable::const_iterator loc = offsetTable.find(value); + if (loc == end) + return ctiDefault; + return loc->second.ctiOffset; + } +#endif + }; + + struct SimpleJumpTable { + // FIXME: The two Vectors can be combind into one Vector<OffsetLocation> + Vector<int32_t> branchOffsets; + int32_t min; +#if ENABLE(JIT) + Vector<void*> ctiOffsets; + void* ctiDefault; +#endif + + int32_t offsetForValue(int32_t value, int32_t defaultOffset); + void add(int32_t key, int32_t offset) + { + if (!branchOffsets[key]) + branchOffsets[key] = offset; + } + +#if ENABLE(JIT) + inline void* ctiForValue(int32_t value) + { + if (value >= min && static_cast<uint32_t>(value - min) < ctiOffsets.size()) + return ctiOffsets[value - min]; + return ctiDefault; + } +#endif + }; + +} // namespace JSC + +#endif // JumpTable_h diff --git a/JavaScriptCore/VM/Opcode.cpp b/JavaScriptCore/bytecode/Opcode.cpp index cc70418..bb7696d 100644 --- a/JavaScriptCore/VM/Opcode.cpp +++ b/JavaScriptCore/bytecode/Opcode.cpp @@ -37,7 +37,7 @@ namespace JSC { #if ENABLE(OPCODE_SAMPLING) || ENABLE(CODEBLOCK_SAMPLING) || ENABLE(OPCODE_STATS) const char* const opcodeNames[] = { -#define OPCODE_NAME_ENTRY(opcode) #opcode, +#define OPCODE_NAME_ENTRY(opcode, size) #opcode, FOR_EACH_OPCODE_ID(OPCODE_NAME_ENTRY) #undef OPCODE_NAME_ENTRY }; diff --git a/JavaScriptCore/bytecode/Opcode.h b/JavaScriptCore/bytecode/Opcode.h new file mode 100644 index 0000000..d00178b --- /dev/null +++ b/JavaScriptCore/bytecode/Opcode.h @@ -0,0 +1,231 @@ +/* + * Copyright (C) 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca> + * + * 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 Opcode_h +#define Opcode_h + +#include <algorithm> +#include <string.h> + +#include <wtf/Assertions.h> + +namespace JSC { + + #define FOR_EACH_OPCODE_ID(macro) \ + macro(op_enter, 1) \ + macro(op_enter_with_activation, 2) \ + macro(op_create_arguments, 1) \ + macro(op_convert_this, 2) \ + \ + macro(op_unexpected_load, 3) \ + macro(op_new_object, 2) \ + macro(op_new_array, 4) \ + macro(op_new_regexp, 3) \ + macro(op_mov, 3) \ + \ + macro(op_not, 3) \ + macro(op_eq, 4) \ + macro(op_eq_null, 3) \ + macro(op_neq, 4) \ + macro(op_neq_null, 3) \ + macro(op_stricteq, 4) \ + macro(op_nstricteq, 4) \ + macro(op_less, 4) \ + macro(op_lesseq, 4) \ + \ + macro(op_pre_inc, 2) \ + macro(op_pre_dec, 2) \ + macro(op_post_inc, 3) \ + macro(op_post_dec, 3) \ + macro(op_to_jsnumber, 3) \ + macro(op_negate, 3) \ + macro(op_add, 5) \ + macro(op_mul, 5) \ + macro(op_div, 4) \ + macro(op_mod, 4) \ + macro(op_sub, 5) \ + \ + macro(op_lshift, 4) \ + macro(op_rshift, 4) \ + macro(op_urshift, 4) \ + macro(op_bitand, 5) \ + macro(op_bitxor, 5) \ + macro(op_bitor, 5) \ + macro(op_bitnot, 3) \ + \ + macro(op_instanceof, 5) \ + macro(op_typeof, 3) \ + macro(op_is_undefined, 3) \ + macro(op_is_boolean, 3) \ + macro(op_is_number, 3) \ + macro(op_is_string, 3) \ + macro(op_is_object, 3) \ + macro(op_is_function, 3) \ + macro(op_in, 4) \ + \ + macro(op_resolve, 3) \ + macro(op_resolve_skip, 4) \ + macro(op_resolve_global, 6) \ + macro(op_get_scoped_var, 4) \ + macro(op_put_scoped_var, 4) \ + macro(op_get_global_var, 4) \ + macro(op_put_global_var, 4) \ + macro(op_resolve_base, 3) \ + macro(op_resolve_with_base, 4) \ + macro(op_resolve_func, 4) \ + macro(op_get_by_id, 8) \ + macro(op_get_by_id_self, 8) \ + macro(op_get_by_id_self_list, 8) \ + macro(op_get_by_id_proto, 8) \ + macro(op_get_by_id_proto_list, 8) \ + macro(op_get_by_id_chain, 8) \ + macro(op_get_by_id_generic, 8) \ + macro(op_get_array_length, 8) \ + macro(op_get_string_length, 8) \ + macro(op_put_by_id, 8) \ + macro(op_put_by_id_transition, 8) \ + macro(op_put_by_id_replace, 8) \ + macro(op_put_by_id_generic, 8) \ + macro(op_del_by_id, 4) \ + macro(op_get_by_val, 4) \ + macro(op_put_by_val, 4) \ + macro(op_del_by_val, 4) \ + macro(op_put_by_index, 4) \ + macro(op_put_getter, 4) \ + macro(op_put_setter, 4) \ + \ + macro(op_jmp, 2) \ + macro(op_jtrue, 3) \ + macro(op_jfalse, 3) \ + macro(op_jeq_null, 3) \ + macro(op_jneq_null, 3) \ + macro(op_jnless, 4) \ + macro(op_jmp_scopes, 3) \ + macro(op_loop, 2) \ + macro(op_loop_if_true, 3) \ + macro(op_loop_if_less, 4) \ + macro(op_loop_if_lesseq, 4) \ + macro(op_switch_imm, 4) \ + macro(op_switch_char, 4) \ + macro(op_switch_string, 4) \ + \ + macro(op_new_func, 3) \ + macro(op_new_func_exp, 3) \ + macro(op_call, 5) \ + macro(op_call_eval, 5) \ + macro(op_tear_off_activation, 2) \ + macro(op_tear_off_arguments, 1) \ + macro(op_ret, 2) \ + \ + macro(op_construct, 7) \ + macro(op_construct_verify, 3) \ + \ + macro(op_get_pnames, 3) \ + macro(op_next_pname, 4) \ + \ + macro(op_push_scope, 2) \ + macro(op_pop_scope, 1) \ + macro(op_push_new_scope, 4) \ + \ + macro(op_catch, 2) \ + macro(op_throw, 2) \ + macro(op_new_error, 4) \ + \ + macro(op_jsr, 3) \ + macro(op_sret, 2) \ + \ + macro(op_debug, 4) \ + macro(op_profile_will_call, 2) \ + macro(op_profile_did_call, 2) \ + \ + macro(op_end, 2) // end must be the last opcode in the list + + #define OPCODE_ID_ENUM(opcode, length) opcode, + typedef enum { FOR_EACH_OPCODE_ID(OPCODE_ID_ENUM) } OpcodeID; + #undef OPCODE_ID_ENUM + + const int numOpcodeIDs = op_end + 1; + + #define OPCODE_ID_LENGTHS(id, length) const int id##_length = length; + FOR_EACH_OPCODE_ID(OPCODE_ID_LENGTHS); + #undef OPCODE_ID_SIZES + + #define OPCODE_LENGTH(opcode) opcode##_length + + #define OPCODE_ID_LENGTH_MAP(opcode, length) length, + const int opcodeLengths[numOpcodeIDs] = { FOR_EACH_OPCODE_ID(OPCODE_ID_LENGTH_MAP) }; + #undef OPCODE_ID_LENGTH_MAP + + #define VERIFY_OPCODE_ID(id, size) COMPILE_ASSERT(id <= op_end, ASSERT_THAT_JS_OPCODE_IDS_ARE_VALID); + FOR_EACH_OPCODE_ID(VERIFY_OPCODE_ID); + #undef VERIFY_OPCODE_ID + +#if HAVE(COMPUTED_GOTO) + typedef void* Opcode; +#else + typedef OpcodeID Opcode; +#endif + +#if ENABLE(OPCODE_SAMPLING) || ENABLE(CODEBLOCK_SAMPLING) || ENABLE(OPCODE_STATS) + +#define PADDING_STRING " " +#define PADDING_STRING_LENGTH static_cast<unsigned>(strlen(PADDING_STRING)) + + extern const char* const opcodeNames[]; + + inline const char* padOpcodeName(OpcodeID op, unsigned width) + { + unsigned pad = width - strlen(opcodeNames[op]); + pad = std::min(pad, PADDING_STRING_LENGTH); + return PADDING_STRING + PADDING_STRING_LENGTH - pad; + } + +#undef PADDING_STRING_LENGTH +#undef PADDING_STRING + +#endif + +#if ENABLE(OPCODE_STATS) + + struct OpcodeStats { + OpcodeStats(); + ~OpcodeStats(); + static long long opcodeCounts[numOpcodeIDs]; + static long long opcodePairCounts[numOpcodeIDs][numOpcodeIDs]; + static int lastOpcode; + + static void recordInstruction(int opcode); + static void resetLastInstruction(); + }; + +#endif + +} // namespace JSC + +#endif // Opcode_h diff --git a/JavaScriptCore/VM/SamplingTool.cpp b/JavaScriptCore/bytecode/SamplingTool.cpp index 3de3ff5..215ebe5 100644 --- a/JavaScriptCore/VM/SamplingTool.cpp +++ b/JavaScriptCore/bytecode/SamplingTool.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Apple Inc. All rights reserved. + * 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 @@ -30,7 +30,7 @@ #include "SamplingTool.h" #include "CodeBlock.h" -#include "Machine.h" +#include "Interpreter.h" #include "Opcode.h" #if !PLATFORM(WIN_OS) @@ -42,14 +42,14 @@ namespace JSC { void ScopeSampleRecord::sample(CodeBlock* codeBlock, Instruction* vPC) { if (!m_samples) { - m_size = codeBlock->instructions.size(); + m_size = codeBlock->instructions().size(); m_samples = static_cast<int*>(calloc(m_size, sizeof(int))); m_codeBlock = codeBlock; } ++m_sampleCount; - unsigned offest = vPC - codeBlock->instructions.begin(); + unsigned offest = vPC - codeBlock->instructions().begin(); // Since we don't read and write codeBlock and vPC atomically, this check // can fail if we sample mid op_call / op_ret. if (offest < m_size) { @@ -94,7 +94,7 @@ void SamplingTool::run() continue; if (!sample.inHostFunction()) { - unsigned opcodeID = m_machine->getOpcodeID(sample.vPC()[0].u.opcode); + unsigned opcodeID = m_interpreter->getOpcodeID(sample.vPC()[0].u.opcode); ++m_opcodeSampleCount; ++m_opcodeSamples[opcodeID]; @@ -105,7 +105,7 @@ void SamplingTool::run() #if ENABLE(CODEBLOCK_SAMPLING) MutexLocker locker(m_scopeSampleMapMutex); - ScopeSampleRecord* record = m_scopeSampleMap->get(sample.codeBlock()->ownerNode); + ScopeSampleRecord* record = m_scopeSampleMap->get(sample.codeBlock()->ownerNode()); ASSERT(record); record->sample(sample.codeBlock(), sample.vPC()); #endif @@ -196,7 +196,7 @@ void SamplingTool::dump(ExecState* exec) // (2) Print Opcode sampling results. - printf("\nOpcode samples [*]\n"); + printf("\nBytecode samples [*]\n"); printf(" sample %% of %% of | cti cti %%\n"); printf("opcode count VM total | count of self\n"); printf("------------------------------------------------------- | ----------------\n"); @@ -206,10 +206,10 @@ void SamplingTool::dump(ExecState* exec) if (!count) continue; - OpcodeID opcode = opcodeSampleInfo[i].opcode; + OpcodeID opcodeID = opcodeSampleInfo[i].opcode; - const char* opcodeName = opcodeNames[opcode]; - const char* opcodePadding = padOpcodeName(opcode, 28); + const char* opcodeName = opcodeNames[opcodeID]; + const char* opcodePadding = padOpcodeName(opcodeID, 28); double percentOfVM = (static_cast<double>(count) * 100) / m_opcodeSampleCount; double percentOfTotal = (static_cast<double>(count) * 100) / m_sampleCount; long long countInCTIFunctions = opcodeSampleInfo[i].countInCTIFunctions; @@ -217,7 +217,7 @@ void SamplingTool::dump(ExecState* exec) fprintf(stdout, "%s:%s%-6lld %.3f%%\t%.3f%%\t | %-6lld %.3f%%\n", opcodeName, opcodePadding, count, percentOfVM, percentOfTotal, countInCTIFunctions, percentInCTIFunctions); } - printf("\n[*] Samples inside host code are not charged to any Opcode.\n\n"); + printf("\n[*] Samples inside host code are not charged to any Bytecode.\n\n"); printf("\tSamples inside VM:\t\t%lld / %lld (%.3f%%)\n", m_opcodeSampleCount, m_sampleCount, (static_cast<double>(m_opcodeSampleCount) * 100) / m_sampleCount); printf("\tSamples inside host code:\t%lld / %lld (%.3f%%)\n\n", m_sampleCount - m_opcodeSampleCount, m_sampleCount, (static_cast<double>(m_sampleCount - m_opcodeSampleCount) * 100) / m_sampleCount); printf("\tsample count:\tsamples inside this opcode\n"); @@ -248,8 +248,8 @@ void SamplingTool::dump(ExecState* exec) double blockPercent = (record->m_sampleCount * 100.0) / m_sampleCount; if (blockPercent >= 1) { - Instruction* code = codeBlock->instructions.begin(); - printf("#%d: %s:%d: %d / %lld (%.3f%%)\n", i + 1, record->m_scope->sourceURL().UTF8String().c_str(), codeBlock->lineNumberForVPC(code), record->m_sampleCount, m_sampleCount, blockPercent); + //Instruction* code = codeBlock->instructions().begin(); + printf("#%d: %s:%d: %d / %lld (%.3f%%)\n", i + 1, record->m_scope->sourceURL().UTF8String().c_str(), codeBlock->lineNumberForBytecodeOffset(exec, 0), record->m_sampleCount, m_sampleCount, blockPercent); if (i < 10) { HashMap<unsigned,unsigned> lineCounts; codeBlock->dump(exec); @@ -259,7 +259,7 @@ void SamplingTool::dump(ExecState* exec) int count = record->m_samples[op]; if (count) { printf(" [% 4d] has sample count: % 4d\n", op, count); - unsigned line = codeBlock->lineNumberForVPC(code+op); + unsigned line = codeBlock->lineNumberForBytecodeOffset(exec, op); lineCounts.set(line, (lineCounts.contains(line) ? lineCounts.get(line) : 0) + count); } } @@ -279,7 +279,7 @@ void SamplingTool::dump(ExecState* exec) printf(" Line #%d has sample count %d.\n", lineCountInfo[lineno].line, lineCountInfo[lineno].count); } printf("\n"); - printf(" [*] Samples inside host code are charged to the calling Opcode.\n"); + printf(" [*] Samples inside host code are charged to the calling Bytecode.\n"); printf(" Samples on a call / return boundary are not charged to a specific opcode or line.\n\n"); printf(" Samples on a call / return boundary: %d / %d (%.3f%%)\n\n", record->m_sampleCount - record->m_opcodeSampleCount, record->m_sampleCount, (static_cast<double>(record->m_sampleCount - record->m_opcodeSampleCount) * 100) / record->m_sampleCount); } diff --git a/JavaScriptCore/VM/SamplingTool.h b/JavaScriptCore/bytecode/SamplingTool.h index 059f0d5..d1cf2e88 100644 --- a/JavaScriptCore/VM/SamplingTool.h +++ b/JavaScriptCore/bytecode/SamplingTool.h @@ -33,14 +33,14 @@ #include <wtf/HashMap.h> #include <wtf/Threading.h> -#include "nodes.h" +#include "Nodes.h" #include "Opcode.h" namespace JSC { class CodeBlock; class ExecState; - class Machine; + class Interpreter; class ScopeNode; struct Instruction; @@ -125,8 +125,8 @@ namespace JSC { }; #endif - SamplingTool(Machine* machine) - : m_machine(machine) + SamplingTool(Interpreter* interpreter) + : m_interpreter(interpreter) , m_running(false) , m_codeBlock(0) , m_sample(0) @@ -159,10 +159,10 @@ namespace JSC { CodeBlock** codeBlockSlot() { return &m_codeBlock; } intptr_t* sampleSlot() { return &m_sample; } - unsigned encodeSample(Instruction* vPC, bool inCTIFunction = false, bool inHostFunction = false) + void* encodeSample(Instruction* vPC, bool inCTIFunction = false, bool inHostFunction = false) { ASSERT(!(reinterpret_cast<intptr_t>(vPC) & 0x3)); - return reinterpret_cast<intptr_t>(vPC) | (static_cast<intptr_t>(inCTIFunction) << 1) | static_cast<intptr_t>(inHostFunction); + return reinterpret_cast<void*>(reinterpret_cast<intptr_t>(vPC) | (static_cast<intptr_t>(inCTIFunction) << 1) | static_cast<intptr_t>(inHostFunction)); } private: @@ -188,7 +188,7 @@ namespace JSC { static void* threadStartFunc(void*); void run(); - Machine* m_machine; + Interpreter* m_interpreter; // Sampling thread state. bool m_running; diff --git a/JavaScriptCore/bytecode/StructureStubInfo.cpp b/JavaScriptCore/bytecode/StructureStubInfo.cpp new file mode 100644 index 0000000..bf3fdc4 --- /dev/null +++ b/JavaScriptCore/bytecode/StructureStubInfo.cpp @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2008 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "StructureStubInfo.h" + +namespace JSC { + +#if ENABLE(JIT) +void StructureStubInfo::deref() +{ + switch (opcodeID) { + case op_get_by_id_self: + u.getByIdSelf.baseObjectStructure->deref(); + return; + case op_get_by_id_proto: + u.getByIdProto.baseObjectStructure->deref(); + u.getByIdProto.prototypeStructure->deref(); + return; + case op_get_by_id_chain: + u.getByIdChain.baseObjectStructure->deref(); + u.getByIdChain.chain->deref(); + return; + case op_get_by_id_self_list: { + PolymorphicAccessStructureList* polymorphicStructures = u.getByIdSelfList.structureList; + polymorphicStructures->derefStructures(u.getByIdSelfList.listSize); + delete polymorphicStructures; + return; + } + case op_get_by_id_proto_list: { + PolymorphicAccessStructureList* polymorphicStructures = u.getByIdProtoList.structureList; + polymorphicStructures->derefStructures(u.getByIdProtoList.listSize); + delete polymorphicStructures; + return; + } + case op_put_by_id_transition: + u.putByIdTransition.previousStructure->deref(); + u.putByIdTransition.structure->deref(); + u.putByIdTransition.chain->deref(); + return; + case op_put_by_id_replace: + u.putByIdReplace.baseObjectStructure->deref(); + return; + case op_get_by_id: + case op_put_by_id: + case op_get_by_id_generic: + case op_put_by_id_generic: + case op_get_array_length: + case op_get_string_length: + // These instructions don't ref their Structures. + return; + default: + ASSERT_NOT_REACHED(); + } +} +#endif + +} // namespace JSC diff --git a/JavaScriptCore/bytecode/StructureStubInfo.h b/JavaScriptCore/bytecode/StructureStubInfo.h new file mode 100644 index 0000000..a9e0678 --- /dev/null +++ b/JavaScriptCore/bytecode/StructureStubInfo.h @@ -0,0 +1,156 @@ +/* + * 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 StructureStubInfo_h +#define StructureStubInfo_h + +#include "Instruction.h" +#include "Opcode.h" +#include "Structure.h" + +namespace JSC { + +#if ENABLE(JIT) + struct StructureStubInfo { + StructureStubInfo(OpcodeID opcodeID) + : opcodeID(opcodeID) + , stubRoutine(0) + , callReturnLocation(0) + , hotPathBegin(0) + { + } + + void initGetByIdSelf(Structure* baseObjectStructure) + { + opcodeID = op_get_by_id_self; + + u.getByIdSelf.baseObjectStructure = baseObjectStructure; + baseObjectStructure->ref(); + } + + void initGetByIdProto(Structure* baseObjectStructure, Structure* prototypeStructure) + { + opcodeID = op_get_by_id_proto; + + u.getByIdProto.baseObjectStructure = baseObjectStructure; + baseObjectStructure->ref(); + + u.getByIdProto.prototypeStructure = prototypeStructure; + prototypeStructure->ref(); + } + + void initGetByIdChain(Structure* baseObjectStructure, StructureChain* chain) + { + opcodeID = op_get_by_id_chain; + + u.getByIdChain.baseObjectStructure = baseObjectStructure; + baseObjectStructure->ref(); + + u.getByIdChain.chain = chain; + chain->ref(); + } + + void initGetByIdSelfList(PolymorphicAccessStructureList* structureList, int listSize) + { + opcodeID = op_get_by_id_self_list; + + u.getByIdProtoList.structureList = structureList; + u.getByIdProtoList.listSize = listSize; + } + + void initGetByIdProtoList(PolymorphicAccessStructureList* structureList, int listSize) + { + opcodeID = op_get_by_id_proto_list; + + u.getByIdProtoList.structureList = structureList; + u.getByIdProtoList.listSize = listSize; + } + + // PutById* + + void initPutByIdTransition(Structure* previousStructure, Structure* structure, StructureChain* chain) + { + opcodeID = op_put_by_id_transition; + + u.putByIdTransition.previousStructure = previousStructure; + previousStructure->ref(); + + u.putByIdTransition.structure = structure; + structure->ref(); + + u.putByIdTransition.chain = chain; + chain->ref(); + } + + void initPutByIdReplace(Structure* baseObjectStructure) + { + opcodeID = op_put_by_id_replace; + + u.putByIdReplace.baseObjectStructure = baseObjectStructure; + baseObjectStructure->ref(); + } + + void deref(); + + OpcodeID opcodeID; + union { + struct { + Structure* baseObjectStructure; + } getByIdSelf; + struct { + Structure* baseObjectStructure; + Structure* prototypeStructure; + } getByIdProto; + struct { + Structure* baseObjectStructure; + StructureChain* chain; + } getByIdChain; + struct { + PolymorphicAccessStructureList* structureList; + int listSize; + } getByIdSelfList; + struct { + PolymorphicAccessStructureList* structureList; + int listSize; + } getByIdProtoList; + struct { + Structure* previousStructure; + Structure* structure; + StructureChain* chain; + } putByIdTransition; + struct { + Structure* baseObjectStructure; + } putByIdReplace; + } u; + + void* stubRoutine; + void* callReturnLocation; + void* hotPathBegin; + }; +#endif + +} // namespace JSC + +#endif // StructureStubInfo_h diff --git a/JavaScriptCore/VM/CodeGenerator.cpp b/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp index 3bfea93..cd89c1e 100644 --- a/JavaScriptCore/VM/CodeGenerator.cpp +++ b/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Apple Inc. All rights reserved. + * Copyright (C) 2008, 2009 Apple Inc. All rights reserved. * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca> * * Redistribution and use in source and binary forms, with or without @@ -28,12 +28,12 @@ */ #include "config.h" -#include "CodeGenerator.h" +#include "BytecodeGenerator.h" #include "BatchedTransitionOptimizer.h" #include "JSFunction.h" -#include "Machine.h" -#include "ustring.h" +#include "Interpreter.h" +#include "UString.h" using namespace std; @@ -115,10 +115,10 @@ namespace JSC { */ #ifndef NDEBUG -bool CodeGenerator::s_dumpsGeneratedCode = false; +static bool s_dumpsGeneratedCode = false; #endif -void CodeGenerator::setDumpsGeneratedCode(bool dumpsGeneratedCode) +void BytecodeGenerator::setDumpsGeneratedCode(bool dumpsGeneratedCode) { #ifndef NDEBUG s_dumpsGeneratedCode = dumpsGeneratedCode; @@ -127,27 +127,42 @@ void CodeGenerator::setDumpsGeneratedCode(bool dumpsGeneratedCode) #endif } -void CodeGenerator::generate() +bool BytecodeGenerator::dumpsGeneratedCode() { - m_codeBlock->thisRegister = m_thisRegister.index(); +#ifndef NDEBUG + return s_dumpsGeneratedCode; +#else + return false; +#endif +} + +void BytecodeGenerator::generate() +{ + m_codeBlock->setThisRegister(m_thisRegister.index()); - m_scopeNode->emitCode(*this); + m_scopeNode->emitBytecode(*this); #ifndef NDEBUG - if (s_dumpsGeneratedCode) { - JSGlobalObject* globalObject = m_scopeChain->globalObject(); - m_codeBlock->dump(globalObject->globalExec()); - } + m_codeBlock->setInstructionCount(m_codeBlock->instructions().size()); + + if (s_dumpsGeneratedCode) + m_codeBlock->dump(m_scopeChain->globalObject()->globalExec()); #endif - m_scopeNode->children().shrinkCapacity(0); - if (m_codeType != EvalCode) { // eval code needs to hang on to its declaration stacks to keep declaration info alive until Machine::execute time. - m_scopeNode->varStack().shrinkCapacity(0); - m_scopeNode->functionStack().shrinkCapacity(0); - } + if ((m_codeType == FunctionCode && !m_codeBlock->needsFullScopeChain() && !m_codeBlock->usesArguments()) || m_codeType == EvalCode) + symbolTable().clear(); + + m_codeBlock->setIsNumericCompareFunction(instructions() == m_globalData->numericCompareFunction(m_scopeChain->globalObject()->globalExec())); + +#if !ENABLE(OPCODE_SAMPLING) + if (!m_regeneratingForExceptionInfo && (m_codeType == FunctionCode || m_codeType == EvalCode)) + m_codeBlock->clearExceptionInfo(); +#endif + + m_codeBlock->shrinkToFit(); } -bool CodeGenerator::addVar(const Identifier& ident, bool isConstant, RegisterID*& r0) +bool BytecodeGenerator::addVar(const Identifier& ident, bool isConstant, RegisterID*& r0) { int index = m_calleeRegisters.size(); SymbolTableEntry newEntry(index, isConstant ? ReadOnly : 0); @@ -158,21 +173,21 @@ bool CodeGenerator::addVar(const Identifier& ident, bool isConstant, RegisterID* return false; } - ++m_codeBlock->numVars; + ++m_codeBlock->m_numVars; r0 = newRegister(); return true; } -bool CodeGenerator::addGlobalVar(const Identifier& ident, bool isConstant, RegisterID*& r0) +bool BytecodeGenerator::addGlobalVar(const Identifier& ident, bool isConstant, RegisterID*& r0) { - int index = m_nextGlobal; + int index = m_nextGlobalIndex; SymbolTableEntry newEntry(index, isConstant ? ReadOnly : 0); pair<SymbolTable::iterator, bool> result = symbolTable().add(ident.ustring().rep(), newEntry); if (!result.second) index = result.first->second.getIndex(); else { - --m_nextGlobal; + --m_nextGlobalIndex; m_globals.append(index + m_globalVarStorageOffset); } @@ -180,20 +195,20 @@ bool CodeGenerator::addGlobalVar(const Identifier& ident, bool isConstant, Regis return result.second; } -void CodeGenerator::allocateConstants(size_t count) +void BytecodeGenerator::allocateConstants(size_t count) { - m_codeBlock->numConstants = count; + m_codeBlock->m_numConstants = count; if (!count) return; - m_nextConstant = m_calleeRegisters.size(); + m_nextConstantIndex = m_calleeRegisters.size(); for (size_t i = 0; i < count; ++i) newRegister(); m_lastConstant = &m_calleeRegisters.last(); } -CodeGenerator::CodeGenerator(ProgramNode* programNode, const Debugger* debugger, const ScopeChain& scopeChain, SymbolTable* symbolTable, CodeBlock* codeBlock, VarStack& varStack, FunctionStack& functionStack) +BytecodeGenerator::BytecodeGenerator(ProgramNode* programNode, const Debugger* debugger, const ScopeChain& scopeChain, SymbolTable* symbolTable, ProgramCodeBlock* codeBlock) : m_shouldEmitDebugHooks(!!debugger) , m_shouldEmitProfileHooks(scopeChain.globalObject()->supportsProfiling()) , m_scopeChain(&scopeChain) @@ -203,27 +218,31 @@ CodeGenerator::CodeGenerator(ProgramNode* programNode, const Debugger* debugger, , m_thisRegister(RegisterFile::ProgramCodeThisRegister) , m_finallyDepth(0) , m_dynamicScopeDepth(0) + , m_baseScopeDepth(0) , m_codeType(GlobalCode) - , m_nextGlobal(-1) + , m_nextGlobalIndex(-1) , m_globalData(&scopeChain.globalObject()->globalExec()->globalData()) , m_lastOpcodeID(op_end) + , m_emitNodeDepth(0) + , m_regeneratingForExceptionInfo(false) + , m_codeBlockBeingRegeneratedFrom(0) { if (m_shouldEmitDebugHooks) - m_codeBlock->needsFullScopeChain = true; + m_codeBlock->setNeedsFullScopeChain(true); emitOpcode(op_enter); - codeBlock->globalData = m_globalData; + codeBlock->setGlobalData(m_globalData); - // FIXME: Move code that modifies the global object to Machine::execute. + // FIXME: Move code that modifies the global object to Interpreter::execute. - m_codeBlock->numParameters = 1; // Allocate space for "this" + m_codeBlock->m_numParameters = 1; // Allocate space for "this" JSGlobalObject* globalObject = scopeChain.globalObject(); ExecState* exec = globalObject->globalExec(); - RegisterFile* registerFile = &exec->globalData().machine->registerFile(); + RegisterFile* registerFile = &exec->globalData().interpreter->registerFile(); // Shift register indexes in generated code to elide registers allocated by intermediate stack frames. - m_globalVarStorageOffset = -RegisterFile::CallFrameHeaderSize - m_codeBlock->numParameters - registerFile->size(); + m_globalVarStorageOffset = -RegisterFile::CallFrameHeaderSize - m_codeBlock->m_numParameters - registerFile->size(); // Add previously defined symbols to bookkeeping. m_globals.grow(symbolTable->size()); @@ -233,10 +252,12 @@ CodeGenerator::CodeGenerator(ProgramNode* programNode, const Debugger* debugger, BatchedTransitionOptimizer optimizer(globalObject); + const VarStack& varStack = programNode->varStack(); + const FunctionStack& functionStack = programNode->functionStack(); bool canOptimizeNewGlobals = symbolTable->size() + functionStack.size() + varStack.size() < registerFile->maxGlobals(); if (canOptimizeNewGlobals) { // Shift new symbols so they get stored prior to existing symbols. - m_nextGlobal -= symbolTable->size(); + m_nextGlobalIndex -= symbolTable->size(); for (size_t i = 0; i < functionStack.size(); ++i) { FuncDeclNode* funcDecl = functionStack[i].get(); @@ -271,7 +292,7 @@ CodeGenerator::CodeGenerator(ProgramNode* programNode, const Debugger* debugger, } } -CodeGenerator::CodeGenerator(FunctionBodyNode* functionBody, const Debugger* debugger, const ScopeChain& scopeChain, SymbolTable* symbolTable, CodeBlock* codeBlock) +BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, const Debugger* debugger, const ScopeChain& scopeChain, SymbolTable* symbolTable, CodeBlock* codeBlock) : m_shouldEmitDebugHooks(!!debugger) , m_shouldEmitProfileHooks(scopeChain.globalObject()->supportsProfiling()) , m_scopeChain(&scopeChain) @@ -280,24 +301,28 @@ CodeGenerator::CodeGenerator(FunctionBodyNode* functionBody, const Debugger* deb , m_codeBlock(codeBlock) , m_finallyDepth(0) , m_dynamicScopeDepth(0) + , m_baseScopeDepth(0) , m_codeType(FunctionCode) , m_globalData(&scopeChain.globalObject()->globalExec()->globalData()) , m_lastOpcodeID(op_end) + , m_emitNodeDepth(0) + , m_regeneratingForExceptionInfo(false) + , m_codeBlockBeingRegeneratedFrom(0) { if (m_shouldEmitDebugHooks) - m_codeBlock->needsFullScopeChain = true; + m_codeBlock->setNeedsFullScopeChain(true); - codeBlock->globalData = m_globalData; + codeBlock->setGlobalData(m_globalData); bool usesArguments = functionBody->usesArguments(); - codeBlock->usesArguments = usesArguments; + codeBlock->setUsesArguments(usesArguments); if (usesArguments) { m_argumentsRegister.setIndex(RegisterFile::OptionalCalleeArguments); addVar(propertyNames().arguments, false); } - if (m_codeBlock->needsFullScopeChain) { - ++m_codeBlock->numVars; + if (m_codeBlock->needsFullScopeChain()) { + ++m_codeBlock->m_numVars; m_activationRegisterIndex = newRegister()->index(); emitOpcode(op_enter_with_activation); instructions().append(m_activationRegisterIndex); @@ -307,7 +332,7 @@ CodeGenerator::CodeGenerator(FunctionBodyNode* functionBody, const Debugger* deb if (usesArguments) emitOpcode(op_create_arguments); - const Node::FunctionStack& functionStack = functionBody->functionStack(); + const DeclarationStacks::FunctionStack& functionStack = functionBody->functionStack(); for (size_t i = 0; i < functionStack.size(); ++i) { FuncDeclNode* funcDecl = functionStack[i].get(); const Identifier& ident = funcDecl->m_ident; @@ -315,21 +340,21 @@ CodeGenerator::CodeGenerator(FunctionBodyNode* functionBody, const Debugger* deb emitNewFunction(addVar(ident, false), funcDecl); } - const Node::VarStack& varStack = functionBody->varStack(); + const DeclarationStacks::VarStack& varStack = functionBody->varStack(); for (size_t i = 0; i < varStack.size(); ++i) addVar(varStack[i].first, varStack[i].second & DeclarationStacks::IsConstant); const Identifier* parameters = functionBody->parameters(); size_t parameterCount = functionBody->parameterCount(); - m_nextParameter = -RegisterFile::CallFrameHeaderSize - parameterCount - 1; + m_nextParameterIndex = -RegisterFile::CallFrameHeaderSize - parameterCount - 1; m_parameters.grow(1 + parameterCount); // reserve space for "this" // Add "this" as a parameter - m_thisRegister.setIndex(m_nextParameter); - ++m_nextParameter; - ++m_codeBlock->numParameters; + m_thisRegister.setIndex(m_nextParameterIndex); + ++m_nextParameterIndex; + ++m_codeBlock->m_numParameters; - if (functionBody->usesThis()) { + if (functionBody->usesThis() || m_shouldEmitDebugHooks) { emitOpcode(op_convert_this); instructions().append(m_thisRegister.index()); } @@ -340,7 +365,7 @@ CodeGenerator::CodeGenerator(FunctionBodyNode* functionBody, const Debugger* deb allocateConstants(functionBody->neededConstants()); } -CodeGenerator::CodeGenerator(EvalNode* evalNode, const Debugger* debugger, const ScopeChain& scopeChain, SymbolTable* symbolTable, EvalCodeBlock* codeBlock) +BytecodeGenerator::BytecodeGenerator(EvalNode* evalNode, const Debugger* debugger, const ScopeChain& scopeChain, SymbolTable* symbolTable, EvalCodeBlock* codeBlock) : m_shouldEmitDebugHooks(!!debugger) , m_shouldEmitProfileHooks(scopeChain.globalObject()->supportsProfiling()) , m_scopeChain(&scopeChain) @@ -350,40 +375,44 @@ CodeGenerator::CodeGenerator(EvalNode* evalNode, const Debugger* debugger, const , m_thisRegister(RegisterFile::ProgramCodeThisRegister) , m_finallyDepth(0) , m_dynamicScopeDepth(0) + , m_baseScopeDepth(codeBlock->baseScopeDepth()) , m_codeType(EvalCode) , m_globalData(&scopeChain.globalObject()->globalExec()->globalData()) , m_lastOpcodeID(op_end) + , m_emitNodeDepth(0) + , m_regeneratingForExceptionInfo(false) + , m_codeBlockBeingRegeneratedFrom(0) { - if (m_shouldEmitDebugHooks) - m_codeBlock->needsFullScopeChain = true; + if (m_shouldEmitDebugHooks || m_baseScopeDepth) + m_codeBlock->setNeedsFullScopeChain(true); emitOpcode(op_enter); - codeBlock->globalData = m_globalData; - m_codeBlock->numParameters = 1; // Allocate space for "this" + codeBlock->setGlobalData(m_globalData); + m_codeBlock->m_numParameters = 1; // Allocate space for "this" allocateConstants(evalNode->neededConstants()); } -RegisterID* CodeGenerator::addParameter(const Identifier& ident) +RegisterID* BytecodeGenerator::addParameter(const Identifier& ident) { // Parameters overwrite var declarations, but not function declarations. RegisterID* result = 0; UString::Rep* rep = ident.ustring().rep(); if (!m_functions.contains(rep)) { - symbolTable().set(rep, m_nextParameter); - RegisterID& parameter = registerFor(m_nextParameter); - parameter.setIndex(m_nextParameter); + symbolTable().set(rep, m_nextParameterIndex); + RegisterID& parameter = registerFor(m_nextParameterIndex); + parameter.setIndex(m_nextParameterIndex); result = ¶meter; } // To maintain the calling convention, we have to allocate unique space for // each parameter, even if the parameter doesn't make it into the symbol table. - ++m_nextParameter; - ++m_codeBlock->numParameters; + ++m_nextParameterIndex; + ++m_codeBlock->m_numParameters; return result; } -RegisterID* CodeGenerator::registerFor(const Identifier& ident) +RegisterID* BytecodeGenerator::registerFor(const Identifier& ident) { if (ident == propertyNames().thisIdentifier) return &m_thisRegister; @@ -398,7 +427,7 @@ RegisterID* CodeGenerator::registerFor(const Identifier& ident) return ®isterFor(entry.getIndex()); } -RegisterID* CodeGenerator::constRegisterFor(const Identifier& ident) +RegisterID* BytecodeGenerator::constRegisterFor(const Identifier& ident) { if (m_codeType == EvalCode) return 0; @@ -409,7 +438,7 @@ RegisterID* CodeGenerator::constRegisterFor(const Identifier& ident) return ®isterFor(entry.getIndex()); } -bool CodeGenerator::isLocal(const Identifier& ident) +bool BytecodeGenerator::isLocal(const Identifier& ident) { if (ident == propertyNames().thisIdentifier) return true; @@ -417,19 +446,19 @@ bool CodeGenerator::isLocal(const Identifier& ident) return shouldOptimizeLocals() && symbolTable().contains(ident.ustring().rep()); } -bool CodeGenerator::isLocalConstant(const Identifier& ident) +bool BytecodeGenerator::isLocalConstant(const Identifier& ident) { return symbolTable().get(ident.ustring().rep()).isReadOnly(); } -RegisterID* CodeGenerator::newRegister() +RegisterID* BytecodeGenerator::newRegister() { m_calleeRegisters.append(m_calleeRegisters.size()); - m_codeBlock->numCalleeRegisters = max<int>(m_codeBlock->numCalleeRegisters, m_calleeRegisters.size()); + m_codeBlock->m_numCalleeRegisters = max<int>(m_codeBlock->m_numCalleeRegisters, m_calleeRegisters.size()); return &m_calleeRegisters.last(); } -RegisterID* CodeGenerator::newTemporary() +RegisterID* BytecodeGenerator::newTemporary() { // Reclaim free register IDs. while (m_calleeRegisters.size() && !m_calleeRegisters.last().refCount()) @@ -440,15 +469,15 @@ RegisterID* CodeGenerator::newTemporary() return result; } -RegisterID* CodeGenerator::highestUsedRegister() +RegisterID* BytecodeGenerator::highestUsedRegister() { - size_t count = m_codeBlock->numCalleeRegisters; + size_t count = m_codeBlock->m_numCalleeRegisters; while (m_calleeRegisters.size() < count) newRegister(); return &m_calleeRegisters.last(); } -PassRefPtr<LabelScope> CodeGenerator::newLabelScope(LabelScope::Type type, const Identifier* name) +PassRefPtr<LabelScope> BytecodeGenerator::newLabelScope(LabelScope::Type type, const Identifier* name) { // Reclaim free label scopes. while (m_labelScopes.size() && !m_labelScopes.last().refCount()) @@ -460,7 +489,7 @@ PassRefPtr<LabelScope> CodeGenerator::newLabelScope(LabelScope::Type type, const return &m_labelScopes.last(); } -PassRefPtr<LabelID> CodeGenerator::newLabel() +PassRefPtr<Label> BytecodeGenerator::newLabel() { // Reclaim free label IDs. while (m_labels.size() && !m_labels.last().refCount()) @@ -471,23 +500,34 @@ PassRefPtr<LabelID> CodeGenerator::newLabel() return &m_labels.last(); } -PassRefPtr<LabelID> CodeGenerator::emitLabel(LabelID* l0) +PassRefPtr<Label> BytecodeGenerator::emitLabel(Label* l0) { - l0->setLocation(instructions().size()); - + unsigned newLabelIndex = instructions().size(); + l0->setLocation(newLabelIndex); + + if (m_codeBlock->numberOfJumpTargets()) { + unsigned lastLabelIndex = m_codeBlock->lastJumpTarget(); + ASSERT(lastLabelIndex <= newLabelIndex); + if (newLabelIndex == lastLabelIndex) { + // Peephole optimizations have already been disabled by emitting the last label + return l0; + } + } + + m_codeBlock->addJumpTarget(newLabelIndex); + // This disables peephole optimizations when an instruction is a jump target m_lastOpcodeID = op_end; - return l0; } -void CodeGenerator::emitOpcode(OpcodeID opcodeID) +void BytecodeGenerator::emitOpcode(OpcodeID opcodeID) { - instructions().append(globalData()->machine->getOpcode(opcodeID)); + instructions().append(globalData()->interpreter->getOpcode(opcodeID)); m_lastOpcodeID = opcodeID; } -void CodeGenerator::retrieveLastBinaryOp(int& dstIndex, int& src1Index, int& src2Index) +void BytecodeGenerator::retrieveLastBinaryOp(int& dstIndex, int& src1Index, int& src2Index) { ASSERT(instructions().size() >= 4); size_t size = instructions().size(); @@ -496,7 +536,7 @@ void CodeGenerator::retrieveLastBinaryOp(int& dstIndex, int& src1Index, int& src src2Index = instructions().at(size - 1).u.operand; } -void CodeGenerator::retrieveLastUnaryOp(int& dstIndex, int& srcIndex) +void BytecodeGenerator::retrieveLastUnaryOp(int& dstIndex, int& srcIndex) { ASSERT(instructions().size() >= 3); size_t size = instructions().size(); @@ -504,28 +544,28 @@ void CodeGenerator::retrieveLastUnaryOp(int& dstIndex, int& srcIndex) srcIndex = instructions().at(size - 1).u.operand; } -void ALWAYS_INLINE CodeGenerator::rewindBinaryOp() +void ALWAYS_INLINE BytecodeGenerator::rewindBinaryOp() { ASSERT(instructions().size() >= 4); instructions().shrink(instructions().size() - 4); } -void ALWAYS_INLINE CodeGenerator::rewindUnaryOp() +void ALWAYS_INLINE BytecodeGenerator::rewindUnaryOp() { ASSERT(instructions().size() >= 3); instructions().shrink(instructions().size() - 3); } -PassRefPtr<LabelID> CodeGenerator::emitJump(LabelID* target) +PassRefPtr<Label> BytecodeGenerator::emitJump(Label* target) { - emitOpcode(target->isForwardLabel() ? op_jmp : op_loop); + emitOpcode(target->isForward() ? op_jmp : op_loop); instructions().append(target->offsetFrom(instructions().size())); return target; } -PassRefPtr<LabelID> CodeGenerator::emitJumpIfTrue(RegisterID* cond, LabelID* target) +PassRefPtr<Label> BytecodeGenerator::emitJumpIfTrue(RegisterID* cond, Label* target) { - if (m_lastOpcodeID == op_less && !target->isForwardLabel()) { + if (m_lastOpcodeID == op_less && !target->isForward()) { int dstIndex; int src1Index; int src2Index; @@ -540,7 +580,7 @@ PassRefPtr<LabelID> CodeGenerator::emitJumpIfTrue(RegisterID* cond, LabelID* tar instructions().append(target->offsetFrom(instructions().size())); return target; } - } else if (m_lastOpcodeID == op_lesseq && !target->isForwardLabel()) { + } else if (m_lastOpcodeID == op_lesseq && !target->isForward()) { int dstIndex; int src1Index; int src2Index; @@ -555,7 +595,7 @@ PassRefPtr<LabelID> CodeGenerator::emitJumpIfTrue(RegisterID* cond, LabelID* tar instructions().append(target->offsetFrom(instructions().size())); return target; } - } else if (m_lastOpcodeID == op_eq_null && target->isForwardLabel()) { + } else if (m_lastOpcodeID == op_eq_null && target->isForward()) { int dstIndex; int srcIndex; @@ -568,7 +608,7 @@ PassRefPtr<LabelID> CodeGenerator::emitJumpIfTrue(RegisterID* cond, LabelID* tar instructions().append(target->offsetFrom(instructions().size())); return target; } - } else if (m_lastOpcodeID == op_neq_null && target->isForwardLabel()) { + } else if (m_lastOpcodeID == op_neq_null && target->isForward()) { int dstIndex; int srcIndex; @@ -583,15 +623,15 @@ PassRefPtr<LabelID> CodeGenerator::emitJumpIfTrue(RegisterID* cond, LabelID* tar } } - emitOpcode(target->isForwardLabel() ? op_jtrue : op_loop_if_true); + emitOpcode(target->isForward() ? op_jtrue : op_loop_if_true); instructions().append(cond->index()); instructions().append(target->offsetFrom(instructions().size())); return target; } -PassRefPtr<LabelID> CodeGenerator::emitJumpIfFalse(RegisterID* cond, LabelID* target) +PassRefPtr<Label> BytecodeGenerator::emitJumpIfFalse(RegisterID* cond, Label* target) { - ASSERT(target->isForwardLabel()); + ASSERT(target->isForward()); if (m_lastOpcodeID == op_less) { int dstIndex; @@ -655,62 +695,54 @@ PassRefPtr<LabelID> CodeGenerator::emitJumpIfFalse(RegisterID* cond, LabelID* ta return target; } -unsigned CodeGenerator::addConstant(FuncDeclNode* n) +unsigned BytecodeGenerator::addConstant(FuncDeclNode* n) { // No need to explicitly unique function body nodes -- they're unique already. - int index = m_codeBlock->functions.size(); - m_codeBlock->functions.append(n); - return index; + return m_codeBlock->addFunction(n); } -unsigned CodeGenerator::addConstant(FuncExprNode* n) +unsigned BytecodeGenerator::addConstant(FuncExprNode* n) { // No need to explicitly unique function expression nodes -- they're unique already. - int index = m_codeBlock->functionExpressions.size(); - m_codeBlock->functionExpressions.append(n); - return index; + return m_codeBlock->addFunctionExpression(n); } -unsigned CodeGenerator::addConstant(const Identifier& ident) +unsigned BytecodeGenerator::addConstant(const Identifier& ident) { UString::Rep* rep = ident.ustring().rep(); - pair<IdentifierMap::iterator, bool> result = m_identifierMap.add(rep, m_codeBlock->identifiers.size()); + pair<IdentifierMap::iterator, bool> result = m_identifierMap.add(rep, m_codeBlock->numberOfIdentifiers()); if (result.second) // new entry - m_codeBlock->identifiers.append(Identifier(m_globalData, rep)); + m_codeBlock->addIdentifier(Identifier(m_globalData, rep)); return result.first->second; } -RegisterID* CodeGenerator::addConstant(JSValue* v) +RegisterID* BytecodeGenerator::addConstant(JSValuePtr v) { - pair<JSValueMap::iterator, bool> result = m_jsValueMap.add(v, m_nextConstant); + pair<JSValueMap::iterator, bool> result = m_jsValueMap.add(JSValuePtr::encode(v), m_nextConstantIndex); if (result.second) { - RegisterID& constant = m_calleeRegisters[m_nextConstant]; + RegisterID& constant = m_calleeRegisters[m_nextConstantIndex]; - ++m_nextConstant; + ++m_nextConstantIndex; - m_codeBlock->constantRegisters.append(v); + m_codeBlock->addConstantRegister(JSValuePtr(v)); return &constant; } return ®isterFor(result.first->second); } -unsigned CodeGenerator::addUnexpectedConstant(JSValue* v) +unsigned BytecodeGenerator::addUnexpectedConstant(JSValuePtr v) { - int index = m_codeBlock->unexpectedConstants.size(); - m_codeBlock->unexpectedConstants.append(v); - return index; + return m_codeBlock->addUnexpectedConstant(v); } -unsigned CodeGenerator::addRegExp(RegExp* r) +unsigned BytecodeGenerator::addRegExp(RegExp* r) { - int index = m_codeBlock->regexps.size(); - m_codeBlock->regexps.append(r); - return index; + return m_codeBlock->addRegExp(r); } -RegisterID* CodeGenerator::emitMove(RegisterID* dst, RegisterID* src) +RegisterID* BytecodeGenerator::emitMove(RegisterID* dst, RegisterID* src) { emitOpcode(op_mov); instructions().append(dst->index()); @@ -718,31 +750,29 @@ RegisterID* CodeGenerator::emitMove(RegisterID* dst, RegisterID* src) return dst; } -RegisterID* CodeGenerator::emitUnaryOp(OpcodeID opcode, RegisterID* dst, RegisterID* src, ResultType type) +RegisterID* BytecodeGenerator::emitUnaryOp(OpcodeID opcodeID, RegisterID* dst, RegisterID* src) { - emitOpcode(opcode); + emitOpcode(opcodeID); instructions().append(dst->index()); instructions().append(src->index()); - if (opcode == op_negate) - instructions().append(type.toInt()); return dst; } -RegisterID* CodeGenerator::emitPreInc(RegisterID* srcDst) +RegisterID* BytecodeGenerator::emitPreInc(RegisterID* srcDst) { emitOpcode(op_pre_inc); instructions().append(srcDst->index()); return srcDst; } -RegisterID* CodeGenerator::emitPreDec(RegisterID* srcDst) +RegisterID* BytecodeGenerator::emitPreDec(RegisterID* srcDst) { emitOpcode(op_pre_dec); instructions().append(srcDst->index()); return srcDst; } -RegisterID* CodeGenerator::emitPostInc(RegisterID* dst, RegisterID* srcDst) +RegisterID* BytecodeGenerator::emitPostInc(RegisterID* dst, RegisterID* srcDst) { emitOpcode(op_post_inc); instructions().append(dst->index()); @@ -750,7 +780,7 @@ RegisterID* CodeGenerator::emitPostInc(RegisterID* dst, RegisterID* srcDst) return dst; } -RegisterID* CodeGenerator::emitPostDec(RegisterID* dst, RegisterID* srcDst) +RegisterID* BytecodeGenerator::emitPostDec(RegisterID* dst, RegisterID* srcDst) { emitOpcode(op_post_dec); instructions().append(dst->index()); @@ -758,22 +788,22 @@ RegisterID* CodeGenerator::emitPostDec(RegisterID* dst, RegisterID* srcDst) return dst; } -RegisterID* CodeGenerator::emitBinaryOp(OpcodeID opcode, RegisterID* dst, RegisterID* src1, RegisterID* src2, OperandTypes types) +RegisterID* BytecodeGenerator::emitBinaryOp(OpcodeID opcodeID, RegisterID* dst, RegisterID* src1, RegisterID* src2, OperandTypes types) { - emitOpcode(opcode); + emitOpcode(opcodeID); instructions().append(dst->index()); instructions().append(src1->index()); instructions().append(src2->index()); - if (opcode == op_bitor || opcode == op_bitand || opcode == op_bitxor || - opcode == op_add || opcode == op_mul || opcode == op_sub) { + if (opcodeID == op_bitor || opcodeID == op_bitand || opcodeID == op_bitxor || + opcodeID == op_add || opcodeID == op_mul || opcodeID == op_sub) { instructions().append(types.toInt()); } return dst; } -RegisterID* CodeGenerator::emitEqualityOp(OpcodeID opcode, RegisterID* dst, RegisterID* src1, RegisterID* src2) +RegisterID* BytecodeGenerator::emitEqualityOp(OpcodeID opcodeID, RegisterID* dst, RegisterID* src1, RegisterID* src2) { if (m_lastOpcodeID == op_typeof) { int dstIndex; @@ -783,14 +813,9 @@ RegisterID* CodeGenerator::emitEqualityOp(OpcodeID opcode, RegisterID* dst, Regi if (src1->index() == dstIndex && src1->isTemporary() - // FIXME: replace the following line by - // && m_codeBlock->isConstant(src2->index()) - // after next merge: - // see http://trac.webkit.org/changeset/38229 - // and http://trac.webkit.org/changeset/38230 - && (src2->index() >= m_codeBlock->numVars && src2->index() < m_codeBlock->numVars + m_codeBlock->numConstants) - && m_codeBlock->constantRegisters[src2->index() - m_codeBlock->numVars].jsValue(m_scopeChain->globalObject()->globalExec())->isString()) { - const UString& value = asString(m_codeBlock->constantRegisters[src2->index() - m_codeBlock->numVars].jsValue(m_scopeChain->globalObject()->globalExec()))->value(); + && m_codeBlock->isConstantRegisterIndex(src2->index()) + && m_codeBlock->constantRegister(src2->index() - m_codeBlock->m_numVars).jsValue(m_scopeChain->globalObject()->globalExec()).isString()) { + const UString& value = asString(m_codeBlock->constantRegister(src2->index() - m_codeBlock->m_numVars).jsValue(m_scopeChain->globalObject()->globalExec()))->value(); if (value == "undefined") { rewindUnaryOp(); emitOpcode(op_is_undefined); @@ -836,39 +861,39 @@ RegisterID* CodeGenerator::emitEqualityOp(OpcodeID opcode, RegisterID* dst, Regi } } - emitOpcode(opcode); + emitOpcode(opcodeID); instructions().append(dst->index()); instructions().append(src1->index()); instructions().append(src2->index()); return dst; } -RegisterID* CodeGenerator::emitLoad(RegisterID* dst, bool b) +RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, bool b) { return emitLoad(dst, jsBoolean(b)); } -RegisterID* CodeGenerator::emitLoad(RegisterID* dst, double number) +RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, double number) { // FIXME: Our hash tables won't hold infinity, so we make a new JSNumberCell each time. // Later we can do the extra work to handle that like the other cases. if (number == HashTraits<double>::emptyValue() || HashTraits<double>::isDeletedValue(number)) return emitLoad(dst, jsNumber(globalData(), number)); - JSValue*& valueInMap = m_numberMap.add(number, noValue()).first->second; + JSValuePtr& valueInMap = m_numberMap.add(number, noValue()).first->second; if (!valueInMap) valueInMap = jsNumber(globalData(), number); return emitLoad(dst, valueInMap); } -RegisterID* CodeGenerator::emitLoad(RegisterID* dst, const Identifier& identifier) +RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, const Identifier& identifier) { - JSString*& valueInMap = m_stringMap.add(identifier.ustring().rep(), 0).first->second; - if (!valueInMap) - valueInMap = jsOwnedString(globalData(), identifier.ustring()); - return emitLoad(dst, valueInMap); + JSString*& stringInMap = m_stringMap.add(identifier.ustring().rep(), 0).first->second; + if (!stringInMap) + stringInMap = jsOwnedString(globalData(), identifier.ustring()); + return emitLoad(dst, JSValuePtr(stringInMap)); } -RegisterID* CodeGenerator::emitLoad(RegisterID* dst, JSValue* v) +RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, JSValuePtr v) { RegisterID* constantID = addConstant(v); if (dst) @@ -876,13 +901,7 @@ RegisterID* CodeGenerator::emitLoad(RegisterID* dst, JSValue* v) return constantID; } -RegisterID* CodeGenerator::emitLoad(RegisterID* dst, JSCell* cell) -{ - JSValue* value = cell; - return emitLoad(dst, value); -} - -RegisterID* CodeGenerator::emitUnexpectedLoad(RegisterID* dst, bool b) +RegisterID* BytecodeGenerator::emitUnexpectedLoad(RegisterID* dst, bool b) { emitOpcode(op_unexpected_load); instructions().append(dst->index()); @@ -890,7 +909,7 @@ RegisterID* CodeGenerator::emitUnexpectedLoad(RegisterID* dst, bool b) return dst; } -RegisterID* CodeGenerator::emitUnexpectedLoad(RegisterID* dst, double d) +RegisterID* BytecodeGenerator::emitUnexpectedLoad(RegisterID* dst, double d) { emitOpcode(op_unexpected_load); instructions().append(dst->index()); @@ -898,7 +917,7 @@ RegisterID* CodeGenerator::emitUnexpectedLoad(RegisterID* dst, double d) return dst; } -bool CodeGenerator::findScopedProperty(const Identifier& property, int& index, size_t& stackDepth, bool forWriting, JSObject*& globalObject) +bool BytecodeGenerator::findScopedProperty(const Identifier& property, int& index, size_t& stackDepth, bool forWriting, JSObject*& globalObject) { // Cases where we cannot statically optimize the lookup. if (property == propertyNames().arguments || !canOptimizeNonLocals()) { @@ -952,7 +971,7 @@ bool CodeGenerator::findScopedProperty(const Identifier& property, int& index, s return true; } -RegisterID* CodeGenerator::emitInstanceOf(RegisterID* dst, RegisterID* value, RegisterID* base, RegisterID* basePrototype) +RegisterID* BytecodeGenerator::emitInstanceOf(RegisterID* dst, RegisterID* value, RegisterID* base, RegisterID* basePrototype) { emitOpcode(op_instanceof); instructions().append(dst->index()); @@ -962,7 +981,7 @@ RegisterID* CodeGenerator::emitInstanceOf(RegisterID* dst, RegisterID* value, Re return dst; } -RegisterID* CodeGenerator::emitResolve(RegisterID* dst, const Identifier& property) +RegisterID* BytecodeGenerator::emitResolve(RegisterID* dst, const Identifier& property) { size_t depth = 0; int index = 0; @@ -975,13 +994,26 @@ RegisterID* CodeGenerator::emitResolve(RegisterID* dst, const Identifier& proper return dst; } - if (index != missingSymbolMarker()) { - // Directly index the property lookup across multiple scopes. Yay! - return emitGetScopedVar(dst, depth, index, globalObject); - } - if (globalObject) { - m_codeBlock->globalResolveInstructions.append(instructions().size()); + bool forceGlobalResolve = false; + if (m_regeneratingForExceptionInfo) { +#if ENABLE(JIT) + forceGlobalResolve = m_codeBlockBeingRegeneratedFrom->hasGlobalResolveInfoAtBytecodeOffset(instructions().size()); +#else + forceGlobalResolve = m_codeBlockBeingRegeneratedFrom->hasGlobalResolveInstructionAtBytecodeOffset(instructions().size()); +#endif + } + + if (index != missingSymbolMarker() && !forceGlobalResolve) { + // Directly index the property lookup across multiple scopes. + return emitGetScopedVar(dst, depth, index, globalObject); + } + +#if ENABLE(JIT) + m_codeBlock->addGlobalResolveInfo(instructions().size()); +#else + m_codeBlock->addGlobalResolveInstruction(instructions().size()); +#endif emitOpcode(op_resolve_global); instructions().append(dst->index()); instructions().append(globalObject); @@ -991,6 +1023,11 @@ RegisterID* CodeGenerator::emitResolve(RegisterID* dst, const Identifier& proper return dst; } + if (index != missingSymbolMarker()) { + // Directly index the property lookup across multiple scopes. + return emitGetScopedVar(dst, depth, index, globalObject); + } + // In this case we are at least able to drop a few scope chains from the // lookup chain, although we still need to hash from then on. emitOpcode(op_resolve_skip); @@ -1000,7 +1037,7 @@ RegisterID* CodeGenerator::emitResolve(RegisterID* dst, const Identifier& proper return dst; } -RegisterID* CodeGenerator::emitGetScopedVar(RegisterID* dst, size_t depth, int index, JSValue* globalObject) +RegisterID* BytecodeGenerator::emitGetScopedVar(RegisterID* dst, size_t depth, int index, JSValuePtr globalObject) { if (globalObject) { emitOpcode(op_get_global_var); @@ -1017,7 +1054,7 @@ RegisterID* CodeGenerator::emitGetScopedVar(RegisterID* dst, size_t depth, int i return dst; } -RegisterID* CodeGenerator::emitPutScopedVar(size_t depth, int index, RegisterID* value, JSValue* globalObject) +RegisterID* BytecodeGenerator::emitPutScopedVar(size_t depth, int index, RegisterID* value, JSValuePtr globalObject) { if (globalObject) { emitOpcode(op_put_global_var); @@ -1033,7 +1070,7 @@ RegisterID* CodeGenerator::emitPutScopedVar(size_t depth, int index, RegisterID* return value; } -RegisterID* CodeGenerator::emitResolveBase(RegisterID* dst, const Identifier& property) +RegisterID* BytecodeGenerator::emitResolveBase(RegisterID* dst, const Identifier& property) { emitOpcode(op_resolve_base); instructions().append(dst->index()); @@ -1041,7 +1078,7 @@ RegisterID* CodeGenerator::emitResolveBase(RegisterID* dst, const Identifier& pr return dst; } -RegisterID* CodeGenerator::emitResolveWithBase(RegisterID* baseDst, RegisterID* propDst, const Identifier& property) +RegisterID* BytecodeGenerator::emitResolveWithBase(RegisterID* baseDst, RegisterID* propDst, const Identifier& property) { emitOpcode(op_resolve_with_base); instructions().append(baseDst->index()); @@ -1050,7 +1087,7 @@ RegisterID* CodeGenerator::emitResolveWithBase(RegisterID* baseDst, RegisterID* return baseDst; } -RegisterID* CodeGenerator::emitResolveFunction(RegisterID* baseDst, RegisterID* funcDst, const Identifier& property) +RegisterID* BytecodeGenerator::emitResolveFunction(RegisterID* baseDst, RegisterID* funcDst, const Identifier& property) { emitOpcode(op_resolve_func); instructions().append(baseDst->index()); @@ -1059,9 +1096,13 @@ RegisterID* CodeGenerator::emitResolveFunction(RegisterID* baseDst, RegisterID* return baseDst; } -RegisterID* CodeGenerator::emitGetById(RegisterID* dst, RegisterID* base, const Identifier& property) +RegisterID* BytecodeGenerator::emitGetById(RegisterID* dst, RegisterID* base, const Identifier& property) { - m_codeBlock->propertyAccessInstructions.append(instructions().size()); +#if ENABLE(JIT) + m_codeBlock->addStructureStubInfo(StructureStubInfo(op_get_by_id)); +#else + m_codeBlock->addPropertyAccessInstruction(instructions().size()); +#endif emitOpcode(op_get_by_id); instructions().append(dst->index()); @@ -1074,9 +1115,13 @@ RegisterID* CodeGenerator::emitGetById(RegisterID* dst, RegisterID* base, const return dst; } -RegisterID* CodeGenerator::emitPutById(RegisterID* base, const Identifier& property, RegisterID* value) +RegisterID* BytecodeGenerator::emitPutById(RegisterID* base, const Identifier& property, RegisterID* value) { - m_codeBlock->propertyAccessInstructions.append(instructions().size()); +#if ENABLE(JIT) + m_codeBlock->addStructureStubInfo(StructureStubInfo(op_put_by_id)); +#else + m_codeBlock->addPropertyAccessInstruction(instructions().size()); +#endif emitOpcode(op_put_by_id); instructions().append(base->index()); @@ -1089,7 +1134,7 @@ RegisterID* CodeGenerator::emitPutById(RegisterID* base, const Identifier& prope return value; } -RegisterID* CodeGenerator::emitPutGetter(RegisterID* base, const Identifier& property, RegisterID* value) +RegisterID* BytecodeGenerator::emitPutGetter(RegisterID* base, const Identifier& property, RegisterID* value) { emitOpcode(op_put_getter); instructions().append(base->index()); @@ -1098,7 +1143,7 @@ RegisterID* CodeGenerator::emitPutGetter(RegisterID* base, const Identifier& pro return value; } -RegisterID* CodeGenerator::emitPutSetter(RegisterID* base, const Identifier& property, RegisterID* value) +RegisterID* BytecodeGenerator::emitPutSetter(RegisterID* base, const Identifier& property, RegisterID* value) { emitOpcode(op_put_setter); instructions().append(base->index()); @@ -1107,7 +1152,7 @@ RegisterID* CodeGenerator::emitPutSetter(RegisterID* base, const Identifier& pro return value; } -RegisterID* CodeGenerator::emitDeleteById(RegisterID* dst, RegisterID* base, const Identifier& property) +RegisterID* BytecodeGenerator::emitDeleteById(RegisterID* dst, RegisterID* base, const Identifier& property) { emitOpcode(op_del_by_id); instructions().append(dst->index()); @@ -1116,7 +1161,7 @@ RegisterID* CodeGenerator::emitDeleteById(RegisterID* dst, RegisterID* base, con return dst; } -RegisterID* CodeGenerator::emitGetByVal(RegisterID* dst, RegisterID* base, RegisterID* property) +RegisterID* BytecodeGenerator::emitGetByVal(RegisterID* dst, RegisterID* base, RegisterID* property) { emitOpcode(op_get_by_val); instructions().append(dst->index()); @@ -1125,7 +1170,7 @@ RegisterID* CodeGenerator::emitGetByVal(RegisterID* dst, RegisterID* base, Regis return dst; } -RegisterID* CodeGenerator::emitPutByVal(RegisterID* base, RegisterID* property, RegisterID* value) +RegisterID* BytecodeGenerator::emitPutByVal(RegisterID* base, RegisterID* property, RegisterID* value) { emitOpcode(op_put_by_val); instructions().append(base->index()); @@ -1134,7 +1179,7 @@ RegisterID* CodeGenerator::emitPutByVal(RegisterID* base, RegisterID* property, return value; } -RegisterID* CodeGenerator::emitDeleteByVal(RegisterID* dst, RegisterID* base, RegisterID* property) +RegisterID* BytecodeGenerator::emitDeleteByVal(RegisterID* dst, RegisterID* base, RegisterID* property) { emitOpcode(op_del_by_val); instructions().append(dst->index()); @@ -1143,7 +1188,7 @@ RegisterID* CodeGenerator::emitDeleteByVal(RegisterID* dst, RegisterID* base, Re return dst; } -RegisterID* CodeGenerator::emitPutByIndex(RegisterID* base, unsigned index, RegisterID* value) +RegisterID* BytecodeGenerator::emitPutByIndex(RegisterID* base, unsigned index, RegisterID* value) { emitOpcode(op_put_by_index); instructions().append(base->index()); @@ -1152,20 +1197,22 @@ RegisterID* CodeGenerator::emitPutByIndex(RegisterID* base, unsigned index, Regi return value; } -RegisterID* CodeGenerator::emitNewObject(RegisterID* dst) +RegisterID* BytecodeGenerator::emitNewObject(RegisterID* dst) { emitOpcode(op_new_object); instructions().append(dst->index()); return dst; } -RegisterID* CodeGenerator::emitNewArray(RegisterID* dst, ElementNode* elements) +RegisterID* BytecodeGenerator::emitNewArray(RegisterID* dst, ElementNode* elements) { Vector<RefPtr<RegisterID>, 16> argv; for (ElementNode* n = elements; n; n = n->next()) { if (n->elision()) break; argv.append(newTemporary()); + // op_new_array requires the initial values to be a sequential range of registers + ASSERT(argv.size() == 1 || argv[argv.size() - 1]->index() == argv[argv.size() - 2]->index() + 1); emitNode(argv.last().get(), n->value()); } emitOpcode(op_new_array); @@ -1175,7 +1222,7 @@ RegisterID* CodeGenerator::emitNewArray(RegisterID* dst, ElementNode* elements) return dst; } -RegisterID* CodeGenerator::emitNewFunction(RegisterID* dst, FuncDeclNode* n) +RegisterID* BytecodeGenerator::emitNewFunction(RegisterID* dst, FuncDeclNode* n) { emitOpcode(op_new_func); instructions().append(dst->index()); @@ -1183,7 +1230,7 @@ RegisterID* CodeGenerator::emitNewFunction(RegisterID* dst, FuncDeclNode* n) return dst; } -RegisterID* CodeGenerator::emitNewRegExp(RegisterID* dst, RegExp* regExp) +RegisterID* BytecodeGenerator::emitNewRegExp(RegisterID* dst, RegExp* regExp) { emitOpcode(op_new_regexp); instructions().append(dst->index()); @@ -1192,7 +1239,7 @@ RegisterID* CodeGenerator::emitNewRegExp(RegisterID* dst, RegExp* regExp) } -RegisterID* CodeGenerator::emitNewFunctionExpression(RegisterID* r0, FuncExprNode* n) +RegisterID* BytecodeGenerator::emitNewFunctionExpression(RegisterID* r0, FuncExprNode* n) { emitOpcode(op_new_func_exp); instructions().append(r0->index()); @@ -1200,27 +1247,43 @@ RegisterID* CodeGenerator::emitNewFunctionExpression(RegisterID* r0, FuncExprNod return r0; } -RegisterID* CodeGenerator::emitCall(RegisterID* dst, RegisterID* func, RegisterID* base, ArgumentsNode* argumentsNode, unsigned divot, unsigned startOffset, unsigned endOffset) +RegisterID* BytecodeGenerator::emitCall(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, ArgumentsNode* argumentsNode, unsigned divot, unsigned startOffset, unsigned endOffset) { - return emitCall(op_call, dst, func, base, argumentsNode, divot, startOffset, endOffset); + return emitCall(op_call, dst, func, thisRegister, argumentsNode, divot, startOffset, endOffset); } -RegisterID* CodeGenerator::emitCallEval(RegisterID* dst, RegisterID* func, RegisterID* base, ArgumentsNode* argumentsNode, unsigned divot, unsigned startOffset, unsigned endOffset) +RegisterID* BytecodeGenerator::emitCallEval(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, ArgumentsNode* argumentsNode, unsigned divot, unsigned startOffset, unsigned endOffset) { - return emitCall(op_call_eval, dst, func, base, argumentsNode, divot, startOffset, endOffset); + return emitCall(op_call_eval, dst, func, thisRegister, argumentsNode, divot, startOffset, endOffset); } -RegisterID* CodeGenerator::emitCall(OpcodeID opcodeID, RegisterID* dst, RegisterID* func, RegisterID* base, ArgumentsNode* argumentsNode, unsigned divot, unsigned startOffset, unsigned endOffset) +RegisterID* BytecodeGenerator::emitCall(OpcodeID opcodeID, RegisterID* dst, RegisterID* func, RegisterID* thisRegister, ArgumentsNode* argumentsNode, unsigned divot, unsigned startOffset, unsigned endOffset) { ASSERT(opcodeID == op_call || opcodeID == op_call_eval); ASSERT(func->refCount()); - ASSERT(!base || base->refCount()); - + ASSERT(thisRegister->refCount()); + + RegisterID* originalFunc = func; + if (m_shouldEmitProfileHooks) { + // If codegen decided to recycle func as this call's destination register, + // we need to undo that optimization here so that func will still be around + // for the sake of op_profile_did_call. + if (dst == func) { + RefPtr<RegisterID> movedThisRegister = emitMove(newTemporary(), thisRegister); + RefPtr<RegisterID> movedFunc = emitMove(thisRegister, func); + + thisRegister = movedThisRegister.release().releaseRef(); + func = movedFunc.release().releaseRef(); + } + } + // Generate code for arguments. Vector<RefPtr<RegisterID>, 16> argv; - argv.append(newTemporary()); // reserve space for "this" + argv.append(thisRegister); for (ArgumentListNode* n = argumentsNode->m_listNode.get(); n; n = n->m_next.get()) { argv.append(newTemporary()); + // op_call requires the arguments to be a sequential range of registers + ASSERT(argv[argv.size() - 1]->index() == argv[argv.size() - 2]->index() + 1); emitNode(argv.last().get(), n); } @@ -1232,48 +1295,71 @@ RegisterID* CodeGenerator::emitCall(OpcodeID opcodeID, RegisterID* dst, Register if (m_shouldEmitProfileHooks) { emitOpcode(op_profile_will_call); instructions().append(func->index()); + +#if ENABLE(JIT) + m_codeBlock->addFunctionRegisterInfo(instructions().size(), func->index()); +#endif } emitExpressionInfo(divot, startOffset, endOffset); - m_codeBlock->callLinkInfos.append(CallLinkInfo()); + +#if ENABLE(JIT) + m_codeBlock->addCallLinkInfo(); +#endif + + // Emit call. emitOpcode(opcodeID); - instructions().append(dst->index()); - instructions().append(func->index()); - instructions().append(base ? base->index() : missingThisObjectMarker()); // We encode the "this" value in the instruction stream, to avoid an explicit instruction for copying or loading it. - instructions().append(argv[0]->index()); // argv - instructions().append(argv.size()); // argc + instructions().append(dst->index()); // dst + instructions().append(func->index()); // func + instructions().append(argv.size()); // argCount instructions().append(argv[0]->index() + argv.size() + RegisterFile::CallFrameHeaderSize); // registerOffset if (m_shouldEmitProfileHooks) { emitOpcode(op_profile_did_call); instructions().append(func->index()); + + if (dst == originalFunc) { + thisRegister->deref(); + func->deref(); + } } return dst; } -RegisterID* CodeGenerator::emitReturn(RegisterID* src) +RegisterID* BytecodeGenerator::emitReturn(RegisterID* src) { - if (m_codeBlock->needsFullScopeChain) { + if (m_codeBlock->needsFullScopeChain()) { emitOpcode(op_tear_off_activation); instructions().append(m_activationRegisterIndex); - } else if (m_codeBlock->usesArguments && m_codeBlock->numParameters > 1) + } else if (m_codeBlock->usesArguments() && m_codeBlock->m_numParameters > 1) emitOpcode(op_tear_off_arguments); return emitUnaryNoDstOp(op_ret, src); } -RegisterID* CodeGenerator::emitUnaryNoDstOp(OpcodeID opcode, RegisterID* src) +RegisterID* BytecodeGenerator::emitUnaryNoDstOp(OpcodeID opcodeID, RegisterID* src) { - emitOpcode(opcode); + emitOpcode(opcodeID); instructions().append(src->index()); return src; } -RegisterID* CodeGenerator::emitConstruct(RegisterID* dst, RegisterID* func, ArgumentsNode* argumentsNode, unsigned divot, unsigned startOffset, unsigned endOffset) +RegisterID* BytecodeGenerator::emitConstruct(RegisterID* dst, RegisterID* func, ArgumentsNode* argumentsNode, unsigned divot, unsigned startOffset, unsigned endOffset) { ASSERT(func->refCount()); + RegisterID* originalFunc = func; + if (m_shouldEmitProfileHooks) { + // If codegen decided to recycle func as this call's destination register, + // we need to undo that optimization here so that func will still be around + // for the sake of op_profile_did_call. + if (dst == func) { + RefPtr<RegisterID> movedFunc = emitMove(newTemporary(), func); + func = movedFunc.release().releaseRef(); + } + } + RefPtr<RegisterID> funcProto = newTemporary(); // Generate code for arguments. @@ -1281,6 +1367,8 @@ RegisterID* CodeGenerator::emitConstruct(RegisterID* dst, RegisterID* func, Argu argv.append(newTemporary()); // reserve space for "this" for (ArgumentListNode* n = argumentsNode ? argumentsNode->m_listNode.get() : 0; n; n = n->m_next.get()) { argv.append(newTemporary()); + // op_construct requires the arguments to be a sequential range of registers + ASSERT(argv[argv.size() - 1]->index() == argv[argv.size() - 2]->index() + 1); emitNode(argv.last().get(), n); } @@ -1291,6 +1379,7 @@ RegisterID* CodeGenerator::emitConstruct(RegisterID* dst, RegisterID* func, Argu // Load prototype. emitExpressionInfo(divot, startOffset, endOffset); + emitGetByIdExceptionInfo(op_construct); emitGetById(funcProto.get(), func, globalData()->propertyNames->prototype); // Reserve space for call frame. @@ -1299,14 +1388,18 @@ RegisterID* CodeGenerator::emitConstruct(RegisterID* dst, RegisterID* func, Argu callFrame.append(newTemporary()); emitExpressionInfo(divot, startOffset, endOffset); - m_codeBlock->callLinkInfos.append(CallLinkInfo()); + +#if ENABLE(JIT) + m_codeBlock->addCallLinkInfo(); +#endif + emitOpcode(op_construct); - instructions().append(dst->index()); - instructions().append(func->index()); - instructions().append(funcProto->index()); - instructions().append(argv[0]->index()); // argv - instructions().append(argv.size()); // argc + instructions().append(dst->index()); // dst + instructions().append(func->index()); // func + instructions().append(argv.size()); // argCount instructions().append(argv[0]->index() + argv.size() + RegisterFile::CallFrameHeaderSize); // registerOffset + instructions().append(funcProto->index()); // proto + instructions().append(argv[0]->index()); // thisRegister emitOpcode(op_construct_verify); instructions().append(dst->index()); @@ -1315,13 +1408,17 @@ RegisterID* CodeGenerator::emitConstruct(RegisterID* dst, RegisterID* func, Argu if (m_shouldEmitProfileHooks) { emitOpcode(op_profile_did_call); instructions().append(func->index()); + + if (dst == originalFunc) + func->deref(); } return dst; } -RegisterID* CodeGenerator::emitPushScope(RegisterID* scope) +RegisterID* BytecodeGenerator::emitPushScope(RegisterID* scope) { + ASSERT(scope->isTemporary()); ControlFlowContext context; context.isFinallyBlock = false; m_scopeContextStack.append(context); @@ -1330,7 +1427,7 @@ RegisterID* CodeGenerator::emitPushScope(RegisterID* scope) return emitUnaryNoDstOp(op_push_scope, scope); } -void CodeGenerator::emitPopScope() +void BytecodeGenerator::emitPopScope() { ASSERT(m_scopeContextStack.size()); ASSERT(!m_scopeContextStack.last().isFinallyBlock); @@ -1341,7 +1438,7 @@ void CodeGenerator::emitPopScope() m_dynamicScopeDepth--; } -void CodeGenerator::emitDebugHook(DebugHookID debugHookID, int firstLine, int lastLine) +void BytecodeGenerator::emitDebugHook(DebugHookID debugHookID, int firstLine, int lastLine) { if (!m_shouldEmitDebugHooks) return; @@ -1351,7 +1448,7 @@ void CodeGenerator::emitDebugHook(DebugHookID debugHookID, int firstLine, int la instructions().append(lastLine); } -void CodeGenerator::pushFinallyContext(LabelID* target, RegisterID* retAddrDst) +void BytecodeGenerator::pushFinallyContext(Label* target, RegisterID* retAddrDst) { ControlFlowContext scope; scope.isFinallyBlock = true; @@ -1361,7 +1458,7 @@ void CodeGenerator::pushFinallyContext(LabelID* target, RegisterID* retAddrDst) m_finallyDepth++; } -void CodeGenerator::popFinallyContext() +void BytecodeGenerator::popFinallyContext() { ASSERT(m_scopeContextStack.size()); ASSERT(m_scopeContextStack.last().isFinallyBlock); @@ -1370,7 +1467,7 @@ void CodeGenerator::popFinallyContext() m_finallyDepth--; } -LabelScope* CodeGenerator::breakTarget(const Identifier& name) +LabelScope* BytecodeGenerator::breakTarget(const Identifier& name) { // Reclaim free label scopes. while (m_labelScopes.size() && !m_labelScopes.last().refCount()) @@ -1403,7 +1500,7 @@ LabelScope* CodeGenerator::breakTarget(const Identifier& name) return 0; } -LabelScope* CodeGenerator::continueTarget(const Identifier& name) +LabelScope* BytecodeGenerator::continueTarget(const Identifier& name) { // Reclaim free label scopes. while (m_labelScopes.size() && !m_labelScopes.last().refCount()) @@ -1438,7 +1535,7 @@ LabelScope* CodeGenerator::continueTarget(const Identifier& name) return 0; } -PassRefPtr<LabelID> CodeGenerator::emitComplexJumpScopes(LabelID* target, ControlFlowContext* topScope, ControlFlowContext* bottomScope) +PassRefPtr<Label> BytecodeGenerator::emitComplexJumpScopes(Label* target, ControlFlowContext* topScope, ControlFlowContext* bottomScope) { while (topScope > bottomScope) { // First we count the number of dynamic scopes we need to remove to get @@ -1466,7 +1563,7 @@ PassRefPtr<LabelID> CodeGenerator::emitComplexJumpScopes(LabelID* target, Contro // Otherwise we just use jmp_scopes to pop a group of scopes and go // to the next instruction - RefPtr<LabelID> nextInsn = newLabel(); + RefPtr<Label> nextInsn = newLabel(); instructions().append(nextInsn->offsetFrom(instructions().size())); emitLabel(nextInsn.get()); } @@ -1483,10 +1580,10 @@ PassRefPtr<LabelID> CodeGenerator::emitComplexJumpScopes(LabelID* target, Contro return emitJump(target); } -PassRefPtr<LabelID> CodeGenerator::emitJumpScopes(LabelID* target, int targetScopeDepth) +PassRefPtr<Label> BytecodeGenerator::emitJumpScopes(Label* target, int targetScopeDepth) { ASSERT(scopeDepth() - targetScopeDepth >= 0); - ASSERT(target->isForwardLabel()); + ASSERT(target->isForward()); size_t scopeDelta = scopeDepth() - targetScopeDepth; ASSERT(scopeDelta <= m_scopeContextStack.size()); @@ -1502,7 +1599,7 @@ PassRefPtr<LabelID> CodeGenerator::emitJumpScopes(LabelID* target, int targetSco return target; } -RegisterID* CodeGenerator::emitNextPropertyName(RegisterID* dst, RegisterID* iter, LabelID* target) +RegisterID* BytecodeGenerator::emitNextPropertyName(RegisterID* dst, RegisterID* iter, Label* target) { emitOpcode(op_next_pname); instructions().append(dst->index()); @@ -1511,16 +1608,21 @@ RegisterID* CodeGenerator::emitNextPropertyName(RegisterID* dst, RegisterID* ite return dst; } -RegisterID* CodeGenerator::emitCatch(RegisterID* targetRegister, LabelID* start, LabelID* end) +RegisterID* BytecodeGenerator::emitCatch(RegisterID* targetRegister, Label* start, Label* end) { - HandlerInfo info = { start->offsetFrom(0), end->offsetFrom(0), instructions().size(), m_dynamicScopeDepth, 0 }; - exceptionHandlers().append(info); +#if ENABLE(JIT) + HandlerInfo info = { start->offsetFrom(0), end->offsetFrom(0), instructions().size(), m_dynamicScopeDepth + m_baseScopeDepth, 0 }; +#else + HandlerInfo info = { start->offsetFrom(0), end->offsetFrom(0), instructions().size(), m_dynamicScopeDepth + m_baseScopeDepth }; +#endif + + m_codeBlock->addExceptionHandler(info); emitOpcode(op_catch); instructions().append(targetRegister->index()); return targetRegister; } -RegisterID* CodeGenerator::emitNewError(RegisterID* dst, ErrorType type, JSValue* message) +RegisterID* BytecodeGenerator::emitNewError(RegisterID* dst, ErrorType type, JSValuePtr message) { emitOpcode(op_new_error); instructions().append(dst->index()); @@ -1529,7 +1631,7 @@ RegisterID* CodeGenerator::emitNewError(RegisterID* dst, ErrorType type, JSValue return dst; } -PassRefPtr<LabelID> CodeGenerator::emitJumpSubroutine(RegisterID* retAddrDst, LabelID* finally) +PassRefPtr<Label> BytecodeGenerator::emitJumpSubroutine(RegisterID* retAddrDst, Label* finally) { emitOpcode(op_jsr); instructions().append(retAddrDst->index()); @@ -1537,13 +1639,13 @@ PassRefPtr<LabelID> CodeGenerator::emitJumpSubroutine(RegisterID* retAddrDst, La return finally; } -void CodeGenerator::emitSubroutineReturn(RegisterID* retAddrSrc) +void BytecodeGenerator::emitSubroutineReturn(RegisterID* retAddrSrc) { emitOpcode(op_sret); instructions().append(retAddrSrc->index()); } -void CodeGenerator::emitPushNewScope(RegisterID* dst, Identifier& property, RegisterID* value) +void BytecodeGenerator::emitPushNewScope(RegisterID* dst, Identifier& property, RegisterID* value) { ControlFlowContext context; context.isFinallyBlock = false; @@ -1556,7 +1658,7 @@ void CodeGenerator::emitPushNewScope(RegisterID* dst, Identifier& property, Regi instructions().append(value->index()); } -void CodeGenerator::beginSwitch(RegisterID* scrutineeRegister, SwitchInfo::SwitchType type) +void BytecodeGenerator::beginSwitch(RegisterID* scrutineeRegister, SwitchInfo::SwitchType type) { SwitchInfo info = { instructions().size(), type }; switch (type) { @@ -1584,15 +1686,15 @@ static int32_t keyForImmediateSwitch(ExpressionNode* node, int32_t min, int32_t UNUSED_PARAM(max); ASSERT(node->isNumber()); double value = static_cast<NumberNode*>(node)->value(); - ASSERT(JSImmediate::from(value)); int32_t key = static_cast<int32_t>(value); + ASSERT(JSValuePtr::makeInt32Fast(key) && (JSValuePtr::makeInt32Fast(key).getInt32Fast() == value)); ASSERT(key == value); ASSERT(key >= min); ASSERT(key <= max); return key - min; } -static void prepareJumpTableForImmediateSwitch(SimpleJumpTable& jumpTable, int32_t switchAddress, uint32_t clauseCount, RefPtr<LabelID>* labels, ExpressionNode** nodes, int32_t min, int32_t max) +static void prepareJumpTableForImmediateSwitch(SimpleJumpTable& jumpTable, int32_t switchAddress, uint32_t clauseCount, RefPtr<Label>* labels, ExpressionNode** nodes, int32_t min, int32_t max) { jumpTable.min = min; jumpTable.branchOffsets.resize(max - min + 1); @@ -1600,7 +1702,7 @@ static void prepareJumpTableForImmediateSwitch(SimpleJumpTable& jumpTable, int32 for (uint32_t i = 0; i < clauseCount; ++i) { // We're emitting this after the clause labels should have been fixed, so // the labels should not be "forward" references - ASSERT(!labels[i]->isForwardLabel()); + ASSERT(!labels[i]->isForward()); jumpTable.add(keyForImmediateSwitch(nodes[i], min, max), labels[i]->offsetFrom(switchAddress)); } } @@ -1618,7 +1720,7 @@ static int32_t keyForCharacterSwitch(ExpressionNode* node, int32_t min, int32_t return key - min; } -static void prepareJumpTableForCharacterSwitch(SimpleJumpTable& jumpTable, int32_t switchAddress, uint32_t clauseCount, RefPtr<LabelID>* labels, ExpressionNode** nodes, int32_t min, int32_t max) +static void prepareJumpTableForCharacterSwitch(SimpleJumpTable& jumpTable, int32_t switchAddress, uint32_t clauseCount, RefPtr<Label>* labels, ExpressionNode** nodes, int32_t min, int32_t max) { jumpTable.min = min; jumpTable.branchOffsets.resize(max - min + 1); @@ -1626,59 +1728,65 @@ static void prepareJumpTableForCharacterSwitch(SimpleJumpTable& jumpTable, int32 for (uint32_t i = 0; i < clauseCount; ++i) { // We're emitting this after the clause labels should have been fixed, so // the labels should not be "forward" references - ASSERT(!labels[i]->isForwardLabel()); + ASSERT(!labels[i]->isForward()); jumpTable.add(keyForCharacterSwitch(nodes[i], min, max), labels[i]->offsetFrom(switchAddress)); } } -static void prepareJumpTableForStringSwitch(StringJumpTable& jumpTable, int32_t switchAddress, uint32_t clauseCount, RefPtr<LabelID>* labels, ExpressionNode** nodes) +static void prepareJumpTableForStringSwitch(StringJumpTable& jumpTable, int32_t switchAddress, uint32_t clauseCount, RefPtr<Label>* labels, ExpressionNode** nodes) { for (uint32_t i = 0; i < clauseCount; ++i) { // We're emitting this after the clause labels should have been fixed, so // the labels should not be "forward" references - ASSERT(!labels[i]->isForwardLabel()); + ASSERT(!labels[i]->isForward()); ASSERT(nodes[i]->isString()); UString::Rep* clause = static_cast<StringNode*>(nodes[i])->value().ustring().rep(); OffsetLocation location; location.branchOffset = labels[i]->offsetFrom(switchAddress); -#if ENABLE(CTI) +#if ENABLE(JIT) location.ctiOffset = 0; #endif jumpTable.offsetTable.add(clause, location); } } -void CodeGenerator::endSwitch(uint32_t clauseCount, RefPtr<LabelID>* labels, ExpressionNode** nodes, LabelID* defaultLabel, int32_t min, int32_t max) +void BytecodeGenerator::endSwitch(uint32_t clauseCount, RefPtr<Label>* labels, ExpressionNode** nodes, Label* defaultLabel, int32_t min, int32_t max) { SwitchInfo switchInfo = m_switchContextStack.last(); m_switchContextStack.removeLast(); if (switchInfo.switchType == SwitchInfo::SwitchImmediate) { - instructions()[switchInfo.opcodeOffset + 1] = m_codeBlock->immediateSwitchJumpTables.size(); - instructions()[switchInfo.opcodeOffset + 2] = defaultLabel->offsetFrom(switchInfo.opcodeOffset + 3); - - m_codeBlock->immediateSwitchJumpTables.append(SimpleJumpTable()); - SimpleJumpTable& jumpTable = m_codeBlock->immediateSwitchJumpTables.last(); + instructions()[switchInfo.bytecodeOffset + 1] = m_codeBlock->numberOfImmediateSwitchJumpTables(); + instructions()[switchInfo.bytecodeOffset + 2] = defaultLabel->offsetFrom(switchInfo.bytecodeOffset + 3); - prepareJumpTableForImmediateSwitch(jumpTable, switchInfo.opcodeOffset + 3, clauseCount, labels, nodes, min, max); + SimpleJumpTable& jumpTable = m_codeBlock->addImmediateSwitchJumpTable(); + prepareJumpTableForImmediateSwitch(jumpTable, switchInfo.bytecodeOffset + 3, clauseCount, labels, nodes, min, max); } else if (switchInfo.switchType == SwitchInfo::SwitchCharacter) { - instructions()[switchInfo.opcodeOffset + 1] = m_codeBlock->characterSwitchJumpTables.size(); - instructions()[switchInfo.opcodeOffset + 2] = defaultLabel->offsetFrom(switchInfo.opcodeOffset + 3); + instructions()[switchInfo.bytecodeOffset + 1] = m_codeBlock->numberOfCharacterSwitchJumpTables(); + instructions()[switchInfo.bytecodeOffset + 2] = defaultLabel->offsetFrom(switchInfo.bytecodeOffset + 3); - m_codeBlock->characterSwitchJumpTables.append(SimpleJumpTable()); - SimpleJumpTable& jumpTable = m_codeBlock->characterSwitchJumpTables.last(); - - prepareJumpTableForCharacterSwitch(jumpTable, switchInfo.opcodeOffset + 3, clauseCount, labels, nodes, min, max); + SimpleJumpTable& jumpTable = m_codeBlock->addCharacterSwitchJumpTable(); + prepareJumpTableForCharacterSwitch(jumpTable, switchInfo.bytecodeOffset + 3, clauseCount, labels, nodes, min, max); } else { ASSERT(switchInfo.switchType == SwitchInfo::SwitchString); - instructions()[switchInfo.opcodeOffset + 1] = m_codeBlock->stringSwitchJumpTables.size(); - instructions()[switchInfo.opcodeOffset + 2] = defaultLabel->offsetFrom(switchInfo.opcodeOffset + 3); - - m_codeBlock->stringSwitchJumpTables.append(StringJumpTable()); - StringJumpTable& jumpTable = m_codeBlock->stringSwitchJumpTables.last(); + instructions()[switchInfo.bytecodeOffset + 1] = m_codeBlock->numberOfStringSwitchJumpTables(); + instructions()[switchInfo.bytecodeOffset + 2] = defaultLabel->offsetFrom(switchInfo.bytecodeOffset + 3); - prepareJumpTableForStringSwitch(jumpTable, switchInfo.opcodeOffset + 3, clauseCount, labels, nodes); + StringJumpTable& jumpTable = m_codeBlock->addStringSwitchJumpTable(); + prepareJumpTableForStringSwitch(jumpTable, switchInfo.bytecodeOffset + 3, clauseCount, labels, nodes); } } +RegisterID* BytecodeGenerator::emitThrowExpressionTooDeepException() +{ + // It would be nice to do an even better job of identifying exactly where the expression is. + // And we could make the caller pass the node pointer in, if there was some way of getting + // that from an arbitrary node. However, calling emitExpressionInfo without any useful data + // is still good enough to get us an accurate line number. + emitExpressionInfo(0, 0, 0); + RegisterID* exception = emitNewError(newTemporary(), SyntaxError, jsString(globalData(), "Expression too deep")); + emitThrow(exception); + return exception; +} + } // namespace JSC diff --git a/JavaScriptCore/VM/CodeGenerator.h b/JavaScriptCore/bytecompiler/BytecodeGenerator.h index 75fc0a5..ceb5881 100644 --- a/JavaScriptCore/VM/CodeGenerator.h +++ b/JavaScriptCore/bytecompiler/BytecodeGenerator.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Apple Inc. All rights reserved. + * Copyright (C) 2008, 2009 Apple Inc. All rights reserved. * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca> * * Redistribution and use in source and binary forms, with or without @@ -27,20 +27,20 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef CodeGenerator_h -#define CodeGenerator_h +#ifndef BytecodeGenerator_h +#define BytecodeGenerator_h #include "CodeBlock.h" #include "HashTraits.h" #include "Instruction.h" -#include "LabelID.h" +#include "Label.h" #include "LabelScope.h" -#include "Machine.h" +#include "Interpreter.h" #include "RegisterID.h" #include "SegmentedVector.h" #include "SymbolTable.h" #include "Debugger.h" -#include "nodes.h" +#include "Nodes.h" #include <wtf/PassRefPtr.h> #include <wtf/Vector.h> @@ -51,7 +51,7 @@ namespace JSC { class ScopeNode; struct FinallyContext { - LabelID* finallyAddr; + Label* finallyAddr; RegisterID* retAddrDst; }; @@ -60,16 +60,17 @@ namespace JSC { FinallyContext finallyContext; }; - class CodeGenerator { + class BytecodeGenerator { public: typedef DeclarationStacks::VarStack VarStack; typedef DeclarationStacks::FunctionStack FunctionStack; static void setDumpsGeneratedCode(bool dumpsGeneratedCode); + static bool dumpsGeneratedCode(); - CodeGenerator(ProgramNode*, const Debugger*, const ScopeChain&, SymbolTable*, CodeBlock*, VarStack&, FunctionStack&); - CodeGenerator(FunctionBodyNode*, const Debugger*, const ScopeChain&, SymbolTable*, CodeBlock*); - CodeGenerator(EvalNode*, const Debugger*, const ScopeChain&, SymbolTable*, EvalCodeBlock*); + BytecodeGenerator(ProgramNode*, const Debugger*, const ScopeChain&, SymbolTable*, ProgramCodeBlock*); + BytecodeGenerator(FunctionBodyNode*, const Debugger*, const ScopeChain&, SymbolTable*, CodeBlock*); + BytecodeGenerator(EvalNode*, const Debugger*, const ScopeChain&, SymbolTable*, EvalCodeBlock*); JSGlobalData* globalData() const { return m_globalData; } const CommonIdentifiers& propertyNames() const { return *m_globalData->propertyNames; } @@ -118,6 +119,8 @@ namespace JSC { // Functions for handling of dst register + RegisterID* ignoredResult() { return &m_ignoredResultRegister; } + // Returns a place to write intermediate values of an operation // which reuses dst if it is safe to do so. RegisterID* tempDestination(RegisterID* dst) @@ -138,7 +141,7 @@ namespace JSC { RegisterID* destinationForAssignResult(RegisterID* dst) { - if (dst && dst != ignoredResult() && m_codeBlock->needsFullScopeChain) + if (dst && dst != ignoredResult() && m_codeBlock->needsFullScopeChain()) return dst->isTemporary() ? dst : newTemporary(); return 0; } @@ -150,7 +153,7 @@ namespace JSC { } PassRefPtr<LabelScope> newLabelScope(LabelScope::Type, const Identifier* = 0); - PassRefPtr<LabelID> newLabel(); + PassRefPtr<Label> newLabel(); // The emitNode functions are just syntactic sugar for calling // Node::emitCode. These functions accept a 0 for the register, @@ -161,11 +164,16 @@ namespace JSC { { // Node::emitCode assumes that dst, if provided, is either a local or a referenced temporary. ASSERT(!dst || dst == ignoredResult() || !dst->isTemporary() || dst->refCount()); - if (!m_codeBlock->lineInfo.size() || m_codeBlock->lineInfo.last().lineNumber != n->lineNo()) { + if (!m_codeBlock->numberOfLineInfos() || m_codeBlock->lastLineInfo().lineNumber != n->lineNo()) { LineInfo info = { instructions().size(), n->lineNo() }; - m_codeBlock->lineInfo.append(info); + m_codeBlock->addLineInfo(info); } - return n->emitCode(*this, dst); + if (m_emitNodeDepth >= s_maxEmitNodeDepth) + return emitThrowExpressionTooDeepException(); + ++m_emitNodeDepth; + RegisterID* r = n->emitBytecode(*this, dst); + --m_emitNodeDepth; + return r; } RegisterID* emitNode(Node* n) @@ -175,7 +183,7 @@ namespace JSC { void emitExpressionInfo(unsigned divot, unsigned startOffset, unsigned endOffset) { - divot -= m_codeBlock->sourceOffset; + divot -= m_codeBlock->sourceOffset(); if (divot > ExpressionRangeInfo::MaxDivot) { // Overflow has occurred, we can only give line number info for errors for this region divot = 0; @@ -199,12 +207,23 @@ namespace JSC { info.divotPoint = divot; info.startOffset = startOffset; info.endOffset = endOffset; - m_codeBlock->expressionInfo.append(info); + m_codeBlock->addExpressionInfo(info); + } + + void emitGetByIdExceptionInfo(OpcodeID opcodeID) + { + // Only op_construct and op_instanceof need exception info for + // a preceding op_get_by_id. + ASSERT(opcodeID == op_construct || opcodeID == op_instanceof); + GetByIdExceptionInfo info; + info.bytecodeOffset = instructions().size(); + info.isOpConstruct = (opcodeID == op_construct); + m_codeBlock->addGetByIdExceptionInfo(info); } ALWAYS_INLINE bool leftHandSideNeedsCopy(bool rightHasAssignments, bool rightIsPure) { - return (m_codeType != FunctionCode || m_codeBlock->needsFullScopeChain || rightHasAssignments) && !rightIsPure; + return (m_codeType != FunctionCode || m_codeBlock->needsFullScopeChain() || rightHasAssignments) && !rightIsPure; } ALWAYS_INLINE PassRefPtr<RegisterID> emitNodeForLeftHandSide(ExpressionNode* n, bool rightHasAssignments, bool rightIsPure) @@ -221,12 +240,11 @@ namespace JSC { RegisterID* emitLoad(RegisterID* dst, bool); RegisterID* emitLoad(RegisterID* dst, double); RegisterID* emitLoad(RegisterID* dst, const Identifier&); - RegisterID* emitLoad(RegisterID* dst, JSValue*); - RegisterID* emitLoad(RegisterID* dst, JSCell*); + RegisterID* emitLoad(RegisterID* dst, JSValuePtr); RegisterID* emitUnexpectedLoad(RegisterID* dst, bool); RegisterID* emitUnexpectedLoad(RegisterID* dst, double); - RegisterID* emitUnaryOp(OpcodeID, RegisterID* dst, RegisterID* src, ResultType); + RegisterID* emitUnaryOp(OpcodeID, RegisterID* dst, RegisterID* src); RegisterID* emitBinaryOp(OpcodeID, RegisterID* dst, RegisterID* src1, RegisterID* src2, OperandTypes); RegisterID* emitEqualityOp(OpcodeID, RegisterID* dst, RegisterID* src1, RegisterID* src2); RegisterID* emitUnaryNoDstOp(OpcodeID, RegisterID* src); @@ -240,19 +258,19 @@ namespace JSC { RegisterID* emitMove(RegisterID* dst, RegisterID* src); - RegisterID* emitToJSNumber(RegisterID* dst, RegisterID* src) { return emitUnaryOp(op_to_jsnumber, dst, src, ResultType::unknown()); } + RegisterID* emitToJSNumber(RegisterID* dst, RegisterID* src) { return emitUnaryOp(op_to_jsnumber, dst, src); } RegisterID* emitPreInc(RegisterID* srcDst); RegisterID* emitPreDec(RegisterID* srcDst); RegisterID* emitPostInc(RegisterID* dst, RegisterID* srcDst); RegisterID* emitPostDec(RegisterID* dst, RegisterID* srcDst); RegisterID* emitInstanceOf(RegisterID* dst, RegisterID* value, RegisterID* base, RegisterID* basePrototype); - RegisterID* emitTypeOf(RegisterID* dst, RegisterID* src) { return emitUnaryOp(op_typeof, dst, src, ResultType::unknown()); } + RegisterID* emitTypeOf(RegisterID* dst, RegisterID* src) { return emitUnaryOp(op_typeof, dst, src); } RegisterID* emitIn(RegisterID* dst, RegisterID* property, RegisterID* base) { return emitBinaryOp(op_in, dst, property, base, OperandTypes()); } RegisterID* emitResolve(RegisterID* dst, const Identifier& property); - RegisterID* emitGetScopedVar(RegisterID* dst, size_t skip, int index, JSValue* globalObject); - RegisterID* emitPutScopedVar(size_t skip, int index, RegisterID* value, JSValue* globalObject); + RegisterID* emitGetScopedVar(RegisterID* dst, size_t skip, int index, JSValuePtr globalObject); + RegisterID* emitPutScopedVar(size_t skip, int index, RegisterID* value, JSValuePtr globalObject); RegisterID* emitResolveBase(RegisterID* dst, const Identifier& property); RegisterID* emitResolveWithBase(RegisterID* baseDst, RegisterID* propDst, const Identifier& property); @@ -268,29 +286,29 @@ namespace JSC { RegisterID* emitPutGetter(RegisterID* base, const Identifier& property, RegisterID* value); RegisterID* emitPutSetter(RegisterID* base, const Identifier& property, RegisterID* value); - RegisterID* emitCall(RegisterID* dst, RegisterID* func, RegisterID* base, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset); - RegisterID* emitCallEval(RegisterID* dst, RegisterID* func, RegisterID* base, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset); + RegisterID* emitCall(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset); + RegisterID* emitCallEval(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset); RegisterID* emitReturn(RegisterID* src); RegisterID* emitEnd(RegisterID* src) { return emitUnaryNoDstOp(op_end, src); } RegisterID* emitConstruct(RegisterID* dst, RegisterID* func, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset); - PassRefPtr<LabelID> emitLabel(LabelID*); - PassRefPtr<LabelID> emitJump(LabelID* target); - PassRefPtr<LabelID> emitJumpIfTrue(RegisterID* cond, LabelID* target); - PassRefPtr<LabelID> emitJumpIfFalse(RegisterID* cond, LabelID* target); - PassRefPtr<LabelID> emitJumpScopes(LabelID* target, int targetScopeDepth); + PassRefPtr<Label> emitLabel(Label*); + PassRefPtr<Label> emitJump(Label* target); + PassRefPtr<Label> emitJumpIfTrue(RegisterID* cond, Label* target); + PassRefPtr<Label> emitJumpIfFalse(RegisterID* cond, Label* target); + PassRefPtr<Label> emitJumpScopes(Label* target, int targetScopeDepth); - PassRefPtr<LabelID> emitJumpSubroutine(RegisterID* retAddrDst, LabelID*); + PassRefPtr<Label> emitJumpSubroutine(RegisterID* retAddrDst, Label*); void emitSubroutineReturn(RegisterID* retAddrSrc); - RegisterID* emitGetPropertyNames(RegisterID* dst, RegisterID* base) { return emitUnaryOp(op_get_pnames, dst, base, ResultType::unknown()); } - RegisterID* emitNextPropertyName(RegisterID* dst, RegisterID* iter, LabelID* target); + RegisterID* emitGetPropertyNames(RegisterID* dst, RegisterID* base) { return emitUnaryOp(op_get_pnames, dst, base); } + RegisterID* emitNextPropertyName(RegisterID* dst, RegisterID* iter, Label* target); - RegisterID* emitCatch(RegisterID*, LabelID* start, LabelID* end); + RegisterID* emitCatch(RegisterID*, Label* start, Label* end); void emitThrow(RegisterID* exc) { emitUnaryNoDstOp(op_throw, exc); } - RegisterID* emitNewError(RegisterID* dst, ErrorType type, JSValue* message); + RegisterID* emitNewError(RegisterID* dst, ErrorType type, JSValuePtr message); void emitPushNewScope(RegisterID* dst, Identifier& property, RegisterID* value); RegisterID* emitPushScope(RegisterID* scope); @@ -300,17 +318,23 @@ namespace JSC { int scopeDepth() { return m_dynamicScopeDepth + m_finallyDepth; } - void pushFinallyContext(LabelID* target, RegisterID* returnAddrDst); + void pushFinallyContext(Label* target, RegisterID* returnAddrDst); void popFinallyContext(); LabelScope* breakTarget(const Identifier&); LabelScope* continueTarget(const Identifier&); void beginSwitch(RegisterID*, SwitchInfo::SwitchType); - void endSwitch(uint32_t clauseCount, RefPtr<LabelID>*, ExpressionNode**, LabelID* defaultLabel, int32_t min, int32_t range); + void endSwitch(uint32_t clauseCount, RefPtr<Label>*, ExpressionNode**, Label* defaultLabel, int32_t min, int32_t range); CodeType codeType() const { return m_codeType; } + void setRegeneratingForExceptionInfo(CodeBlock* originalCodeBlock) + { + m_regeneratingForExceptionInfo = true; + m_codeBlockBeingRegeneratedFrom = originalCodeBlock; + } + private: void emitOpcode(OpcodeID); void retrieveLastBinaryOp(int& dstIndex, int& src1Index, int& src2Index); @@ -318,14 +342,14 @@ namespace JSC { void rewindBinaryOp(); void rewindUnaryOp(); - PassRefPtr<LabelID> emitComplexJumpScopes(LabelID* target, ControlFlowContext* topScope, ControlFlowContext* bottomScope); + PassRefPtr<Label> emitComplexJumpScopes(Label* target, ControlFlowContext* topScope, ControlFlowContext* bottomScope); - struct JSValueHashTraits : HashTraits<JSValue*> { - static void constructDeletedValue(JSValue*& slot) { slot = JSImmediate::impossibleValue(); } - static bool isDeletedValue(JSValue* value) { return value == JSImmediate::impossibleValue(); } + struct JSValueHashTraits : HashTraits<JSValueEncodedAsPointer*> { + static void constructDeletedValue(JSValueEncodedAsPointer*& slot) { slot = JSValuePtr::encode(jsImpossibleValue()); } + static bool isDeletedValue(JSValueEncodedAsPointer* value) { return value == JSValuePtr::encode(jsImpossibleValue()); } }; - typedef HashMap<JSValue*, unsigned, PtrHash<JSValue*>, JSValueHashTraits> JSValueMap; + typedef HashMap<JSValueEncodedAsPointer*, unsigned, PtrHash<JSValueEncodedAsPointer*>, JSValueHashTraits> JSValueMap; struct IdentifierMapIndexHashTraits { typedef int TraitType; @@ -337,10 +361,10 @@ namespace JSC { }; typedef HashMap<RefPtr<UString::Rep>, int, IdentifierRepHash, HashTraits<RefPtr<UString::Rep> >, IdentifierMapIndexHashTraits> IdentifierMap; - typedef HashMap<double, JSValue*> NumberMap; + typedef HashMap<double, JSValuePtr> NumberMap; typedef HashMap<UString::Rep*, JSString*, IdentifierRepHash> IdentifierStringMap; - RegisterID* emitCall(OpcodeID, RegisterID*, RegisterID*, RegisterID*, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset); + RegisterID* emitCall(OpcodeID, RegisterID* dst, RegisterID* func, RegisterID* thisRegister, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset); RegisterID* newRegister(); @@ -387,17 +411,17 @@ namespace JSC { unsigned addConstant(FuncDeclNode*); unsigned addConstant(FuncExprNode*); unsigned addConstant(const Identifier&); - RegisterID* addConstant(JSValue*); - unsigned addUnexpectedConstant(JSValue*); + RegisterID* addConstant(JSValuePtr); + unsigned addUnexpectedConstant(JSValuePtr); unsigned addRegExp(RegExp*); - StructureID* addStructureID(); - Vector<Instruction>& instructions() { return m_codeBlock->instructions; } + Vector<Instruction>& instructions() { return m_codeBlock->instructions(); } SymbolTable& symbolTable() { return *m_symbolTable; } - Vector<HandlerInfo>& exceptionHandlers() { return m_codeBlock->exceptionHandlers; } bool shouldOptimizeLocals() { return (m_codeType != EvalCode) && !m_dynamicScopeDepth; } - bool canOptimizeNonLocals() { return (m_codeType == FunctionCode) && !m_dynamicScopeDepth && !m_codeBlock->usesEval; } + bool canOptimizeNonLocals() { return (m_codeType == FunctionCode) && !m_dynamicScopeDepth && !m_codeBlock->usesEval(); } + + RegisterID* emitThrowExpressionTooDeepException(); bool m_shouldEmitDebugHooks; bool m_shouldEmitProfileHooks; @@ -409,6 +433,7 @@ namespace JSC { CodeBlock* m_codeBlock; HashSet<RefPtr<UString::Rep>, IdentifierRepHash> m_functions; + RegisterID m_ignoredResultRegister; RegisterID m_thisRegister; RegisterID m_argumentsRegister; int m_activationRegisterIndex; @@ -416,18 +441,19 @@ namespace JSC { SegmentedVector<RegisterID, 512> m_parameters; SegmentedVector<RegisterID, 512> m_globals; SegmentedVector<LabelScope, 256> m_labelScopes; - SegmentedVector<LabelID, 256> m_labels; + SegmentedVector<Label, 256> m_labels; RefPtr<RegisterID> m_lastConstant; int m_finallyDepth; int m_dynamicScopeDepth; + int m_baseScopeDepth; CodeType m_codeType; Vector<ControlFlowContext> m_scopeContextStack; Vector<SwitchInfo> m_switchContextStack; - int m_nextGlobal; - int m_nextParameter; - int m_nextConstant; + int m_nextGlobalIndex; + int m_nextParameterIndex; + int m_nextConstantIndex; int m_globalVarStorageOffset; @@ -441,11 +467,14 @@ namespace JSC { OpcodeID m_lastOpcodeID; -#ifndef NDEBUG - static bool s_dumpsGeneratedCode; -#endif + unsigned m_emitNodeDepth; + + bool m_regeneratingForExceptionInfo; + CodeBlock* m_codeBlockBeingRegeneratedFrom; + + static const unsigned s_maxEmitNodeDepth = 10000; }; } -#endif // CodeGenerator_h +#endif // BytecodeGenerator_h diff --git a/JavaScriptCore/VM/LabelID.h b/JavaScriptCore/bytecompiler/Label.h index 6bcac26..0b3d038 100644 --- a/JavaScriptCore/VM/LabelID.h +++ b/JavaScriptCore/bytecompiler/Label.h @@ -26,8 +26,8 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef LabelID_h -#define LabelID_h +#ifndef Label_h +#define Label_h #include "CodeBlock.h" #include "Instruction.h" @@ -37,46 +37,28 @@ namespace JSC { - class LabelID { + class Label { public: - explicit LabelID(CodeBlock* codeBlock) + explicit Label(CodeBlock* codeBlock) : m_refCount(0) , m_location(invalidLocation) , m_codeBlock(codeBlock) { } - // It doesn't really make sense to copy a LabelID, but we need this copy - // constructor to support moving LabelIDs in a Vector. - - LabelID(const LabelID& other) - : m_refCount(other.m_refCount) - , m_location(other.m_location) - , m_codeBlock(other.m_codeBlock) - , m_unresolvedJumps(other.m_unresolvedJumps) - { - #ifndef NDEBUG - const_cast<LabelID&>(other).m_codeBlock = 0; - #endif - } - void setLocation(unsigned location) { - ASSERT(m_codeBlock); m_location = location; unsigned size = m_unresolvedJumps.size(); for (unsigned i = 0; i < size; ++i) { unsigned j = m_unresolvedJumps[i]; - m_codeBlock->instructions[j].u.operand = m_location - j; + m_codeBlock->instructions()[j].u.operand = m_location - j; } - - m_codeBlock->labels.add(location); } int offsetFrom(int location) const { - ASSERT(m_codeBlock); if (m_location == invalidLocation) { m_unresolvedJumps.append(location); return 0; @@ -84,23 +66,15 @@ namespace JSC { return m_location - location; } - void ref() - { - ++m_refCount; - } - + void ref() { ++m_refCount; } void deref() { --m_refCount; ASSERT(m_refCount >= 0); } + int refCount() const { return m_refCount; } - int refCount() const - { - return m_refCount; - } - - bool isForwardLabel() const { return m_location == invalidLocation; } + bool isForward() const { return m_location == invalidLocation; } private: typedef Vector<int, 8> JumpVector; @@ -115,4 +89,4 @@ namespace JSC { } // namespace JSC -#endif // LabelID_h +#endif // Label_h diff --git a/JavaScriptCore/kjs/LabelScope.h b/JavaScriptCore/bytecompiler/LabelScope.h index 8c30be5..cc21fff 100644 --- a/JavaScriptCore/kjs/LabelScope.h +++ b/JavaScriptCore/bytecompiler/LabelScope.h @@ -30,7 +30,7 @@ #define LabelScope_h #include <wtf/PassRefPtr.h> -#include "LabelID.h" +#include "Label.h" namespace JSC { @@ -40,7 +40,7 @@ namespace JSC { public: enum Type { Loop, Switch, NamedLabel }; - LabelScope(Type type, const Identifier* name, int scopeDepth, PassRefPtr<LabelID> breakTarget, PassRefPtr<LabelID> continueTarget) + LabelScope(Type type, const Identifier* name, int scopeDepth, PassRefPtr<Label> breakTarget, PassRefPtr<Label> continueTarget) : m_refCount(0) , m_type(type) , m_name(name) @@ -50,19 +50,6 @@ namespace JSC { { } - // It doesn't really make sense to copy a LabelScope, but we need this copy - // constructor to support moving LabelScopes in a Vector. - - LabelScope(const LabelScope& other) - : m_refCount(other.m_refCount) - , m_type(other.m_type) - , m_name(other.m_name) - , m_scopeDepth(other.m_scopeDepth) - , m_breakTarget(other.m_breakTarget) - , m_continueTarget(other.m_continueTarget) - { - } - void ref() { ++m_refCount; } void deref() { @@ -71,8 +58,8 @@ namespace JSC { } int refCount() const { return m_refCount; } - LabelID* breakTarget() const { return m_breakTarget.get(); } - LabelID* continueTarget() const { return m_continueTarget.get(); } + Label* breakTarget() const { return m_breakTarget.get(); } + Label* continueTarget() const { return m_continueTarget.get(); } Type type() const { return m_type; } const Identifier* name() const { return m_name; } @@ -83,8 +70,8 @@ namespace JSC { Type m_type; const Identifier* m_name; int m_scopeDepth; - RefPtr<LabelID> m_breakTarget; - RefPtr<LabelID> m_continueTarget; + RefPtr<Label> m_breakTarget; + RefPtr<Label> m_continueTarget; }; } // namespace JSC diff --git a/JavaScriptCore/VM/RegisterID.h b/JavaScriptCore/bytecompiler/RegisterID.h index bff653b..0223c2a 100644 --- a/JavaScriptCore/VM/RegisterID.h +++ b/JavaScriptCore/bytecompiler/RegisterID.h @@ -107,8 +107,6 @@ namespace JSC { #endif }; - inline RegisterID* ignoredResult() { return reinterpret_cast<RegisterID*>(1); } - } // namespace JSC namespace WTF { diff --git a/JavaScriptCore/VM/SegmentedVector.h b/JavaScriptCore/bytecompiler/SegmentedVector.h index bbab04f..bbab04f 100644 --- a/JavaScriptCore/VM/SegmentedVector.h +++ b/JavaScriptCore/bytecompiler/SegmentedVector.h diff --git a/JavaScriptCore/kjs/config.h b/JavaScriptCore/config.h index 53bc0a9..a85178c 100644 --- a/JavaScriptCore/kjs/config.h +++ b/JavaScriptCore/config.h @@ -25,11 +25,6 @@ #include <wtf/Platform.h> -#if PLATFORM(ANDROID) - -#define ANDROID_MOBILE // change can be merged back to WebKit.org for MOBILE -#endif - #if PLATFORM(WIN_OS) // If we don't define these, they get defined in windef.h. @@ -37,7 +32,7 @@ #define max max #define min min -#if !COMPILER(MSVC7) +#if !COMPILER(MSVC7) && !PLATFORM(WIN_CE) // We need to define this before the first #include of stdlib.h or it won't contain rand_s. #ifndef _CRT_RAND_S #define _CRT_RAND_S @@ -68,3 +63,4 @@ #if !PLATFORM(QT) && !PLATFORM(WX) #include <wtf/DisallowCType.h> #endif + diff --git a/JavaScriptCore/kjs/create_hash_table b/JavaScriptCore/create_hash_table index 829a024..3bd9f76 100755 --- a/JavaScriptCore/kjs/create_hash_table +++ b/JavaScriptCore/create_hash_table @@ -5,9 +5,7 @@ # (c) 2000-2002 by Harri Porten <porten@kde.org> and # David Faure <faure@kde.org> # Modified (c) 2004 by Nikolas Zimmermann <wildfox@kde.org> -# Copyright (C) 2007 Apple Inc. All rights reserved. -# -# Part of the KJS library. +# Copyright (C) 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 Lesser General Public @@ -30,7 +28,7 @@ my $file = $ARGV[0]; shift; my $includelookup = 0; -# Use -i as second argument to make it include "lookup.h" +# Use -i as second argument to make it include "Lookup.h" $includelookup = 1 if (defined($ARGV[0]) && $ARGV[0] eq "-i"); # Use -n as second argument to make it use the third argument as namespace parameter ie. -n KDOM @@ -46,9 +44,12 @@ my @hashes = (); my $inside = 0; my $name; -my $size; +my $pefectHashSize; +my $compactSize; +my $compactHashSizeMask; my $banner = 0; -sub calcSize(); +sub calcPerfectHashSize(); +sub calcCompactHashSize(); sub output(); sub jsc_ucfirst($); sub hashValue($); @@ -65,7 +66,8 @@ while (<IN>) { print STDERR "WARNING: \@begin without table name, skipping $_\n"; } } elsif (/^\@end\s*$/ && $inside) { - calcSize(); + calcPerfectHashSize(); + calcCompactHashSize(); output(); @keys = (); @@ -116,23 +118,23 @@ sub jsc_ucfirst($) sub ceilingToPowerOf2 { - my ($size) = @_; + my ($pefectHashSize) = @_; my $powerOf2 = 1; - while ($size > $powerOf2) { + while ($pefectHashSize > $powerOf2) { $powerOf2 <<= 1; } return $powerOf2; } -sub calcSize() +sub calcPerfectHashSize() { tableSizeLoop: - for ($size = ceilingToPowerOf2(scalar @keys); ; $size += $size) { + for ($pefectHashSize = ceilingToPowerOf2(scalar @keys); ; $pefectHashSize += $pefectHashSize) { my @table = (); foreach my $key (@keys) { - my $h = hashValue($key) % $size; + my $h = hashValue($key) % $pefectHashSize; next tableSizeLoop if $table[$h]; $table[$h] = 1; } @@ -145,6 +147,36 @@ sub leftShift($$) { return (($value << $distance) & 0xFFFFFFFF); } +sub calcCompactHashSize() +{ + my @table = (); + my @links = (); + my $compactHashSize = ceilingToPowerOf2(2 * @keys); + $compactHashSizeMask = $compactHashSize - 1; + $compactSize = $compactHashSize; + my $collisions = 0; + my $maxdepth = 0; + my $i = 0; + foreach my $key (@keys) { + my $depth = 0; + my $h = hashValue($key) % $compactHashSize; + while (defined($table[$h])) { + if (defined($links[$h])) { + $h = $links[$h]; + $depth++; + } else { + $collisions++; + $links[$h] = $compactSize; + $h = $compactSize; + $compactSize++; + } + } + $table[$h] = $i; + $i++; + $maxdepth = $depth if ( $depth > $maxdepth); + } +} + # Paul Hsieh's SuperFastHash # http://www.azillionmonkeys.com/qed/hash.html # Ported from UString.. @@ -207,7 +239,7 @@ sub output() { my $nameEntries = "${name}Values"; $nameEntries =~ s/:/_/g; - print "\n#include \"lookup.h\"\n" if ($includelookup); + print "\n#include \"Lookup.h\"\n" if ($includelookup); if ($useNameSpace) { print "\nnamespace ${useNameSpace} {\n"; print "\nusing namespace JSC;\n"; @@ -236,7 +268,11 @@ sub output() { } print " { 0, 0, 0, 0 }\n"; print "};\n\n"; - print "extern const struct HashTable $name = "; - print "\{ ", $size - 1, ", $nameEntries, 0 \};\n\n"; + print "extern const struct HashTable $name =\n"; + print "#if ENABLE(PERFECT_HASH_SIZE)\n"; + print " \{ ", $pefectHashSize - 1, ", $nameEntries, 0 \};\n"; + print "#else\n"; + print " \{ $compactSize, $compactHashSizeMask, $nameEntries, 0 \};\n"; + print "#endif\n\n"; print "} // namespace\n"; } diff --git a/JavaScriptCore/debugger/Debugger.cpp b/JavaScriptCore/debugger/Debugger.cpp index a52a542..da1cb3d 100644 --- a/JavaScriptCore/debugger/Debugger.cpp +++ b/JavaScriptCore/debugger/Debugger.cpp @@ -23,6 +23,8 @@ #include "Debugger.h" #include "JSGlobalObject.h" +#include "Interpreter.h" +#include "Parser.h" namespace JSC { @@ -51,4 +53,18 @@ void Debugger::detach(JSGlobalObject* globalObject) globalObject->setDebugger(0); } +JSValuePtr evaluateInGlobalCallFrame(const UString& script, JSValuePtr& exception, JSGlobalObject* globalObject) +{ + CallFrame* globalCallFrame = globalObject->globalExec(); + + int errLine; + UString errMsg; + SourceCode source = makeSource(script); + RefPtr<EvalNode> evalNode = globalObject->globalData()->parser->parse<EvalNode>(globalCallFrame, globalObject->debugger(), source, &errLine, &errMsg); + if (!evalNode) + return Error::create(globalCallFrame, SyntaxError, errMsg, errLine, source.provider()->asID(), source.provider()->url()); + + return globalObject->globalData()->interpreter->execute(evalNode.get(), globalCallFrame, globalObject, globalCallFrame->scopeChain(), &exception); +} + } // namespace JSC diff --git a/JavaScriptCore/debugger/Debugger.h b/JavaScriptCore/debugger/Debugger.h index 4a6a9b3..0559898 100644 --- a/JavaScriptCore/debugger/Debugger.h +++ b/JavaScriptCore/debugger/Debugger.h @@ -22,7 +22,7 @@ #ifndef Debugger_h #define Debugger_h -#include "protect.h" +#include "Protect.h" namespace JSC { @@ -54,6 +54,10 @@ namespace JSC { HashSet<JSGlobalObject*> m_globalObjects; }; + // This method exists only for backwards compatibility with existing + // WebScriptDebugger clients + JSValuePtr evaluateInGlobalCallFrame(const UString&, JSValuePtr& exception, JSGlobalObject*); + } // namespace JSC #endif // Debugger_h diff --git a/JavaScriptCore/debugger/DebuggerActivation.cpp b/JavaScriptCore/debugger/DebuggerActivation.cpp new file mode 100644 index 0000000..9d4dcbf --- /dev/null +++ b/JavaScriptCore/debugger/DebuggerActivation.cpp @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2008 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "DebuggerActivation.h" + +#include "JSActivation.h" + +namespace JSC { + +DebuggerActivation::DebuggerActivation(JSObject* activation) + : JSObject(DebuggerActivation::createStructure(jsNull())) +{ + ASSERT(activation); + ASSERT(activation->isActivationObject()); + m_activation = static_cast<JSActivation*>(activation); +} + +void DebuggerActivation::mark() +{ + JSObject::mark(); + if (m_activation && !m_activation->marked()) + m_activation->mark(); +} + +UString DebuggerActivation::className() const +{ + return m_activation->className(); +} + +bool DebuggerActivation::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) +{ + return m_activation->getOwnPropertySlot(exec, propertyName, slot); +} + +void DebuggerActivation::put(ExecState* exec, const Identifier& propertyName, JSValuePtr value, PutPropertySlot& slot) +{ + m_activation->put(exec, propertyName, value, slot); +} + +void DebuggerActivation::putWithAttributes(ExecState* exec, const Identifier& propertyName, JSValuePtr value, unsigned attributes) +{ + m_activation->putWithAttributes(exec, propertyName, value, attributes); +} + +bool DebuggerActivation::deleteProperty(ExecState* exec, const Identifier& propertyName) +{ + return m_activation->deleteProperty(exec, propertyName); +} + +void DebuggerActivation::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames) +{ + m_activation->getPropertyNames(exec, propertyNames); +} + +bool DebuggerActivation::getPropertyAttributes(JSC::ExecState* exec, const Identifier& propertyName, unsigned& attributes) const +{ + return m_activation->getPropertyAttributes(exec, propertyName, attributes); +} + +void DebuggerActivation::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunction) +{ + m_activation->defineGetter(exec, propertyName, getterFunction); +} + +void DebuggerActivation::defineSetter(ExecState* exec, const Identifier& propertyName, JSObject* setterFunction) +{ + m_activation->defineSetter(exec, propertyName, setterFunction); +} + +JSValuePtr DebuggerActivation::lookupGetter(ExecState* exec, const Identifier& propertyName) +{ + return m_activation->lookupGetter(exec, propertyName); +} + +JSValuePtr DebuggerActivation::lookupSetter(ExecState* exec, const Identifier& propertyName) +{ + return m_activation->lookupSetter(exec, propertyName); +} + +} // namespace JSC diff --git a/JavaScriptCore/debugger/DebuggerActivation.h b/JavaScriptCore/debugger/DebuggerActivation.h new file mode 100644 index 0000000..c2ede4f --- /dev/null +++ b/JavaScriptCore/debugger/DebuggerActivation.h @@ -0,0 +1,63 @@ +/* + * 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 DebuggerActivation_h +#define DebuggerActivation_h + +#include "JSObject.h" + +namespace JSC { + + class JSActivation; + + class DebuggerActivation : public JSObject { + public: + DebuggerActivation(JSObject*); + + virtual void mark(); + virtual UString className() const; + virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); + virtual void put(ExecState*, const Identifier& propertyName, JSValuePtr, PutPropertySlot&); + virtual void putWithAttributes(ExecState*, const Identifier& propertyName, JSValuePtr, unsigned attributes); + virtual bool deleteProperty(ExecState*, const Identifier& propertyName); + virtual void getPropertyNames(ExecState*, PropertyNameArray&); + virtual bool getPropertyAttributes(ExecState*, const Identifier& propertyName, unsigned& attributes) const; + virtual void defineGetter(ExecState*, const Identifier& propertyName, JSObject* getterFunction); + virtual void defineSetter(ExecState*, const Identifier& propertyName, JSObject* setterFunction); + virtual JSValuePtr lookupGetter(ExecState*, const Identifier& propertyName); + virtual JSValuePtr lookupSetter(ExecState*, const Identifier& propertyName); + + static PassRefPtr<Structure> createStructure(JSValuePtr prototype) + { + return Structure::create(prototype, TypeInfo(ObjectType)); + } + + private: + JSActivation* m_activation; + }; + +} // namespace JSC + +#endif // DebuggerActivation_h diff --git a/JavaScriptCore/debugger/DebuggerCallFrame.cpp b/JavaScriptCore/debugger/DebuggerCallFrame.cpp index ae62cd3..27b824c 100644 --- a/JavaScriptCore/debugger/DebuggerCallFrame.cpp +++ b/JavaScriptCore/debugger/DebuggerCallFrame.cpp @@ -31,7 +31,7 @@ #include "JSFunction.h" #include "CodeBlock.h" -#include "Machine.h" +#include "Interpreter.h" #include "Parser.h" namespace JSC { @@ -60,11 +60,10 @@ JSObject* DebuggerCallFrame::thisObject() const if (!m_callFrame->codeBlock()) return 0; - // FIXME: Why is it safe to assume this is an object? return asObject(m_callFrame->thisValue()); } -JSValue* DebuggerCallFrame::evaluate(const UString& script, JSValue*& exception) const +JSValuePtr DebuggerCallFrame::evaluate(const UString& script, JSValuePtr& exception) const { if (!m_callFrame->codeBlock()) return noValue(); @@ -76,7 +75,7 @@ JSValue* DebuggerCallFrame::evaluate(const UString& script, JSValue*& exception) if (!evalNode) return Error::create(m_callFrame, SyntaxError, errMsg, errLine, source.provider()->asID(), source.provider()->url()); - return m_callFrame->scopeChain()->globalData->machine->execute(evalNode.get(), m_callFrame, thisObject(), m_callFrame->scopeChain(), &exception); + return m_callFrame->scopeChain()->globalData->interpreter->execute(evalNode.get(), m_callFrame, thisObject(), m_callFrame->scopeChain(), &exception); } } // namespace JSC diff --git a/JavaScriptCore/debugger/DebuggerCallFrame.h b/JavaScriptCore/debugger/DebuggerCallFrame.h index 8326b20..cdf4965 100644 --- a/JavaScriptCore/debugger/DebuggerCallFrame.h +++ b/JavaScriptCore/debugger/DebuggerCallFrame.h @@ -29,7 +29,7 @@ #ifndef DebuggerCallFrame_h #define DebuggerCallFrame_h -#include "ExecState.h" +#include "CallFrame.h" namespace JSC { @@ -43,7 +43,7 @@ namespace JSC { { } - DebuggerCallFrame(CallFrame* callFrame, JSValue* exception) + DebuggerCallFrame(CallFrame* callFrame, JSValuePtr exception) : m_callFrame(callFrame) , m_exception(exception) { @@ -54,12 +54,12 @@ namespace JSC { const UString* functionName() const; Type type() const; JSObject* thisObject() const; - JSValue* evaluate(const UString&, JSValue*& exception) const; - JSValue* exception() const { return m_exception; } + JSValuePtr evaluate(const UString&, JSValuePtr& exception) const; + JSValuePtr exception() const { return m_exception; } private: CallFrame* m_callFrame; - JSValue* m_exception; + JSValuePtr m_exception; }; } // namespace JSC diff --git a/JavaScriptCore/docs/make-bytecode-docs.pl b/JavaScriptCore/docs/make-bytecode-docs.pl index 0be22eb..9494d1b 100755 --- a/JavaScriptCore/docs/make-bytecode-docs.pl +++ b/JavaScriptCore/docs/make-bytecode-docs.pl @@ -10,9 +10,9 @@ my @undocumented = (); print OUTPUT "<style>p code \{ font-size: 14px; \}</style>\n"; while (<MACHINE>) { - if (/^ *BEGIN_OPCODE/) { + if (/^ *DEFINE_OPCODE/) { chomp; - s/^ *BEGIN_OPCODE\(op_//; + s/^ *DEFINE_OPCODE\(op_//; s/\).*$//; my $opcode = $_; $_ = <MACHINE>; diff --git a/JavaScriptCore/runtime/ExecState.cpp b/JavaScriptCore/interpreter/CallFrame.cpp index 0144c14..1c74280 100644 --- a/JavaScriptCore/runtime/ExecState.cpp +++ b/JavaScriptCore/interpreter/CallFrame.cpp @@ -24,15 +24,15 @@ */ #include "config.h" -#include "ExecState.h" +#include "CallFrame.h" #include "CodeBlock.h" namespace JSC { -JSValue* CallFrame::thisValue() +JSValuePtr CallFrame::thisValue() { - return this[codeBlock()->thisRegister].jsValue(this); + return this[codeBlock()->thisRegister()].jsValue(this); } } diff --git a/JavaScriptCore/runtime/ExecState.h b/JavaScriptCore/interpreter/CallFrame.h index f1891bb..d6b9b79 100644 --- a/JavaScriptCore/runtime/ExecState.h +++ b/JavaScriptCore/interpreter/CallFrame.h @@ -20,19 +20,18 @@ * */ -#ifndef ExecState_h -#define ExecState_h - -// FIXME: Rename this file to CallFrame.h. +#ifndef CallFrame_h +#define CallFrame_h #include "JSGlobalData.h" -#include "Machine.h" +#include "RegisterFile.h" #include "ScopeChain.h" namespace JSC { class Arguments; class JSActivation; + class Interpreter; // Represents the current state of script execution. // Passed as the first argument to most functions. @@ -42,7 +41,7 @@ namespace JSC { CodeBlock* codeBlock() const { return this[RegisterFile::CodeBlock].Register::codeBlock(); } ScopeChainNode* scopeChain() const { return this[RegisterFile::ScopeChain].Register::scopeChain(); } - JSValue* thisValue(); + JSValuePtr thisValue(); // Global object in which execution began. JSGlobalObject* dynamicGlobalObject(); @@ -74,15 +73,15 @@ namespace JSC { // pointer, so these are inefficient, and should be used sparingly in new code. // But they're used in many places in legacy code, so they're not going away any time soon. - void setException(JSValue* exception) { globalData().exception = exception; } + void setException(JSValuePtr exception) { globalData().exception = exception; } void clearException() { globalData().exception = noValue(); } - JSValue* exception() const { return globalData().exception; } - JSValue** exceptionSlot() { return &globalData().exception; } - bool hadException() const { return !!globalData().exception; } + JSValuePtr exception() const { return globalData().exception; } + JSValuePtr* exceptionSlot() { return &globalData().exception; } + bool hadException() const { return globalData().exception; } const CommonIdentifiers& propertyNames() const { return *globalData().propertyNames; } const ArgList& emptyList() const { return *globalData().emptyList; } - Machine* machine() { return globalData().machine; } + Interpreter* interpreter() { return globalData().interpreter; } Heap* heap() { return &globalData().heap; } static const HashTable* arrayTable(CallFrame* callFrame) { return callFrame->globalData().arrayTable; } @@ -97,7 +96,7 @@ namespace JSC { friend class Arguments; friend class JSActivation; friend class JSGlobalObject; - friend class Machine; + friend class Interpreter; static CallFrame* create(Register* callFrameBase) { return static_cast<CallFrame*>(callFrameBase); } Register* registers() { return this; } @@ -125,7 +124,7 @@ namespace JSC { setCodeBlock(codeBlock); setScopeChain(scopeChain); setCallerFrame(callerFrame); - this[RegisterFile::ReturnPC] = vPC; + this[RegisterFile::ReturnPC] = vPC; // This is either an Instruction* or a pointer into JIT generated code stored as an Instruction*. this[RegisterFile::ReturnValueRegister] = returnValueRegister; setArgumentCount(argc); // original argument count (for the sake of the "arguments" object) setCallee(function); @@ -145,4 +144,4 @@ namespace JSC { } // namespace JSC -#endif // ExecState_h +#endif // CallFrame_h diff --git a/JavaScriptCore/VM/Machine.cpp b/JavaScriptCore/interpreter/Interpreter.cpp index a605d25..135c42f 100644 --- a/JavaScriptCore/VM/Machine.cpp +++ b/JavaScriptCore/interpreter/Interpreter.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Apple Inc. All rights reserved. + * Copyright (C) 2008, 2009 Apple Inc. All rights reserved. * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca> * * Redistribution and use in source and binary forms, with or without @@ -28,17 +28,19 @@ */ #include "config.h" -#include "Machine.h" +#include "Interpreter.h" #include "Arguments.h" #include "BatchedTransitionOptimizer.h" #include "CodeBlock.h" #include "DebuggerCallFrame.h" +#include "EvalCodeCache.h" #include "ExceptionHelpers.h" -#include "ExecState.h" +#include "CallFrame.h" #include "GlobalEvalFunction.h" #include "JSActivation.h" #include "JSArray.h" +#include "JSByteArray.h" #include "JSFunction.h" #include "JSNotAnObject.h" #include "JSPropertyNameIterator.h" @@ -50,14 +52,18 @@ #include "RegExpObject.h" #include "RegExpPrototype.h" #include "Register.h" -#include "collector.h" +#include "Collector.h" #include "Debugger.h" -#include "operations.h" +#include "Operations.h" #include "SamplingTool.h" #include <stdio.h> -#if ENABLE(CTI) -#include "CTI.h" +#if ENABLE(JIT) +#include "JIT.h" +#endif + +#if ENABLE(ASSEMBLER) +#include "AssemblerBuffer.h" #endif #if PLATFORM(DARWIN) @@ -83,107 +89,42 @@ namespace JSC { // Preferred number of milliseconds between each timeout check static const int preferredScriptCheckTimeInterval = 1000; -#if HAVE(COMPUTED_GOTO) -static void* op_throw_end_indirect; -static void* op_call_indirect; -#endif - -#if ENABLE(CTI) - -static ALWAYS_INLINE Instruction* vPCForPC(CodeBlock* codeBlock, void* pc) +static ALWAYS_INLINE unsigned bytecodeOffsetForPC(CallFrame* callFrame, CodeBlock* codeBlock, void* pc) { - if (pc >= codeBlock->instructions.begin() && pc < codeBlock->instructions.end()) - return static_cast<Instruction*>(pc); - - ASSERT(codeBlock->ctiReturnAddressVPCMap.contains(pc)); - unsigned vPCIndex = codeBlock->ctiReturnAddressVPCMap.get(pc); - return codeBlock->instructions.begin() + vPCIndex; -} - -#else // ENABLE(CTI) - -static ALWAYS_INLINE Instruction* vPCForPC(CodeBlock*, void* pc) -{ - return static_cast<Instruction*>(pc); +#if ENABLE(JIT) + return codeBlock->getBytecodeIndex(callFrame, pc); +#else + UNUSED_PARAM(callFrame); + return static_cast<Instruction*>(pc) - codeBlock->instructions().begin(); +#endif } -#endif // ENABLE(CTI) - // Returns the depth of the scope chain within a given call frame. static int depth(CodeBlock* codeBlock, ScopeChain& sc) { - if (!codeBlock->needsFullScopeChain) + if (!codeBlock->needsFullScopeChain()) return 0; - int scopeDepth = 0; - ScopeChainIterator iter = sc.begin(); - ScopeChainIterator end = sc.end(); - while (!(*iter)->isObject(&JSActivation::info)) { - ++iter; - if (iter == end) - break; - ++scopeDepth; - } - return scopeDepth; + return sc.localDepth(); } -// FIXME: This operation should be called "getNumber", not "isNumber" (as it is in JSValue.h). -// FIXME: There's no need to have a "slow" version of this. All versions should be fast. -static ALWAYS_INLINE bool fastIsNumber(JSValue* value, double& arg) +static inline bool jsLess(CallFrame* callFrame, JSValuePtr v1, JSValuePtr v2) { - if (JSImmediate::isNumber(value)) - arg = JSImmediate::getTruncatedInt32(value); - else if (LIKELY(!JSImmediate::isImmediate(value)) && LIKELY(Heap::isNumber(asCell(value)))) - arg = asNumberCell(value)->value(); - else - return false; - return true; -} - -// FIXME: Why doesn't JSValue*::toInt32 have the Heap::isNumber optimization? -static bool fastToInt32(JSValue* value, int32_t& arg) -{ - if (JSImmediate::isNumber(value)) - arg = JSImmediate::getTruncatedInt32(value); - else if (LIKELY(!JSImmediate::isImmediate(value)) && LIKELY(Heap::isNumber(asCell(value)))) - arg = asNumberCell(value)->toInt32(); - else - return false; - return true; -} - -static ALWAYS_INLINE bool fastToUInt32(JSValue* value, uint32_t& arg) -{ - if (JSImmediate::isNumber(value)) { - if (JSImmediate::getTruncatedUInt32(value, arg)) - return true; - bool scratch; - arg = toUInt32SlowCase(JSImmediate::getTruncatedInt32(value), scratch); - return true; - } else if (!JSImmediate::isImmediate(value) && Heap::isNumber(asCell(value))) - arg = asNumberCell(value)->toUInt32(); - else - return false; - return true; -} - -static inline bool jsLess(CallFrame* callFrame, JSValue* v1, JSValue* v2) -{ - if (JSImmediate::areBothImmediateNumbers(v1, v2)) - return JSImmediate::getTruncatedInt32(v1) < JSImmediate::getTruncatedInt32(v2); + if (JSValuePtr::areBothInt32Fast(v1, v2)) + return v1.getInt32Fast() < v2.getInt32Fast(); double n1; double n2; - if (fastIsNumber(v1, n1) && fastIsNumber(v2, n2)) + if (v1.getNumber(n1) && v2.getNumber(n2)) return n1 < n2; - Machine* machine = callFrame->machine(); - if (machine->isJSString(v1) && machine->isJSString(v2)) + Interpreter* interpreter = callFrame->interpreter(); + if (interpreter->isJSString(v1) && interpreter->isJSString(v2)) return asString(v1)->value() < asString(v2)->value(); - JSValue* p1; - JSValue* p2; - bool wasNotString1 = v1->getPrimitiveNumber(callFrame, n1, p1); - bool wasNotString2 = v2->getPrimitiveNumber(callFrame, n2, p2); + JSValuePtr p1; + JSValuePtr p2; + bool wasNotString1 = v1.getPrimitiveNumber(callFrame, n1, p1); + bool wasNotString2 = v2.getPrimitiveNumber(callFrame, n2, p2); if (wasNotString1 | wasNotString2) return n1 < n2; @@ -191,24 +132,24 @@ static inline bool jsLess(CallFrame* callFrame, JSValue* v1, JSValue* v2) return asString(p1)->value() < asString(p2)->value(); } -static inline bool jsLessEq(CallFrame* callFrame, JSValue* v1, JSValue* v2) +static inline bool jsLessEq(CallFrame* callFrame, JSValuePtr v1, JSValuePtr v2) { - if (JSImmediate::areBothImmediateNumbers(v1, v2)) - return JSImmediate::getTruncatedInt32(v1) <= JSImmediate::getTruncatedInt32(v2); + if (JSValuePtr::areBothInt32Fast(v1, v2)) + return v1.getInt32Fast() <= v2.getInt32Fast(); double n1; double n2; - if (fastIsNumber(v1, n1) && fastIsNumber(v2, n2)) + if (v1.getNumber(n1) && v2.getNumber(n2)) return n1 <= n2; - Machine* machine = callFrame->machine(); - if (machine->isJSString(v1) && machine->isJSString(v2)) + Interpreter* interpreter = callFrame->interpreter(); + if (interpreter->isJSString(v1) && interpreter->isJSString(v2)) return !(asString(v2)->value() < asString(v1)->value()); - JSValue* p1; - JSValue* p2; - bool wasNotString1 = v1->getPrimitiveNumber(callFrame, n1, p1); - bool wasNotString2 = v2->getPrimitiveNumber(callFrame, n2, p2); + JSValuePtr p1; + JSValuePtr p2; + bool wasNotString1 = v1.getPrimitiveNumber(callFrame, n1, p1); + bool wasNotString2 = v2.getPrimitiveNumber(callFrame, n2, p2); if (wasNotString1 | wasNotString2) return n1 <= n2; @@ -216,20 +157,20 @@ static inline bool jsLessEq(CallFrame* callFrame, JSValue* v1, JSValue* v2) return !(asString(p2)->value() < asString(p1)->value()); } -static NEVER_INLINE JSValue* jsAddSlowCase(CallFrame* callFrame, JSValue* v1, JSValue* v2) +static NEVER_INLINE JSValuePtr jsAddSlowCase(CallFrame* callFrame, JSValuePtr v1, JSValuePtr v2) { // exception for the Date exception in defaultValue() - JSValue* p1 = v1->toPrimitive(callFrame); - JSValue* p2 = v2->toPrimitive(callFrame); + JSValuePtr p1 = v1.toPrimitive(callFrame); + JSValuePtr p2 = v2.toPrimitive(callFrame); - if (p1->isString() || p2->isString()) { - RefPtr<UString::Rep> value = concatenate(p1->toString(callFrame).rep(), p2->toString(callFrame).rep()); + if (p1.isString() || p2.isString()) { + RefPtr<UString::Rep> value = concatenate(p1.toString(callFrame).rep(), p2.toString(callFrame).rep()); if (!value) return throwOutOfMemoryError(callFrame); return jsString(callFrame, value.release()); } - return jsNumber(callFrame, p1->toNumber(callFrame) + p2->toNumber(callFrame)); + return jsNumber(callFrame, p1.toNumber(callFrame) + p2.toNumber(callFrame)); } // Fast-path choices here are based on frequency data from SunSpider: @@ -241,17 +182,17 @@ static NEVER_INLINE JSValue* jsAddSlowCase(CallFrame* callFrame, JSValue* v1, JS // 13962 Add case: 5 3 // 4000 Add case: 3 5 -static ALWAYS_INLINE JSValue* jsAdd(CallFrame* callFrame, JSValue* v1, JSValue* v2) +static ALWAYS_INLINE JSValuePtr jsAdd(CallFrame* callFrame, JSValuePtr v1, JSValuePtr v2) { double left; double right = 0.0; - bool rightIsNumber = fastIsNumber(v2, right); - if (rightIsNumber && fastIsNumber(v1, left)) + bool rightIsNumber = v2.getNumber(right); + if (rightIsNumber && v1.getNumber(left)) return jsNumber(callFrame, left + right); - bool leftIsString = v1->isString(); - if (leftIsString && v2->isString()) { + bool leftIsString = v1.isString(); + if (leftIsString && v2.isString()) { RefPtr<UString::Rep> value = concatenate(asString(v1)->value().rep(), asString(v2)->value().rep()); if (!value) return throwOutOfMemoryError(callFrame); @@ -259,8 +200,8 @@ static ALWAYS_INLINE JSValue* jsAdd(CallFrame* callFrame, JSValue* v1, JSValue* } if (rightIsNumber & leftIsString) { - RefPtr<UString::Rep> value = JSImmediate::isImmediate(v2) ? - concatenate(asString(v1)->value().rep(), JSImmediate::getTruncatedInt32(v2)) : + RefPtr<UString::Rep> value = v2.isInt32Fast() ? + concatenate(asString(v1)->value().rep(), v2.getInt32Fast()) : concatenate(asString(v1)->value().rep(), right); if (!value) @@ -272,20 +213,20 @@ static ALWAYS_INLINE JSValue* jsAdd(CallFrame* callFrame, JSValue* v1, JSValue* return jsAddSlowCase(callFrame, v1, v2); } -static JSValue* jsTypeStringForValue(CallFrame* callFrame, JSValue* v) +static JSValuePtr jsTypeStringForValue(CallFrame* callFrame, JSValuePtr v) { - if (v->isUndefined()) + if (v.isUndefined()) return jsNontrivialString(callFrame, "undefined"); - if (v->isBoolean()) + if (v.isBoolean()) return jsNontrivialString(callFrame, "boolean"); - if (v->isNumber()) + if (v.isNumber()) return jsNontrivialString(callFrame, "number"); - if (v->isString()) + if (v.isString()) return jsNontrivialString(callFrame, "string"); - if (v->isObject()) { + if (v.isObject()) { // Return "undefined" for objects that should be treated // as null when doing comparisons. - if (asObject(v)->structureID()->typeInfo().masqueradesAsUndefined()) + if (asObject(v)->structure()->typeInfo().masqueradesAsUndefined()) return jsNontrivialString(callFrame, "undefined"); CallData callData; if (asObject(v)->getCallData(callData) != CallTypeNone) @@ -294,16 +235,16 @@ static JSValue* jsTypeStringForValue(CallFrame* callFrame, JSValue* v) return jsNontrivialString(callFrame, "object"); } -static bool jsIsObjectType(JSValue* v) +static bool jsIsObjectType(JSValuePtr v) { - if (JSImmediate::isImmediate(v)) - return v->isNull(); + if (!v.isCell()) + return v.isNull(); - JSType type = asCell(v)->structureID()->typeInfo().type(); + JSType type = asCell(v)->structure()->typeInfo().type(); if (type == NumberType || type == StringType) return false; if (type == ObjectType) { - if (asObject(v)->structureID()->typeInfo().masqueradesAsUndefined()) + if (asObject(v)->structure()->typeInfo().masqueradesAsUndefined()) return false; CallData callData; if (asObject(v)->getCallData(callData) != CallTypeNone) @@ -312,9 +253,9 @@ static bool jsIsObjectType(JSValue* v) return true; } -static bool jsIsFunctionType(JSValue* v) +static bool jsIsFunctionType(JSValuePtr v) { - if (v->isObject()) { + if (v.isObject()) { CallData callData; if (asObject(v)->getCallData(callData) != CallTypeNone) return true; @@ -322,7 +263,7 @@ static bool jsIsFunctionType(JSValue* v) return false; } -NEVER_INLINE bool Machine::resolve(CallFrame* callFrame, Instruction* vPC, JSValue*& exceptionValue) +NEVER_INLINE bool Interpreter::resolve(CallFrame* callFrame, Instruction* vPC, JSValuePtr& exceptionValue) { int dst = (vPC + 1)->u.operand; int property = (vPC + 2)->u.operand; @@ -333,30 +274,30 @@ NEVER_INLINE bool Machine::resolve(CallFrame* callFrame, Instruction* vPC, JSVal ASSERT(iter != end); CodeBlock* codeBlock = callFrame->codeBlock(); - Identifier& ident = codeBlock->identifiers[property]; + Identifier& ident = codeBlock->identifier(property); do { JSObject* o = *iter; PropertySlot slot(o); if (o->getPropertySlot(callFrame, ident, slot)) { - JSValue* result = slot.getValue(callFrame, ident); + JSValuePtr result = slot.getValue(callFrame, ident); exceptionValue = callFrame->globalData().exception; if (exceptionValue) return false; - callFrame[dst] = result; + callFrame[dst] = JSValuePtr(result); return true; } } while (++iter != end); - exceptionValue = createUndefinedVariableError(callFrame, ident, vPC, codeBlock); + exceptionValue = createUndefinedVariableError(callFrame, ident, vPC - codeBlock->instructions().begin(), codeBlock); return false; } -NEVER_INLINE bool Machine::resolveSkip(CallFrame* callFrame, Instruction* vPC, JSValue*& exceptionValue) +NEVER_INLINE bool Interpreter::resolveSkip(CallFrame* callFrame, Instruction* vPC, JSValuePtr& exceptionValue) { CodeBlock* codeBlock = callFrame->codeBlock(); int dst = (vPC + 1)->u.operand; int property = (vPC + 2)->u.operand; - int skip = (vPC + 3)->u.operand + codeBlock->needsFullScopeChain; + int skip = (vPC + 3)->u.operand + codeBlock->needsFullScopeChain(); ScopeChainNode* scopeChain = callFrame->scopeChain(); ScopeChainIterator iter = scopeChain->begin(); @@ -366,64 +307,64 @@ NEVER_INLINE bool Machine::resolveSkip(CallFrame* callFrame, Instruction* vPC, J ++iter; ASSERT(iter != end); } - Identifier& ident = codeBlock->identifiers[property]; + Identifier& ident = codeBlock->identifier(property); do { JSObject* o = *iter; PropertySlot slot(o); if (o->getPropertySlot(callFrame, ident, slot)) { - JSValue* result = slot.getValue(callFrame, ident); + JSValuePtr result = slot.getValue(callFrame, ident); exceptionValue = callFrame->globalData().exception; if (exceptionValue) return false; - callFrame[dst] = result; + callFrame[dst] = JSValuePtr(result); return true; } } while (++iter != end); - exceptionValue = createUndefinedVariableError(callFrame, ident, vPC, codeBlock); + exceptionValue = createUndefinedVariableError(callFrame, ident, vPC - codeBlock->instructions().begin(), codeBlock); return false; } -NEVER_INLINE bool Machine::resolveGlobal(CallFrame* callFrame, Instruction* vPC, JSValue*& exceptionValue) +NEVER_INLINE bool Interpreter::resolveGlobal(CallFrame* callFrame, Instruction* vPC, JSValuePtr& exceptionValue) { int dst = (vPC + 1)->u.operand; JSGlobalObject* globalObject = static_cast<JSGlobalObject*>((vPC + 2)->u.jsCell); ASSERT(globalObject->isGlobalObject()); int property = (vPC + 3)->u.operand; - StructureID* structureID = (vPC + 4)->u.structureID; + Structure* structure = (vPC + 4)->u.structure; int offset = (vPC + 5)->u.operand; - if (structureID == globalObject->structureID()) { - callFrame[dst] = globalObject->getDirectOffset(offset); + if (structure == globalObject->structure()) { + callFrame[dst] = JSValuePtr(globalObject->getDirectOffset(offset)); return true; } CodeBlock* codeBlock = callFrame->codeBlock(); - Identifier& ident = codeBlock->identifiers[property]; + Identifier& ident = codeBlock->identifier(property); PropertySlot slot(globalObject); if (globalObject->getPropertySlot(callFrame, ident, slot)) { - JSValue* result = slot.getValue(callFrame, ident); - if (slot.isCacheable()) { - if (vPC[4].u.structureID) - vPC[4].u.structureID->deref(); - globalObject->structureID()->ref(); - vPC[4] = globalObject->structureID(); + JSValuePtr result = slot.getValue(callFrame, ident); + if (slot.isCacheable() && !globalObject->structure()->isDictionary()) { + if (vPC[4].u.structure) + vPC[4].u.structure->deref(); + globalObject->structure()->ref(); + vPC[4] = globalObject->structure(); vPC[5] = slot.cachedOffset(); - callFrame[dst] = result; + callFrame[dst] = JSValuePtr(result); return true; } exceptionValue = callFrame->globalData().exception; if (exceptionValue) return false; - callFrame[dst] = result; + callFrame[dst] = JSValuePtr(result); return true; } - exceptionValue = createUndefinedVariableError(callFrame, ident, vPC, codeBlock); + exceptionValue = createUndefinedVariableError(callFrame, ident, vPC - codeBlock->instructions().begin(), codeBlock); return false; } -static ALWAYS_INLINE JSValue* inlineResolveBase(CallFrame* callFrame, Identifier& property, ScopeChainNode* scopeChain) +static ALWAYS_INLINE JSValuePtr inlineResolveBase(CallFrame* callFrame, Identifier& property, ScopeChainNode* scopeChain) { ScopeChainIterator iter = scopeChain->begin(); ScopeChainIterator next = iter; @@ -446,14 +387,14 @@ static ALWAYS_INLINE JSValue* inlineResolveBase(CallFrame* callFrame, Identifier return noValue(); } -NEVER_INLINE void Machine::resolveBase(CallFrame* callFrame, Instruction* vPC) +NEVER_INLINE void Interpreter::resolveBase(CallFrame* callFrame, Instruction* vPC) { int dst = (vPC + 1)->u.operand; int property = (vPC + 2)->u.operand; - callFrame[dst] = inlineResolveBase(callFrame, callFrame->codeBlock()->identifiers[property], callFrame->scopeChain()); + callFrame[dst] = JSValuePtr(inlineResolveBase(callFrame, callFrame->codeBlock()->identifier(property), callFrame->scopeChain())); } -NEVER_INLINE bool Machine::resolveBaseAndProperty(CallFrame* callFrame, Instruction* vPC, JSValue*& exceptionValue) +NEVER_INLINE bool Interpreter::resolveBaseAndProperty(CallFrame* callFrame, Instruction* vPC, JSValuePtr& exceptionValue) { int baseDst = (vPC + 1)->u.operand; int propDst = (vPC + 2)->u.operand; @@ -468,28 +409,28 @@ NEVER_INLINE bool Machine::resolveBaseAndProperty(CallFrame* callFrame, Instruct ASSERT(iter != end); CodeBlock* codeBlock = callFrame->codeBlock(); - Identifier& ident = codeBlock->identifiers[property]; + Identifier& ident = codeBlock->identifier(property); JSObject* base; do { base = *iter; PropertySlot slot(base); if (base->getPropertySlot(callFrame, ident, slot)) { - JSValue* result = slot.getValue(callFrame, ident); + JSValuePtr result = slot.getValue(callFrame, ident); exceptionValue = callFrame->globalData().exception; if (exceptionValue) return false; - callFrame[propDst] = result; - callFrame[baseDst] = base; + callFrame[propDst] = JSValuePtr(result); + callFrame[baseDst] = JSValuePtr(base); return true; } ++iter; } while (iter != end); - exceptionValue = createUndefinedVariableError(callFrame, ident, vPC, codeBlock); + exceptionValue = createUndefinedVariableError(callFrame, ident, vPC - codeBlock->instructions().begin(), codeBlock); return false; } -NEVER_INLINE bool Machine::resolveBaseAndFunc(CallFrame* callFrame, Instruction* vPC, JSValue*& exceptionValue) +NEVER_INLINE bool Interpreter::resolveBaseAndFunc(CallFrame* callFrame, Instruction* vPC, JSValuePtr& exceptionValue) { int baseDst = (vPC + 1)->u.operand; int funcDst = (vPC + 2)->u.operand; @@ -504,7 +445,7 @@ NEVER_INLINE bool Machine::resolveBaseAndFunc(CallFrame* callFrame, Instruction* ASSERT(iter != end); CodeBlock* codeBlock = callFrame->codeBlock(); - Identifier& ident = codeBlock->identifiers[property]; + Identifier& ident = codeBlock->identifier(property); JSObject* base; do { base = *iter; @@ -518,33 +459,33 @@ NEVER_INLINE bool Machine::resolveBaseAndFunc(CallFrame* callFrame, Instruction* // that in host objects you always get a valid object for this. // We also handle wrapper substitution for the global object at the same time. JSObject* thisObj = base->toThisObject(callFrame); - JSValue* result = slot.getValue(callFrame, ident); + JSValuePtr result = slot.getValue(callFrame, ident); exceptionValue = callFrame->globalData().exception; if (exceptionValue) return false; - callFrame[baseDst] = thisObj; - callFrame[funcDst] = result; + callFrame[baseDst] = JSValuePtr(thisObj); + callFrame[funcDst] = JSValuePtr(result); return true; } ++iter; } while (iter != end); - exceptionValue = createUndefinedVariableError(callFrame, ident, vPC, codeBlock); + exceptionValue = createUndefinedVariableError(callFrame, ident, vPC - codeBlock->instructions().begin(), codeBlock); return false; } -ALWAYS_INLINE CallFrame* Machine::slideRegisterWindowForCall(CodeBlock* newCodeBlock, RegisterFile* registerFile, CallFrame* callFrame, size_t registerOffset, int argc) +ALWAYS_INLINE CallFrame* Interpreter::slideRegisterWindowForCall(CodeBlock* newCodeBlock, RegisterFile* registerFile, CallFrame* callFrame, size_t registerOffset, int argc) { Register* r = callFrame->registers(); - Register* newEnd = r + registerOffset + newCodeBlock->numCalleeRegisters; + Register* newEnd = r + registerOffset + newCodeBlock->m_numCalleeRegisters; - if (LIKELY(argc == newCodeBlock->numParameters)) { // correct number of arguments + if (LIKELY(argc == newCodeBlock->m_numParameters)) { // correct number of arguments if (UNLIKELY(!registerFile->grow(newEnd))) return 0; r += registerOffset; - } else if (argc < newCodeBlock->numParameters) { // too few arguments -- fill in the blanks - size_t omittedArgCount = newCodeBlock->numParameters - argc; + } else if (argc < newCodeBlock->m_numParameters) { // too few arguments -- fill in the blanks + size_t omittedArgCount = newCodeBlock->m_numParameters - argc; registerOffset += omittedArgCount; newEnd += omittedArgCount; if (!registerFile->grow(newEnd)) @@ -555,7 +496,7 @@ ALWAYS_INLINE CallFrame* Machine::slideRegisterWindowForCall(CodeBlock* newCodeB for (size_t i = 0; i < omittedArgCount; ++i) argv[i] = jsUndefined(); } else { // too many arguments -- copy expected arguments, leaving the extra arguments behind - size_t numParameters = newCodeBlock->numParameters; + size_t numParameters = newCodeBlock->m_numParameters; registerOffset += numParameters; newEnd += numParameters; @@ -571,42 +512,45 @@ ALWAYS_INLINE CallFrame* Machine::slideRegisterWindowForCall(CodeBlock* newCodeB return CallFrame::create(r); } -static NEVER_INLINE bool isNotObject(CallFrame* callFrame, bool forInstanceOf, CodeBlock* codeBlock, const Instruction* vPC, JSValue* value, JSValue*& exceptionData) +static NEVER_INLINE bool isNotObject(CallFrame* callFrame, bool forInstanceOf, CodeBlock* codeBlock, const Instruction* vPC, JSValuePtr value, JSValuePtr& exceptionData) { - if (value->isObject()) + if (value.isObject()) return false; - exceptionData = createInvalidParamError(callFrame, forInstanceOf ? "instanceof" : "in" , value, vPC, codeBlock); + exceptionData = createInvalidParamError(callFrame, forInstanceOf ? "instanceof" : "in" , value, vPC - codeBlock->instructions().begin(), codeBlock); return true; } -NEVER_INLINE JSValue* Machine::callEval(CallFrame* callFrame, JSObject* thisObj, ScopeChainNode* scopeChain, RegisterFile* registerFile, int argv, int argc, JSValue*& exceptionValue) +NEVER_INLINE JSValuePtr Interpreter::callEval(CallFrame* callFrame, RegisterFile* registerFile, Register* argv, int argc, int registerOffset, JSValuePtr& exceptionValue) { if (argc < 2) return jsUndefined(); - JSValue* program = callFrame[argv + 1].jsValue(callFrame); + JSValuePtr program = argv[1].jsValue(callFrame); - if (!program->isString()) + if (!program.isString()) return program; UString programSource = asString(program)->value(); + ScopeChainNode* scopeChain = callFrame->scopeChain(); CodeBlock* codeBlock = callFrame->codeBlock(); - RefPtr<EvalNode> evalNode = codeBlock->evalCodeCache.get(callFrame, programSource, scopeChain, exceptionValue); + RefPtr<EvalNode> evalNode = codeBlock->evalCodeCache().get(callFrame, programSource, scopeChain, exceptionValue); - JSValue* result = jsUndefined(); + JSValuePtr result = jsUndefined(); if (evalNode) - result = callFrame->globalData().machine->execute(evalNode.get(), callFrame, thisObj, callFrame->registers() - registerFile->start() + argv + 1 + RegisterFile::CallFrameHeaderSize, scopeChain, &exceptionValue); + result = callFrame->globalData().interpreter->execute(evalNode.get(), callFrame, callFrame->thisValue().toThisObject(callFrame), callFrame->registers() - registerFile->start() + registerOffset, scopeChain, &exceptionValue); return result; } -Machine::Machine() +Interpreter::Interpreter() : m_sampler(0) -#if ENABLE(CTI) +#if ENABLE(JIT) , m_ctiArrayLengthTrampoline(0) , m_ctiStringLengthTrampoline(0) - , m_jitCodeBuffer(new JITCodeBuffer(1024 * 1024)) + , m_ctiVirtualCallPreLink(0) + , m_ctiVirtualCallLink(0) + , m_ctiVirtualCall(0) #endif , m_reentryDepth(0) , m_timeoutTime(0) @@ -621,44 +565,47 @@ Machine::Machine() // Bizarrely, calling fastMalloc here is faster than allocating space on the stack. void* storage = fastMalloc(sizeof(CollectorBlock)); - JSCell* jsArray = new (storage) JSArray(JSArray::createStructureID(jsNull())); + JSCell* jsArray = new (storage) JSArray(JSArray::createStructure(jsNull())); m_jsArrayVptr = jsArray->vptr(); jsArray->~JSCell(); + JSCell* jsByteArray = new (storage) JSByteArray(JSByteArray::VPtrStealingHack); + m_jsByteArrayVptr = jsByteArray->vptr(); + jsByteArray->~JSCell(); + JSCell* jsString = new (storage) JSString(JSString::VPtrStealingHack); m_jsStringVptr = jsString->vptr(); jsString->~JSCell(); - JSCell* jsFunction = new (storage) JSFunction(JSFunction::createStructureID(jsNull())); + JSCell* jsFunction = new (storage) JSFunction(JSFunction::createStructure(jsNull())); m_jsFunctionVptr = jsFunction->vptr(); jsFunction->~JSCell(); fastFree(storage); } -Machine::~Machine() +void Interpreter::initialize(JSGlobalData* globalData) { -#if ENABLE(CTI) - if (m_ctiArrayLengthTrampoline) - fastFree(m_ctiArrayLengthTrampoline); - if (m_ctiStringLengthTrampoline) - fastFree(m_ctiStringLengthTrampoline); +#if ENABLE(JIT) + JIT::compileCTIMachineTrampolines(globalData); +#else + UNUSED_PARAM(globalData); #endif } -#ifndef NDEBUG - -void Machine::dumpCallFrame(const RegisterFile* registerFile, CallFrame* callFrame) +Interpreter::~Interpreter() { - JSGlobalObject* globalObject = callFrame->scopeChain()->globalObject(); +} - CodeBlock* codeBlock = callFrame->codeBlock(); - codeBlock->dump(globalObject->globalExec()); +#ifndef NDEBUG - dumpRegisters(registerFile, callFrame); +void Interpreter::dumpCallFrame(CallFrame* callFrame) +{ + callFrame->codeBlock()->dump(callFrame); + dumpRegisters(callFrame); } -void Machine::dumpRegisters(const RegisterFile* registerFile, CallFrame* callFrame) +void Interpreter::dumpRegisters(CallFrame* callFrame) { printf("Register frame: \n\n"); printf("----------------------------------------------------\n"); @@ -666,10 +613,11 @@ void Machine::dumpRegisters(const RegisterFile* registerFile, CallFrame* callFra printf("----------------------------------------------------\n"); CodeBlock* codeBlock = callFrame->codeBlock(); + RegisterFile* registerFile = &callFrame->scopeChain()->globalObject()->globalData()->interpreter->registerFile(); const Register* it; const Register* end; - if (codeBlock->codeType == GlobalCode) { + if (codeBlock->codeType() == GlobalCode) { it = registerFile->lastGlobal(); end = it + registerFile->numGlobals(); while (it != end) { @@ -679,9 +627,9 @@ void Machine::dumpRegisters(const RegisterFile* registerFile, CallFrame* callFra printf("----------------------------------------------------\n"); } - it = callFrame->registers() - RegisterFile::CallFrameHeaderSize - codeBlock->numParameters; + it = callFrame->registers() - RegisterFile::CallFrameHeaderSize - codeBlock->m_numParameters; printf("[this] | %10p | %10p \n", it, (*it).v()); ++it; - end = it + max(codeBlock->numParameters - 1, 0); // - 1 to skip "this" + end = it + max(codeBlock->m_numParameters - 1, 0); // - 1 to skip "this" if (it != end) { do { printf("[param] | %10p | %10p \n", it, (*it).v()); @@ -702,7 +650,7 @@ void Machine::dumpRegisters(const RegisterFile* registerFile, CallFrame* callFra int registerCount = 0; - end = it + codeBlock->numVars; + end = it + codeBlock->m_numVars; if (it != end) { do { printf("[r%2d] | %10p | %10p \n", registerCount, it, (*it).v()); @@ -712,7 +660,7 @@ void Machine::dumpRegisters(const RegisterFile* registerFile, CallFrame* callFra } printf("----------------------------------------------------\n"); - end = it + codeBlock->numConstants; + end = it + codeBlock->m_numConstants; if (it != end) { do { printf("[r%2d] | %10p | %10p \n", registerCount, it, (*it).v()); @@ -722,7 +670,7 @@ void Machine::dumpRegisters(const RegisterFile* registerFile, CallFrame* callFra } printf("----------------------------------------------------\n"); - end = it + codeBlock->numCalleeRegisters - codeBlock->numConstants - codeBlock->numVars; + end = it + codeBlock->m_numCalleeRegisters - codeBlock->m_numConstants - codeBlock->m_numVars; if (it != end) { do { printf("[r%2d] | %10p | %10p \n", registerCount, it, (*it).v()); @@ -735,7 +683,7 @@ void Machine::dumpRegisters(const RegisterFile* registerFile, CallFrame* callFra #endif -bool Machine::isOpcode(Opcode opcode) +bool Interpreter::isOpcode(Opcode opcode) { #if HAVE(COMPUTED_GOTO) return opcode != HashTraits<Opcode>::emptyValue() @@ -746,7 +694,7 @@ bool Machine::isOpcode(Opcode opcode) #endif } -NEVER_INLINE bool Machine::unwindCallFrame(CallFrame*& callFrame, JSValue* exceptionValue, const Instruction*& vPC, CodeBlock*& codeBlock) +NEVER_INLINE bool Interpreter::unwindCallFrame(CallFrame*& callFrame, JSValuePtr exceptionValue, unsigned& bytecodeOffset, CodeBlock*& codeBlock) { CodeBlock* oldCodeBlock = codeBlock; ScopeChainNode* scopeChain = callFrame->scopeChain(); @@ -754,20 +702,20 @@ NEVER_INLINE bool Machine::unwindCallFrame(CallFrame*& callFrame, JSValue* excep if (Debugger* debugger = callFrame->dynamicGlobalObject()->debugger()) { DebuggerCallFrame debuggerCallFrame(callFrame, exceptionValue); if (callFrame->callee()) - debugger->returnEvent(debuggerCallFrame, codeBlock->ownerNode->sourceID(), codeBlock->ownerNode->lastLine()); + debugger->returnEvent(debuggerCallFrame, codeBlock->ownerNode()->sourceID(), codeBlock->ownerNode()->lastLine()); else - debugger->didExecuteProgram(debuggerCallFrame, codeBlock->ownerNode->sourceID(), codeBlock->ownerNode->lastLine()); + debugger->didExecuteProgram(debuggerCallFrame, codeBlock->ownerNode()->sourceID(), codeBlock->ownerNode()->lastLine()); } if (Profiler* profiler = *Profiler::enabledProfilerReference()) { if (callFrame->callee()) profiler->didExecute(callFrame, callFrame->callee()); else - profiler->didExecute(callFrame, codeBlock->ownerNode->sourceURL(), codeBlock->ownerNode->lineNo()); + profiler->didExecute(callFrame, codeBlock->ownerNode()->sourceURL(), codeBlock->ownerNode()->lineNo()); } // If this call frame created an activation or an 'arguments' object, tear it off. - if (oldCodeBlock->codeType == FunctionCode && oldCodeBlock->needsFullScopeChain) { + if (oldCodeBlock->codeType() == FunctionCode && oldCodeBlock->needsFullScopeChain()) { while (!scopeChain->object->isObject(&JSActivation::info)) scopeChain = scopeChain->pop(); static_cast<JSActivation*>(scopeChain->object)->copyRegisters(callFrame->optionalCalleeArguments()); @@ -776,7 +724,7 @@ NEVER_INLINE bool Machine::unwindCallFrame(CallFrame*& callFrame, JSValue* excep arguments->copyRegisters(); } - if (oldCodeBlock->needsFullScopeChain) + if (oldCodeBlock->needsFullScopeChain()) scopeChain->deref(); void* returnPC = callFrame->returnPC(); @@ -785,19 +733,19 @@ NEVER_INLINE bool Machine::unwindCallFrame(CallFrame*& callFrame, JSValue* excep return false; codeBlock = callFrame->codeBlock(); - vPC = vPCForPC(codeBlock, returnPC); + bytecodeOffset = bytecodeOffsetForPC(callFrame, codeBlock, returnPC); return true; } -NEVER_INLINE Instruction* Machine::throwException(CallFrame*& callFrame, JSValue*& exceptionValue, const Instruction* vPC, bool explicitThrow) +NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSValuePtr& exceptionValue, unsigned bytecodeOffset, bool explicitThrow) { // Set up the exception object - + CodeBlock* codeBlock = callFrame->codeBlock(); - if (exceptionValue->isObject()) { + if (exceptionValue.isObject()) { JSObject* exception = asObject(exceptionValue); if (exception->isNotAnObjectErrorStub()) { - exception = createNotAnObjectError(callFrame, static_cast<JSNotAnObjectErrorStub*>(exception), vPC, codeBlock); + exception = createNotAnObjectError(callFrame, static_cast<JSNotAnObjectErrorStub*>(exception), bytecodeOffset, codeBlock); exceptionValue = exception; } else { if (!exception->hasProperty(callFrame, Identifier(callFrame, "line")) && @@ -810,7 +758,7 @@ NEVER_INLINE Instruction* Machine::throwException(CallFrame*& callFrame, JSValue int startOffset = 0; int endOffset = 0; int divotPoint = 0; - int line = codeBlock->expressionRangeForVPC(vPC, divotPoint, startOffset, endOffset); + int line = codeBlock->expressionRangeForBytecodeOffset(callFrame, bytecodeOffset, divotPoint, startOffset, endOffset); exception->putWithAttributes(callFrame, Identifier(callFrame, "line"), jsNumber(callFrame, line), ReadOnly | DontDelete); // We only hit this path for error messages and throw statements, which don't have a specific failure position @@ -818,13 +766,13 @@ NEVER_INLINE Instruction* Machine::throwException(CallFrame*& callFrame, JSValue exception->putWithAttributes(callFrame, Identifier(callFrame, expressionBeginOffsetPropertyName), jsNumber(callFrame, divotPoint - startOffset), ReadOnly | DontDelete); exception->putWithAttributes(callFrame, Identifier(callFrame, expressionEndOffsetPropertyName), jsNumber(callFrame, divotPoint + endOffset), ReadOnly | DontDelete); } else - exception->putWithAttributes(callFrame, Identifier(callFrame, "line"), jsNumber(callFrame, codeBlock->lineNumberForVPC(vPC)), ReadOnly | DontDelete); - exception->putWithAttributes(callFrame, Identifier(callFrame, "sourceId"), jsNumber(callFrame, codeBlock->ownerNode->sourceID()), ReadOnly | DontDelete); - exception->putWithAttributes(callFrame, Identifier(callFrame, "sourceURL"), jsOwnedString(callFrame, codeBlock->ownerNode->sourceURL()), ReadOnly | DontDelete); + exception->putWithAttributes(callFrame, Identifier(callFrame, "line"), jsNumber(callFrame, codeBlock->lineNumberForBytecodeOffset(callFrame, bytecodeOffset)), ReadOnly | DontDelete); + exception->putWithAttributes(callFrame, Identifier(callFrame, "sourceId"), jsNumber(callFrame, codeBlock->ownerNode()->sourceID()), ReadOnly | DontDelete); + exception->putWithAttributes(callFrame, Identifier(callFrame, "sourceURL"), jsOwnedString(callFrame, codeBlock->ownerNode()->sourceURL()), ReadOnly | DontDelete); } if (exception->isWatchdogException()) { - while (unwindCallFrame(callFrame, exceptionValue, vPC, codeBlock)) { + while (unwindCallFrame(callFrame, exceptionValue, bytecodeOffset, codeBlock)) { // Don't need handler checks or anything, we just want to unroll all the JS callframes possible. } return 0; @@ -834,61 +782,47 @@ NEVER_INLINE Instruction* Machine::throwException(CallFrame*& callFrame, JSValue if (Debugger* debugger = callFrame->dynamicGlobalObject()->debugger()) { DebuggerCallFrame debuggerCallFrame(callFrame, exceptionValue); - debugger->exception(debuggerCallFrame, codeBlock->ownerNode->sourceID(), codeBlock->lineNumberForVPC(vPC)); + debugger->exception(debuggerCallFrame, codeBlock->ownerNode()->sourceID(), codeBlock->lineNumberForBytecodeOffset(callFrame, bytecodeOffset)); } // If we throw in the middle of a call instruction, we need to notify // the profiler manually that the call instruction has returned, since // we'll never reach the relevant op_profile_did_call. if (Profiler* profiler = *Profiler::enabledProfilerReference()) { - if (isCallOpcode(vPC[0].u.opcode)) - profiler->didExecute(callFrame, callFrame[vPC[2].u.operand].jsValue(callFrame)); - else if (vPC[8].u.opcode == getOpcode(op_construct)) - profiler->didExecute(callFrame, callFrame[vPC[10].u.operand].jsValue(callFrame)); +#if !ENABLE(JIT) + if (isCallBytecode(codeBlock->instructions()[bytecodeOffset].u.opcode)) + profiler->didExecute(callFrame, callFrame[codeBlock->instructions()[bytecodeOffset + 2].u.operand].jsValue(callFrame)); + else if (codeBlock->instructions()[bytecodeOffset + 8].u.opcode == getOpcode(op_construct)) + profiler->didExecute(callFrame, callFrame[codeBlock->instructions()[bytecodeOffset + 10].u.operand].jsValue(callFrame)); +#else + int functionRegisterIndex; + if (codeBlock->functionRegisterForBytecodeOffset(bytecodeOffset, functionRegisterIndex)) + profiler->didExecute(callFrame, callFrame[functionRegisterIndex].jsValue(callFrame)); +#endif } // Calculate an exception handler vPC, unwinding call frames as necessary. - int scopeDepth; - Instruction* handlerVPC; - - while (!codeBlock->getHandlerForVPC(vPC, handlerVPC, scopeDepth)) { - if (!unwindCallFrame(callFrame, exceptionValue, vPC, codeBlock)) + HandlerInfo* handler = 0; + while (!(handler = codeBlock->handlerForBytecodeOffset(bytecodeOffset))) { + if (!unwindCallFrame(callFrame, exceptionValue, bytecodeOffset, codeBlock)) return 0; } // Now unwind the scope chain within the exception handler's call frame. - ScopeChain sc(callFrame->scopeChain()); - int scopeDelta = depth(codeBlock, sc) - scopeDepth; + ScopeChainNode* scopeChain = callFrame->scopeChain(); + ScopeChain sc(scopeChain); + int scopeDelta = depth(codeBlock, sc) - handler->scopeDepth; ASSERT(scopeDelta >= 0); while (scopeDelta--) - sc.pop(); - callFrame->setScopeChain(sc.node()); + scopeChain = scopeChain->pop(); + callFrame->setScopeChain(scopeChain); - return handlerVPC; + return handler; } -class DynamicGlobalObjectScope : Noncopyable { -public: - DynamicGlobalObjectScope(CallFrame* callFrame, JSGlobalObject* dynamicGlobalObject) - : m_dynamicGlobalObjectSlot(callFrame->globalData().dynamicGlobalObject) - , m_savedDynamicGlobalObject(m_dynamicGlobalObjectSlot) - { - m_dynamicGlobalObjectSlot = dynamicGlobalObject; - } - - ~DynamicGlobalObjectScope() - { - m_dynamicGlobalObjectSlot = m_savedDynamicGlobalObject; - } - -private: - JSGlobalObject*& m_dynamicGlobalObjectSlot; - JSGlobalObject* m_savedDynamicGlobalObject; -}; - -JSValue* Machine::execute(ProgramNode* programNode, CallFrame* callFrame, ScopeChainNode* scopeChain, JSObject* thisObj, JSValue** exception) +JSValuePtr Interpreter::execute(ProgramNode* programNode, CallFrame* callFrame, ScopeChainNode* scopeChain, JSObject* thisObj, JSValuePtr* exception) { ASSERT(!scopeChain->globalData->exception); @@ -897,10 +831,10 @@ JSValue* Machine::execute(ProgramNode* programNode, CallFrame* callFrame, ScopeC return jsNull(); } - CodeBlock* codeBlock = &programNode->byteCode(scopeChain); + CodeBlock* codeBlock = &programNode->bytecode(scopeChain); Register* oldEnd = m_registerFile.end(); - Register* newEnd = oldEnd + codeBlock->numParameters + RegisterFile::CallFrameHeaderSize + codeBlock->numCalleeRegisters; + Register* newEnd = oldEnd + codeBlock->m_numParameters + RegisterFile::CallFrameHeaderSize + codeBlock->m_numCalleeRegisters; if (!m_registerFile.grow(newEnd)) { *exception = createStackOverflowError(callFrame); return jsNull(); @@ -912,26 +846,26 @@ JSValue* Machine::execute(ProgramNode* programNode, CallFrame* callFrame, ScopeC JSGlobalObject* globalObject = callFrame->dynamicGlobalObject(); globalObject->copyGlobalsTo(m_registerFile); - CallFrame* newCallFrame = CallFrame::create(oldEnd + codeBlock->numParameters + RegisterFile::CallFrameHeaderSize); - newCallFrame[codeBlock->thisRegister] = thisObj; + CallFrame* newCallFrame = CallFrame::create(oldEnd + codeBlock->m_numParameters + RegisterFile::CallFrameHeaderSize); + newCallFrame[codeBlock->thisRegister()] = JSValuePtr(thisObj); newCallFrame->init(codeBlock, 0, scopeChain, CallFrame::noCaller(), 0, 0, 0); - if (codeBlock->needsFullScopeChain) + if (codeBlock->needsFullScopeChain()) scopeChain->ref(); Profiler** profiler = Profiler::enabledProfilerReference(); if (*profiler) (*profiler)->willExecute(newCallFrame, programNode->sourceURL(), programNode->lineNo()); - JSValue* result; + JSValuePtr result; { SamplingTool::CallRecord callRecord(m_sampler); m_reentryDepth++; -#if ENABLE(CTI) - if (!codeBlock->ctiCode) - CTI::compile(this, newCallFrame, codeBlock); - result = CTI::execute(codeBlock->ctiCode, &m_registerFile, newCallFrame, scopeChain->globalData, exception); +#if ENABLE(JIT) + if (!codeBlock->jitCode()) + JIT::compile(scopeChain->globalData, codeBlock); + result = JIT::execute(codeBlock->jitCode(), &m_registerFile, newCallFrame, scopeChain->globalData, exception); #else result = privateExecute(Normal, &m_registerFile, newCallFrame, exception); #endif @@ -949,7 +883,7 @@ JSValue* Machine::execute(ProgramNode* programNode, CallFrame* callFrame, ScopeC return result; } -JSValue* Machine::execute(FunctionBodyNode* functionBodyNode, CallFrame* callFrame, JSFunction* function, JSObject* thisObj, const ArgList& args, ScopeChainNode* scopeChain, JSValue** exception) +JSValuePtr Interpreter::execute(FunctionBodyNode* functionBodyNode, CallFrame* callFrame, JSFunction* function, JSObject* thisObj, const ArgList& args, ScopeChainNode* scopeChain, JSValuePtr* exception) { ASSERT(!scopeChain->globalData->exception); @@ -970,12 +904,12 @@ JSValue* Machine::execute(FunctionBodyNode* functionBodyNode, CallFrame* callFra CallFrame* newCallFrame = CallFrame::create(oldEnd); size_t dst = 0; - newCallFrame[0] = thisObj; + newCallFrame[0] = JSValuePtr(thisObj); ArgList::const_iterator end = args.end(); for (ArgList::const_iterator it = args.begin(); it != end; ++it) newCallFrame[++dst] = *it; - CodeBlock* codeBlock = &functionBodyNode->byteCode(scopeChain); + CodeBlock* codeBlock = &functionBodyNode->bytecode(scopeChain); newCallFrame = slideRegisterWindowForCall(codeBlock, &m_registerFile, newCallFrame, argc + RegisterFile::CallFrameHeaderSize, argc); if (UNLIKELY(!newCallFrame)) { *exception = createStackOverflowError(callFrame); @@ -987,17 +921,17 @@ JSValue* Machine::execute(FunctionBodyNode* functionBodyNode, CallFrame* callFra Profiler** profiler = Profiler::enabledProfilerReference(); if (*profiler) - (*profiler)->willExecute(newCallFrame, function); + (*profiler)->willExecute(callFrame, function); - JSValue* result; + JSValuePtr result; { SamplingTool::CallRecord callRecord(m_sampler); m_reentryDepth++; -#if ENABLE(CTI) - if (!codeBlock->ctiCode) - CTI::compile(this, newCallFrame, codeBlock); - result = CTI::execute(codeBlock->ctiCode, &m_registerFile, newCallFrame, scopeChain->globalData, exception); +#if ENABLE(JIT) + if (!codeBlock->jitCode()) + JIT::compile(scopeChain->globalData, codeBlock); + result = JIT::execute(codeBlock->jitCode(), &m_registerFile, newCallFrame, scopeChain->globalData, exception); #else result = privateExecute(Normal, &m_registerFile, newCallFrame, exception); #endif @@ -1005,18 +939,18 @@ JSValue* Machine::execute(FunctionBodyNode* functionBodyNode, CallFrame* callFra } if (*profiler) - (*profiler)->didExecute(newCallFrame, function); + (*profiler)->didExecute(callFrame, function); m_registerFile.shrink(oldEnd); return result; } -JSValue* Machine::execute(EvalNode* evalNode, CallFrame* callFrame, JSObject* thisObj, ScopeChainNode* scopeChain, JSValue** exception) +JSValuePtr Interpreter::execute(EvalNode* evalNode, CallFrame* callFrame, JSObject* thisObj, ScopeChainNode* scopeChain, JSValuePtr* exception) { - return execute(evalNode, callFrame, thisObj, m_registerFile.size() + evalNode->byteCode(scopeChain).numParameters + RegisterFile::CallFrameHeaderSize, scopeChain, exception); + return execute(evalNode, callFrame, thisObj, m_registerFile.size() + evalNode->bytecode(scopeChain).m_numParameters + RegisterFile::CallFrameHeaderSize, scopeChain, exception); } -JSValue* Machine::execute(EvalNode* evalNode, CallFrame* callFrame, JSObject* thisObj, int registerOffset, ScopeChainNode* scopeChain, JSValue** exception) +JSValuePtr Interpreter::execute(EvalNode* evalNode, CallFrame* callFrame, JSObject* thisObj, int globalRegisterOffset, ScopeChainNode* scopeChain, JSValuePtr* exception) { ASSERT(!scopeChain->globalData->exception); @@ -1027,7 +961,7 @@ JSValue* Machine::execute(EvalNode* evalNode, CallFrame* callFrame, JSObject* th DynamicGlobalObjectScope globalObjectScope(callFrame, callFrame->globalData().dynamicGlobalObject ? callFrame->globalData().dynamicGlobalObject : scopeChain->globalObject()); - EvalCodeBlock* codeBlock = &evalNode->byteCode(scopeChain); + EvalCodeBlock* codeBlock = &evalNode->bytecode(scopeChain); JSVariableObject* variableObject; for (ScopeChainNode* node = scopeChain; ; node = node->next) { @@ -1042,9 +976,9 @@ JSValue* Machine::execute(EvalNode* evalNode, CallFrame* callFrame, JSObject* th BatchedTransitionOptimizer optimizer(variableObject); - const Node::VarStack& varStack = codeBlock->ownerNode->varStack(); - Node::VarStack::const_iterator varStackEnd = varStack.end(); - for (Node::VarStack::const_iterator it = varStack.begin(); it != varStackEnd; ++it) { + const DeclarationStacks::VarStack& varStack = codeBlock->ownerNode()->varStack(); + DeclarationStacks::VarStack::const_iterator varStackEnd = varStack.end(); + for (DeclarationStacks::VarStack::const_iterator it = varStack.begin(); it != varStackEnd; ++it) { const Identifier& ident = (*it).first; if (!variableObject->hasProperty(callFrame, ident)) { PutPropertySlot slot; @@ -1052,9 +986,9 @@ JSValue* Machine::execute(EvalNode* evalNode, CallFrame* callFrame, JSObject* th } } - const Node::FunctionStack& functionStack = codeBlock->ownerNode->functionStack(); - Node::FunctionStack::const_iterator functionStackEnd = functionStack.end(); - for (Node::FunctionStack::const_iterator it = functionStack.begin(); it != functionStackEnd; ++it) { + const DeclarationStacks::FunctionStack& functionStack = codeBlock->ownerNode()->functionStack(); + DeclarationStacks::FunctionStack::const_iterator functionStackEnd = functionStack.end(); + for (DeclarationStacks::FunctionStack::const_iterator it = functionStack.begin(); it != functionStackEnd; ++it) { PutPropertySlot slot; variableObject->put(callFrame, (*it)->m_ident, (*it)->makeFunction(callFrame, scopeChain), slot); } @@ -1062,34 +996,34 @@ JSValue* Machine::execute(EvalNode* evalNode, CallFrame* callFrame, JSObject* th } Register* oldEnd = m_registerFile.end(); - Register* newEnd = m_registerFile.start() + registerOffset + codeBlock->numCalleeRegisters; + Register* newEnd = m_registerFile.start() + globalRegisterOffset + codeBlock->m_numCalleeRegisters; if (!m_registerFile.grow(newEnd)) { *exception = createStackOverflowError(callFrame); return jsNull(); } - CallFrame* newCallFrame = CallFrame::create(m_registerFile.start() + registerOffset); + CallFrame* newCallFrame = CallFrame::create(m_registerFile.start() + globalRegisterOffset); // a 0 codeBlock indicates a built-in caller - newCallFrame[codeBlock->thisRegister] = thisObj; + newCallFrame[codeBlock->thisRegister()] = JSValuePtr(thisObj); newCallFrame->init(codeBlock, 0, scopeChain, callFrame->addHostCallFrameFlag(), 0, 0, 0); - if (codeBlock->needsFullScopeChain) + if (codeBlock->needsFullScopeChain()) scopeChain->ref(); Profiler** profiler = Profiler::enabledProfilerReference(); if (*profiler) (*profiler)->willExecute(newCallFrame, evalNode->sourceURL(), evalNode->lineNo()); - JSValue* result; + JSValuePtr result; { SamplingTool::CallRecord callRecord(m_sampler); m_reentryDepth++; -#if ENABLE(CTI) - if (!codeBlock->ctiCode) - CTI::compile(this, newCallFrame, codeBlock); - result = CTI::execute(codeBlock->ctiCode, &m_registerFile, newCallFrame, scopeChain->globalData, exception); +#if ENABLE(JIT) + if (!codeBlock->jitCode()) + JIT::compile(scopeChain->globalData, codeBlock); + result = JIT::execute(codeBlock->jitCode(), &m_registerFile, newCallFrame, scopeChain->globalData, exception); #else result = privateExecute(Normal, &m_registerFile, newCallFrame, exception); #endif @@ -1103,7 +1037,7 @@ JSValue* Machine::execute(EvalNode* evalNode, CallFrame* callFrame, JSObject* th return result; } -NEVER_INLINE void Machine::debug(CallFrame* callFrame, DebugHookID debugHookID, int firstLine, int lastLine) +NEVER_INLINE void Interpreter::debug(CallFrame* callFrame, DebugHookID debugHookID, int firstLine, int lastLine) { Debugger* debugger = callFrame->dynamicGlobalObject()->debugger(); if (!debugger) @@ -1111,27 +1045,27 @@ NEVER_INLINE void Machine::debug(CallFrame* callFrame, DebugHookID debugHookID, switch (debugHookID) { case DidEnterCallFrame: - debugger->callEvent(callFrame, callFrame->codeBlock()->ownerNode->sourceID(), firstLine); + debugger->callEvent(callFrame, callFrame->codeBlock()->ownerNode()->sourceID(), firstLine); return; case WillLeaveCallFrame: - debugger->returnEvent(callFrame, callFrame->codeBlock()->ownerNode->sourceID(), lastLine); + debugger->returnEvent(callFrame, callFrame->codeBlock()->ownerNode()->sourceID(), lastLine); return; case WillExecuteStatement: - debugger->atStatement(callFrame, callFrame->codeBlock()->ownerNode->sourceID(), firstLine); + debugger->atStatement(callFrame, callFrame->codeBlock()->ownerNode()->sourceID(), firstLine); return; case WillExecuteProgram: - debugger->willExecuteProgram(callFrame, callFrame->codeBlock()->ownerNode->sourceID(), firstLine); + debugger->willExecuteProgram(callFrame, callFrame->codeBlock()->ownerNode()->sourceID(), firstLine); return; case DidExecuteProgram: - debugger->didExecuteProgram(callFrame, callFrame->codeBlock()->ownerNode->sourceID(), lastLine); + debugger->didExecuteProgram(callFrame, callFrame->codeBlock()->ownerNode()->sourceID(), lastLine); return; case DidReachBreakpoint: - debugger->didReachBreakpoint(callFrame, callFrame->codeBlock()->ownerNode->sourceID(), lastLine); + debugger->didReachBreakpoint(callFrame, callFrame->codeBlock()->ownerNode()->sourceID(), lastLine); return; } } -void Machine::resetTimeoutCheck() +void Interpreter::resetTimeoutCheck() { m_ticksUntilNextTimeoutCheck = initialTickCountThreshold; m_timeAtLastCheckTimeout = 0; @@ -1146,7 +1080,9 @@ static inline unsigned getCPUTime() thread_basic_info_data_t info; // Get thread information - thread_info(mach_thread_self(), THREAD_BASIC_INFO, reinterpret_cast<thread_info_t>(&info), &infoCount); + mach_port_t threadPort = mach_thread_self(); + thread_info(threadPort, THREAD_BASIC_INFO, reinterpret_cast<thread_info_t>(&info), &infoCount); + mach_port_deallocate(mach_task_self(), threadPort); unsigned time = info.user_time.seconds * 1000 + info.user_time.microseconds / 1000; time += info.system_time.seconds * 1000 + info.system_time.microseconds / 1000; @@ -1180,14 +1116,14 @@ static inline unsigned getCPUTime() // We have to return a JSValue here, gcc seems to produce worse code if // we attempt to return a bool -ALWAYS_INLINE JSValue* Machine::checkTimeout(JSGlobalObject* globalObject) +ALWAYS_INLINE bool Interpreter::checkTimeout(JSGlobalObject* globalObject) { unsigned currentTime = getCPUTime(); if (!m_timeAtLastCheckTimeout) { // Suspicious amount of looping in a script -- start timing it m_timeAtLastCheckTimeout = currentTime; - return noValue(); + return false; } unsigned timeDiff = currentTime - m_timeAtLastCheckTimeout; @@ -1208,43 +1144,43 @@ ALWAYS_INLINE JSValue* Machine::checkTimeout(JSGlobalObject* globalObject) if (m_timeoutTime && m_timeExecuting > m_timeoutTime) { if (globalObject->shouldInterruptScript()) - return jsNull(); // Appeasing GCC, all we need is a non-null js value. + return true; resetTimeoutCheck(); } - return noValue(); + return false; } -NEVER_INLINE ScopeChainNode* Machine::createExceptionScope(CallFrame* callFrame, const Instruction* vPC) +NEVER_INLINE ScopeChainNode* Interpreter::createExceptionScope(CallFrame* callFrame, const Instruction* vPC) { int dst = (++vPC)->u.operand; CodeBlock* codeBlock = callFrame->codeBlock(); - Identifier& property = codeBlock->identifiers[(++vPC)->u.operand]; - JSValue* value = callFrame[(++vPC)->u.operand].jsValue(callFrame); + Identifier& property = codeBlock->identifier((++vPC)->u.operand); + JSValuePtr value = callFrame[(++vPC)->u.operand].jsValue(callFrame); JSObject* scope = new (callFrame) JSStaticScopeObject(callFrame, property, value, DontDelete); - callFrame[dst] = scope; + callFrame[dst] = JSValuePtr(scope); return callFrame->scopeChain()->push(scope); } -static StructureIDChain* cachePrototypeChain(CallFrame* callFrame, StructureID* structureID) +static StructureChain* cachePrototypeChain(CallFrame* callFrame, Structure* structure) { - JSValue* prototype = structureID->prototypeForLookup(callFrame); - if (JSImmediate::isImmediate(prototype)) + JSValuePtr prototype = structure->prototypeForLookup(callFrame); + if (!prototype.isCell()) return 0; - RefPtr<StructureIDChain> chain = StructureIDChain::create(asObject(prototype)->structureID()); - structureID->setCachedPrototypeChain(chain.release()); - return structureID->cachedPrototypeChain(); + RefPtr<StructureChain> chain = StructureChain::create(asObject(prototype)->structure()); + structure->setCachedPrototypeChain(chain.release()); + return structure->cachedPrototypeChain(); } -NEVER_INLINE void Machine::tryCachePutByID(CallFrame* callFrame, CodeBlock* codeBlock, Instruction* vPC, JSValue* baseValue, const PutPropertySlot& slot) +NEVER_INLINE void Interpreter::tryCachePutByID(CallFrame* callFrame, CodeBlock* codeBlock, Instruction* vPC, JSValuePtr baseValue, const PutPropertySlot& slot) { // Recursive invocation may already have specialized this instruction. if (vPC[0].u.opcode != getOpcode(op_put_by_id)) return; - if (JSImmediate::isImmediate(baseValue)) + if (!baseValue.isCell()) return; // Uncacheable: give up. @@ -1254,19 +1190,19 @@ NEVER_INLINE void Machine::tryCachePutByID(CallFrame* callFrame, CodeBlock* code } JSCell* baseCell = asCell(baseValue); - StructureID* structureID = baseCell->structureID(); + Structure* structure = baseCell->structure(); - if (structureID->isDictionary()) { + if (structure->isDictionary()) { vPC[0] = getOpcode(op_put_by_id_generic); return; } - // Cache miss: record StructureID to compare against next time. - StructureID* lastStructureID = vPC[4].u.structureID; - if (structureID != lastStructureID) { - // First miss: record StructureID to compare against next time. - if (!lastStructureID) { - vPC[4] = structureID; + // Cache miss: record Structure to compare against next time. + Structure* lastStructure = vPC[4].u.structure; + if (structure != lastStructure) { + // First miss: record Structure to compare against next time. + if (!lastStructure) { + vPC[4] = structure; return; } @@ -1275,7 +1211,7 @@ NEVER_INLINE void Machine::tryCachePutByID(CallFrame* callFrame, CodeBlock* code return; } - // Cache hit: Specialize instruction and ref StructureIDs. + // Cache hit: Specialize instruction and ref Structures. // If baseCell != slot.base(), then baseCell must be a proxy for another object. if (baseCell != slot.base()) { @@ -1283,14 +1219,14 @@ NEVER_INLINE void Machine::tryCachePutByID(CallFrame* callFrame, CodeBlock* code return; } - // StructureID transition, cache transition info + // Structure transition, cache transition info if (slot.type() == PutPropertySlot::NewProperty) { vPC[0] = getOpcode(op_put_by_id_transition); - vPC[4] = structureID->previousID(); - vPC[5] = structureID; - StructureIDChain* chain = structureID->cachedPrototypeChain(); + vPC[4] = structure->previousID(); + vPC[5] = structure; + StructureChain* chain = structure->cachedPrototypeChain(); if (!chain) { - chain = cachePrototypeChain(callFrame, structureID); + chain = cachePrototypeChain(callFrame, structure); if (!chain) { // This happens if someone has manually inserted null into the prototype chain vPC[0] = getOpcode(op_put_by_id_generic); @@ -1299,30 +1235,61 @@ NEVER_INLINE void Machine::tryCachePutByID(CallFrame* callFrame, CodeBlock* code } vPC[6] = chain; vPC[7] = slot.cachedOffset(); - codeBlock->refStructureIDs(vPC); + codeBlock->refStructures(vPC); return; } vPC[0] = getOpcode(op_put_by_id_replace); vPC[5] = slot.cachedOffset(); - codeBlock->refStructureIDs(vPC); + codeBlock->refStructures(vPC); } -NEVER_INLINE void Machine::uncachePutByID(CodeBlock* codeBlock, Instruction* vPC) +NEVER_INLINE void Interpreter::uncachePutByID(CodeBlock* codeBlock, Instruction* vPC) { - codeBlock->derefStructureIDs(vPC); + codeBlock->derefStructures(vPC); vPC[0] = getOpcode(op_put_by_id); vPC[4] = 0; } -NEVER_INLINE void Machine::tryCacheGetByID(CallFrame* callFrame, CodeBlock* codeBlock, Instruction* vPC, JSValue* baseValue, const Identifier& propertyName, const PropertySlot& slot) +static size_t countPrototypeChainEntriesAndCheckForProxies(CallFrame* callFrame, JSValuePtr baseValue, const PropertySlot& slot) +{ + JSCell* cell = asCell(baseValue); + size_t count = 0; + + while (slot.slotBase() != cell) { + JSValuePtr v = cell->structure()->prototypeForLookup(callFrame); + + // If we didn't find slotBase in baseValue's prototype chain, then baseValue + // must be a proxy for another object. + + if (v.isNull()) + return 0; + + cell = asCell(v); + + // Since we're accessing a prototype in a loop, it's a good bet that it + // should not be treated as a dictionary. + if (cell->structure()->isDictionary()) { + RefPtr<Structure> transition = Structure::fromDictionaryTransition(cell->structure()); + asObject(cell)->setStructure(transition.release()); + cell->structure()->setCachedPrototypeChain(0); + } + + ++count; + } + + ASSERT(count); + return count; +} + +NEVER_INLINE void Interpreter::tryCacheGetByID(CallFrame* callFrame, CodeBlock* codeBlock, Instruction* vPC, JSValuePtr baseValue, const Identifier& propertyName, const PropertySlot& slot) { // Recursive invocation may already have specialized this instruction. if (vPC[0].u.opcode != getOpcode(op_get_by_id)) return; // FIXME: Cache property access for immediates. - if (JSImmediate::isImmediate(baseValue)) { + if (!baseValue.isCell()) { vPC[0] = getOpcode(op_get_by_id_generic); return; } @@ -1343,19 +1310,19 @@ NEVER_INLINE void Machine::tryCacheGetByID(CallFrame* callFrame, CodeBlock* code return; } - StructureID* structureID = asCell(baseValue)->structureID(); + Structure* structure = asCell(baseValue)->structure(); - if (structureID->isDictionary()) { + if (structure->isDictionary()) { vPC[0] = getOpcode(op_get_by_id_generic); return; } // Cache miss - StructureID* lastStructureID = vPC[4].u.structureID; - if (structureID != lastStructureID) { - // First miss: record StructureID to compare against next time. - if (!lastStructureID) { - vPC[4] = structureID; + Structure* lastStructure = vPC[4].u.structure; + if (structure != lastStructure) { + // First miss: record Structure to compare against next time. + if (!lastStructure) { + vPC[4] = structure; return; } @@ -1364,116 +1331,95 @@ NEVER_INLINE void Machine::tryCacheGetByID(CallFrame* callFrame, CodeBlock* code return; } - // Cache hit: Specialize instruction and ref StructureIDs. + // Cache hit: Specialize instruction and ref Structures. if (slot.slotBase() == baseValue) { vPC[0] = getOpcode(op_get_by_id_self); vPC[5] = slot.cachedOffset(); - codeBlock->refStructureIDs(vPC); + codeBlock->refStructures(vPC); return; } - if (slot.slotBase() == structureID->prototypeForLookup(callFrame)) { - ASSERT(slot.slotBase()->isObject()); + if (slot.slotBase() == structure->prototypeForLookup(callFrame)) { + ASSERT(slot.slotBase().isObject()); JSObject* baseObject = asObject(slot.slotBase()); - // Heavy access to a prototype is a good indication that it's not being - // used as a dictionary. - if (baseObject->structureID()->isDictionary()) { - RefPtr<StructureID> transition = StructureID::fromDictionaryTransition(baseObject->structureID()); - baseObject->setStructureID(transition.release()); - asCell(baseValue)->structureID()->setCachedPrototypeChain(0); + // Since we're accessing a prototype in a loop, it's a good bet that it + // should not be treated as a dictionary. + if (baseObject->structure()->isDictionary()) { + RefPtr<Structure> transition = Structure::fromDictionaryTransition(baseObject->structure()); + baseObject->setStructure(transition.release()); + asCell(baseValue)->structure()->setCachedPrototypeChain(0); } vPC[0] = getOpcode(op_get_by_id_proto); - vPC[5] = baseObject->structureID(); + vPC[5] = baseObject->structure(); vPC[6] = slot.cachedOffset(); - codeBlock->refStructureIDs(vPC); + codeBlock->refStructures(vPC); return; } - size_t count = 0; - JSObject* o = asObject(baseValue); - while (slot.slotBase() != o) { - JSValue* v = o->structureID()->prototypeForLookup(callFrame); - - // If we didn't find base in baseValue's prototype chain, then baseValue - // must be a proxy for another object. - if (v->isNull()) { - vPC[0] = getOpcode(op_get_by_id_generic); - return; - } - - o = asObject(v); - - // Heavy access to a prototype is a good indication that it's not being - // used as a dictionary. - if (o->structureID()->isDictionary()) { - RefPtr<StructureID> transition = StructureID::fromDictionaryTransition(o->structureID()); - o->setStructureID(transition.release()); - asObject(baseValue)->structureID()->setCachedPrototypeChain(0); - } - - ++count; + size_t count = countPrototypeChainEntriesAndCheckForProxies(callFrame, baseValue, slot); + if (!count) { + vPC[0] = getOpcode(op_get_by_id_generic); + return; } - StructureIDChain* chain = structureID->cachedPrototypeChain(); + StructureChain* chain = structure->cachedPrototypeChain(); if (!chain) - chain = cachePrototypeChain(callFrame, structureID); + chain = cachePrototypeChain(callFrame, structure); ASSERT(chain); vPC[0] = getOpcode(op_get_by_id_chain); - vPC[4] = structureID; + vPC[4] = structure; vPC[5] = chain; vPC[6] = count; vPC[7] = slot.cachedOffset(); - codeBlock->refStructureIDs(vPC); + codeBlock->refStructures(vPC); } -NEVER_INLINE void Machine::uncacheGetByID(CodeBlock* codeBlock, Instruction* vPC) +NEVER_INLINE void Interpreter::uncacheGetByID(CodeBlock* codeBlock, Instruction* vPC) { - codeBlock->derefStructureIDs(vPC); + codeBlock->derefStructures(vPC); vPC[0] = getOpcode(op_get_by_id); vPC[4] = 0; } -JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, CallFrame* callFrame, JSValue** exception) +JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, CallFrame* callFrame, JSValuePtr* exception) { // One-time initialization of our address tables. We have to put this code // here because our labels are only in scope inside this function. if (flag == InitializeAndReturn) { #if HAVE(COMPUTED_GOTO) - #define ADD_OPCODE(id) m_opcodeTable[id] = &&id; - FOR_EACH_OPCODE_ID(ADD_OPCODE); - #undef ADD_OPCODE + #define ADD_BYTECODE(id, length) m_opcodeTable[id] = &&id; + FOR_EACH_OPCODE_ID(ADD_BYTECODE); + #undef ADD_BYTECODE - #define ADD_OPCODE_ID(id) m_opcodeIDTable.add(&&id, id); + #define ADD_OPCODE_ID(id, length) m_opcodeIDTable.add(&&id, id); FOR_EACH_OPCODE_ID(ADD_OPCODE_ID); #undef ADD_OPCODE_ID ASSERT(m_opcodeIDTable.size() == numOpcodeIDs); - op_throw_end_indirect = &&op_throw_end; - op_call_indirect = &&op_call; #endif // HAVE(COMPUTED_GOTO) return noValue(); } -#if ENABLE(CTI) +#if ENABLE(JIT) // Currently with CTI enabled we never interpret functions ASSERT_NOT_REACHED(); #endif JSGlobalData* globalData = &callFrame->globalData(); - JSValue* exceptionValue = noValue(); - Instruction* handlerVPC = 0; + JSValuePtr exceptionValue = noValue(); + HandlerInfo* handler = 0; - Instruction* vPC = callFrame->codeBlock()->instructions.begin(); + Instruction* vPC = callFrame->codeBlock()->instructions().begin(); Profiler** enabledProfilerReference = Profiler::enabledProfilerReference(); unsigned tickCount = m_ticksUntilNextTimeoutCheck + 1; -#define VM_CHECK_EXCEPTION() \ +#define CHECK_FOR_EXCEPTION() \ do { \ if (UNLIKELY(globalData->exception != noValue())) { \ exceptionValue = globalData->exception; \ @@ -1487,52 +1433,54 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, #define CHECK_FOR_TIMEOUT() \ if (!--tickCount) { \ - if ((exceptionValue = checkTimeout(callFrame->dynamicGlobalObject()))) \ + if (checkTimeout(callFrame->dynamicGlobalObject())) { \ + exceptionValue = jsNull(); \ goto vm_throw; \ + } \ tickCount = m_ticksUntilNextTimeoutCheck; \ } #if ENABLE(OPCODE_SAMPLING) #define SAMPLE(codeBlock, vPC) m_sampler->sample(codeBlock, vPC) - #define CTI_SAMPLER ARG_globalData->machine->sampler() + #define CTI_SAMPLER ARG_globalData->interpreter->sampler() #else #define SAMPLE(codeBlock, vPC) #define CTI_SAMPLER 0 #endif #if HAVE(COMPUTED_GOTO) - #define NEXT_OPCODE SAMPLE(callFrame->codeBlock(), vPC); goto *vPC->u.opcode + #define NEXT_INSTRUCTION() SAMPLE(callFrame->codeBlock(), vPC); goto *vPC->u.opcode #if ENABLE(OPCODE_STATS) - #define BEGIN_OPCODE(opcode) opcode: OpcodeStats::recordInstruction(opcode); + #define DEFINE_OPCODE(opcode) opcode: OpcodeStats::recordInstruction(opcode); #else - #define BEGIN_OPCODE(opcode) opcode: + #define DEFINE_OPCODE(opcode) opcode: #endif - NEXT_OPCODE; + NEXT_INSTRUCTION(); #else - #define NEXT_OPCODE SAMPLE(callFrame->codeBlock(), vPC); goto interpreterLoopStart + #define NEXT_INSTRUCTION() SAMPLE(callFrame->codeBlock(), vPC); goto interpreterLoopStart #if ENABLE(OPCODE_STATS) - #define BEGIN_OPCODE(opcode) case opcode: OpcodeStats::recordInstruction(opcode); + #define DEFINE_OPCODE(opcode) case opcode: OpcodeStats::recordInstruction(opcode); #else - #define BEGIN_OPCODE(opcode) case opcode: + #define DEFINE_OPCODE(opcode) case opcode: #endif while (1) { // iterator loop begins interpreterLoopStart:; switch (vPC->u.opcode) #endif { - BEGIN_OPCODE(op_new_object) { + DEFINE_OPCODE(op_new_object) { /* new_object dst(r) Constructs a new empty Object instance using the original constructor, and puts the result in register dst. */ int dst = (++vPC)->u.operand; - callFrame[dst] = constructEmptyObject(callFrame); + callFrame[dst] = JSValuePtr(constructEmptyObject(callFrame)); ++vPC; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_new_array) { + DEFINE_OPCODE(op_new_array) { /* new_array dst(r) firstArg(r) argCount(n) Constructs a new Array instance using the original @@ -1544,12 +1492,12 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, int firstArg = (++vPC)->u.operand; int argCount = (++vPC)->u.operand; ArgList args(callFrame->registers() + firstArg, argCount); - callFrame[dst] = constructArray(callFrame, args); + callFrame[dst] = JSValuePtr(constructArray(callFrame, args)); ++vPC; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_new_regexp) { + DEFINE_OPCODE(op_new_regexp) { /* new_regexp dst(r) regExp(re) Constructs a new RegExp instance using the original @@ -1558,12 +1506,12 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, */ int dst = (++vPC)->u.operand; int regExp = (++vPC)->u.operand; - callFrame[dst] = new (globalData) RegExpObject(callFrame->scopeChain()->globalObject()->regExpStructure(), callFrame->codeBlock()->regexps[regExp]); + callFrame[dst] = JSValuePtr(new (globalData) RegExpObject(callFrame->scopeChain()->globalObject()->regExpStructure(), callFrame->codeBlock()->regexp(regExp))); ++vPC; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_mov) { + DEFINE_OPCODE(op_mov) { /* mov dst(r) src(r) Copies register src to register dst. @@ -1573,9 +1521,9 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, callFrame[dst] = callFrame[src]; ++vPC; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_eq) { + DEFINE_OPCODE(op_eq) { /* eq dst(r) src1(r) src2(r) Checks whether register src1 and register src2 are equal, @@ -1583,39 +1531,39 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, as a boolean in register dst. */ int dst = (++vPC)->u.operand; - JSValue* src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame); - JSValue* src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame); - if (JSImmediate::areBothImmediateNumbers(src1, src2)) - callFrame[dst] = jsBoolean(src1 == src2); + JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame); + JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame); + if (JSFastMath::canDoFastBitwiseOperations(src1, src2)) + callFrame[dst] = JSFastMath::equal(src1, src2); else { - JSValue* result = jsBoolean(equalSlowCase(callFrame, src1, src2)); - VM_CHECK_EXCEPTION(); + JSValuePtr result = jsBoolean(JSValuePtr::equalSlowCase(callFrame, src1, src2)); + CHECK_FOR_EXCEPTION(); callFrame[dst] = result; } ++vPC; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_eq_null) { + DEFINE_OPCODE(op_eq_null) { /* eq_null dst(r) src(r) Checks whether register src is null, as with the ECMAScript '!=' operator, and puts the result as a boolean in register dst. */ int dst = (++vPC)->u.operand; - JSValue* src = callFrame[(++vPC)->u.operand].jsValue(callFrame); + JSValuePtr src = callFrame[(++vPC)->u.operand].jsValue(callFrame); - if (src->isUndefinedOrNull()) { + if (src.isUndefinedOrNull()) { callFrame[dst] = jsBoolean(true); ++vPC; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - callFrame[dst] = jsBoolean(!JSImmediate::isImmediate(src) && src->asCell()->structureID()->typeInfo().masqueradesAsUndefined()); + callFrame[dst] = jsBoolean(src.isCell() && src.asCell()->structure()->typeInfo().masqueradesAsUndefined()); ++vPC; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_neq) { + DEFINE_OPCODE(op_neq) { /* neq dst(r) src1(r) src2(r) Checks whether register src1 and register src2 are not @@ -1623,39 +1571,39 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, result as a boolean in register dst. */ int dst = (++vPC)->u.operand; - JSValue* src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame); - JSValue* src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame); - if (JSImmediate::areBothImmediateNumbers(src1, src2)) - callFrame[dst] = jsBoolean(src1 != src2); + JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame); + JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame); + if (JSFastMath::canDoFastBitwiseOperations(src1, src2)) + callFrame[dst] = JSFastMath::notEqual(src1, src2); else { - JSValue* result = jsBoolean(!equalSlowCase(callFrame, src1, src2)); - VM_CHECK_EXCEPTION(); + JSValuePtr result = jsBoolean(!JSValuePtr::equalSlowCase(callFrame, src1, src2)); + CHECK_FOR_EXCEPTION(); callFrame[dst] = result; } ++vPC; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_neq_null) { + DEFINE_OPCODE(op_neq_null) { /* neq_null dst(r) src(r) Checks whether register src is not null, as with the ECMAScript '!=' operator, and puts the result as a boolean in register dst. */ int dst = (++vPC)->u.operand; - JSValue* src = callFrame[(++vPC)->u.operand].jsValue(callFrame); + JSValuePtr src = callFrame[(++vPC)->u.operand].jsValue(callFrame); - if (src->isUndefinedOrNull()) { + if (src.isUndefinedOrNull()) { callFrame[dst] = jsBoolean(false); ++vPC; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - callFrame[dst] = jsBoolean(JSImmediate::isImmediate(src) || !asCell(src)->structureID()->typeInfo().masqueradesAsUndefined()); + callFrame[dst] = jsBoolean(!src.isCell() || !asCell(src)->structure()->typeInfo().masqueradesAsUndefined()); ++vPC; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_stricteq) { + DEFINE_OPCODE(op_stricteq) { /* stricteq dst(r) src1(r) src2(r) Checks whether register src1 and register src2 are strictly @@ -1663,19 +1611,14 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, result as a boolean in register dst. */ int dst = (++vPC)->u.operand; - JSValue* src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame); - JSValue* src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame); - if (JSImmediate::areBothImmediate(src1, src2)) - callFrame[dst] = jsBoolean(src1 == src2); - else if (JSImmediate::isEitherImmediate(src1, src2) & (src1 != JSImmediate::zeroImmediate()) & (src2 != JSImmediate::zeroImmediate())) - callFrame[dst] = jsBoolean(false); - else - callFrame[dst] = jsBoolean(strictEqualSlowCase(src1, src2)); + JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame); + JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame); + callFrame[dst] = jsBoolean(JSValuePtr::strictEqual(src1, src2)); ++vPC; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_nstricteq) { + DEFINE_OPCODE(op_nstricteq) { /* nstricteq dst(r) src1(r) src2(r) Checks whether register src1 and register src2 are not @@ -1683,20 +1626,14 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, puts the result as a boolean in register dst. */ int dst = (++vPC)->u.operand; - JSValue* src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame); - JSValue* src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame); - - if (JSImmediate::areBothImmediate(src1, src2)) - callFrame[dst] = jsBoolean(src1 != src2); - else if (JSImmediate::isEitherImmediate(src1, src2) & (src1 != JSImmediate::zeroImmediate()) & (src2 != JSImmediate::zeroImmediate())) - callFrame[dst] = jsBoolean(true); - else - callFrame[dst] = jsBoolean(!strictEqualSlowCase(src1, src2)); + JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame); + JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame); + callFrame[dst] = jsBoolean(!JSValuePtr::strictEqual(src1, src2)); ++vPC; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_less) { + DEFINE_OPCODE(op_less) { /* less dst(r) src1(r) src2(r) Checks whether register src1 is less than register src2, as @@ -1704,16 +1641,16 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, a boolean in register dst. */ int dst = (++vPC)->u.operand; - JSValue* src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame); - JSValue* src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame); - JSValue* result = jsBoolean(jsLess(callFrame, src1, src2)); - VM_CHECK_EXCEPTION(); + JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame); + JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame); + JSValuePtr result = jsBoolean(jsLess(callFrame, src1, src2)); + CHECK_FOR_EXCEPTION(); callFrame[dst] = result; ++vPC; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_lesseq) { + DEFINE_OPCODE(op_lesseq) { /* lesseq dst(r) src1(r) src2(r) Checks whether register src1 is less than or equal to @@ -1721,54 +1658,54 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, puts the result as a boolean in register dst. */ int dst = (++vPC)->u.operand; - JSValue* src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame); - JSValue* src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame); - JSValue* result = jsBoolean(jsLessEq(callFrame, src1, src2)); - VM_CHECK_EXCEPTION(); + JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame); + JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame); + JSValuePtr result = jsBoolean(jsLessEq(callFrame, src1, src2)); + CHECK_FOR_EXCEPTION(); callFrame[dst] = result; ++vPC; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_pre_inc) { + DEFINE_OPCODE(op_pre_inc) { /* pre_inc srcDst(r) Converts register srcDst to number, adds one, and puts the result back in register srcDst. */ int srcDst = (++vPC)->u.operand; - JSValue* v = callFrame[srcDst].jsValue(callFrame); - if (JSImmediate::canDoFastAdditiveOperations(v)) - callFrame[srcDst] = JSImmediate::incImmediateNumber(v); + JSValuePtr v = callFrame[srcDst].jsValue(callFrame); + if (JSFastMath::canDoFastAdditiveOperations(v)) + callFrame[srcDst] = JSValuePtr(JSFastMath::incImmediateNumber(v)); else { - JSValue* result = jsNumber(callFrame, v->toNumber(callFrame) + 1); - VM_CHECK_EXCEPTION(); + JSValuePtr result = jsNumber(callFrame, v.toNumber(callFrame) + 1); + CHECK_FOR_EXCEPTION(); callFrame[srcDst] = result; } ++vPC; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_pre_dec) { + DEFINE_OPCODE(op_pre_dec) { /* pre_dec srcDst(r) Converts register srcDst to number, subtracts one, and puts the result back in register srcDst. */ int srcDst = (++vPC)->u.operand; - JSValue* v = callFrame[srcDst].jsValue(callFrame); - if (JSImmediate::canDoFastAdditiveOperations(v)) - callFrame[srcDst] = JSImmediate::decImmediateNumber(v); + JSValuePtr v = callFrame[srcDst].jsValue(callFrame); + if (JSFastMath::canDoFastAdditiveOperations(v)) + callFrame[srcDst] = JSValuePtr(JSFastMath::decImmediateNumber(v)); else { - JSValue* result = jsNumber(callFrame, v->toNumber(callFrame) - 1); - VM_CHECK_EXCEPTION(); + JSValuePtr result = jsNumber(callFrame, v.toNumber(callFrame) - 1); + CHECK_FOR_EXCEPTION(); callFrame[srcDst] = result; } ++vPC; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_post_inc) { + DEFINE_OPCODE(op_post_inc) { /* post_inc dst(r) srcDst(r) Converts register srcDst to number. The number itself is @@ -1777,21 +1714,21 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, */ int dst = (++vPC)->u.operand; int srcDst = (++vPC)->u.operand; - JSValue* v = callFrame[srcDst].jsValue(callFrame); - if (JSImmediate::canDoFastAdditiveOperations(v)) { + JSValuePtr v = callFrame[srcDst].jsValue(callFrame); + if (JSFastMath::canDoFastAdditiveOperations(v)) { callFrame[dst] = v; - callFrame[srcDst] = JSImmediate::incImmediateNumber(v); + callFrame[srcDst] = JSValuePtr(JSFastMath::incImmediateNumber(v)); } else { - JSValue* number = callFrame[srcDst].jsValue(callFrame)->toJSNumber(callFrame); - VM_CHECK_EXCEPTION(); + JSValuePtr number = callFrame[srcDst].jsValue(callFrame).toJSNumber(callFrame); + CHECK_FOR_EXCEPTION(); callFrame[dst] = number; - callFrame[srcDst] = jsNumber(callFrame, number->uncheckedGetNumber() + 1); + callFrame[srcDst] = JSValuePtr(jsNumber(callFrame, number.uncheckedGetNumber() + 1)); } ++vPC; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_post_dec) { + DEFINE_OPCODE(op_post_dec) { /* post_dec dst(r) srcDst(r) Converts register srcDst to number. The number itself is @@ -1800,21 +1737,21 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, */ int dst = (++vPC)->u.operand; int srcDst = (++vPC)->u.operand; - JSValue* v = callFrame[srcDst].jsValue(callFrame); - if (JSImmediate::canDoFastAdditiveOperations(v)) { + JSValuePtr v = callFrame[srcDst].jsValue(callFrame); + if (JSFastMath::canDoFastAdditiveOperations(v)) { callFrame[dst] = v; - callFrame[srcDst] = JSImmediate::decImmediateNumber(v); + callFrame[srcDst] = JSValuePtr(JSFastMath::decImmediateNumber(v)); } else { - JSValue* number = callFrame[srcDst].jsValue(callFrame)->toJSNumber(callFrame); - VM_CHECK_EXCEPTION(); + JSValuePtr number = callFrame[srcDst].jsValue(callFrame).toJSNumber(callFrame); + CHECK_FOR_EXCEPTION(); callFrame[dst] = number; - callFrame[srcDst] = jsNumber(callFrame, number->uncheckedGetNumber() - 1); + callFrame[srcDst] = JSValuePtr(jsNumber(callFrame, number.uncheckedGetNumber() - 1)); } ++vPC; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_to_jsnumber) { + DEFINE_OPCODE(op_to_jsnumber) { /* to_jsnumber dst(r) src(r) Converts register src to number, and puts the result @@ -1823,41 +1760,40 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, int dst = (++vPC)->u.operand; int src = (++vPC)->u.operand; - JSValue* srcVal = callFrame[src].jsValue(callFrame); + JSValuePtr srcVal = callFrame[src].jsValue(callFrame); - if (LIKELY(srcVal->isNumber())) + if (LIKELY(srcVal.isNumber())) callFrame[dst] = callFrame[src]; else { - JSValue* result = srcVal->toJSNumber(callFrame); - VM_CHECK_EXCEPTION(); + JSValuePtr result = srcVal.toJSNumber(callFrame); + CHECK_FOR_EXCEPTION(); callFrame[dst] = result; } ++vPC; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_negate) { + DEFINE_OPCODE(op_negate) { /* negate dst(r) src(r) Converts register src to number, negates it, and puts the result in register dst. */ int dst = (++vPC)->u.operand; - JSValue* src = callFrame[(++vPC)->u.operand].jsValue(callFrame); + JSValuePtr src = callFrame[(++vPC)->u.operand].jsValue(callFrame); ++vPC; double v; - if (fastIsNumber(src, v)) - callFrame[dst] = jsNumber(callFrame, -v); + if (src.getNumber(v)) + callFrame[dst] = JSValuePtr(jsNumber(callFrame, -v)); else { - JSValue* result = jsNumber(callFrame, -src->toNumber(callFrame)); - VM_CHECK_EXCEPTION(); + JSValuePtr result = jsNumber(callFrame, -src.toNumber(callFrame)); + CHECK_FOR_EXCEPTION(); callFrame[dst] = result; } - ++vPC; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_add) { + DEFINE_OPCODE(op_add) { /* add dst(r) src1(r) src2(r) Adds register src1 and register src2, and puts the result @@ -1865,48 +1801,48 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, numeric add, depending on the types of the operands.) */ int dst = (++vPC)->u.operand; - JSValue* src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame); - JSValue* src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame); - if (JSImmediate::canDoFastAdditiveOperations(src1) && JSImmediate::canDoFastAdditiveOperations(src2)) - callFrame[dst] = JSImmediate::addImmediateNumbers(src1, src2); + JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame); + JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame); + if (JSFastMath::canDoFastAdditiveOperations(src1, src2)) + callFrame[dst] = JSValuePtr(JSFastMath::addImmediateNumbers(src1, src2)); else { - JSValue* result = jsAdd(callFrame, src1, src2); - VM_CHECK_EXCEPTION(); + JSValuePtr result = jsAdd(callFrame, src1, src2); + CHECK_FOR_EXCEPTION(); callFrame[dst] = result; } vPC += 2; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_mul) { + DEFINE_OPCODE(op_mul) { /* mul dst(r) src1(r) src2(r) Multiplies register src1 and register src2 (converted to numbers), and puts the product in register dst. */ int dst = (++vPC)->u.operand; - JSValue* src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame); - JSValue* src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame); + JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame); + JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame); double left; double right; - if (JSImmediate::areBothImmediateNumbers(src1, src2)) { - int32_t left = JSImmediate::getTruncatedInt32(src1); - int32_t right = JSImmediate::getTruncatedInt32(src2); + if (JSValuePtr::areBothInt32Fast(src1, src2)) { + int32_t left = src1.getInt32Fast(); + int32_t right = src2.getInt32Fast(); if ((left | right) >> 15 == 0) - callFrame[dst] = jsNumber(callFrame, left * right); + callFrame[dst] = JSValuePtr(jsNumber(callFrame, left * right)); else - callFrame[dst] = jsNumber(callFrame, static_cast<double>(left) * static_cast<double>(right)); - } else if (fastIsNumber(src1, left) && fastIsNumber(src2, right)) - callFrame[dst] = jsNumber(callFrame, left * right); + callFrame[dst] = JSValuePtr(jsNumber(callFrame, static_cast<double>(left) * static_cast<double>(right))); + } else if (src1.getNumber(left) && src2.getNumber(right)) + callFrame[dst] = JSValuePtr(jsNumber(callFrame, left * right)); else { - JSValue* result = jsNumber(callFrame, src1->toNumber(callFrame) * src2->toNumber(callFrame)); - VM_CHECK_EXCEPTION(); + JSValuePtr result = jsNumber(callFrame, src1.toNumber(callFrame) * src2.toNumber(callFrame)); + CHECK_FOR_EXCEPTION(); callFrame[dst] = result; } vPC += 2; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_div) { + DEFINE_OPCODE(op_div) { /* div dst(r) dividend(r) divisor(r) Divides register dividend (converted to number) by the @@ -1914,21 +1850,21 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, quotient in register dst. */ int dst = (++vPC)->u.operand; - JSValue* dividend = callFrame[(++vPC)->u.operand].jsValue(callFrame); - JSValue* divisor = callFrame[(++vPC)->u.operand].jsValue(callFrame); + JSValuePtr dividend = callFrame[(++vPC)->u.operand].jsValue(callFrame); + JSValuePtr divisor = callFrame[(++vPC)->u.operand].jsValue(callFrame); double left; double right; - if (fastIsNumber(dividend, left) && fastIsNumber(divisor, right)) - callFrame[dst] = jsNumber(callFrame, left / right); + if (dividend.getNumber(left) && divisor.getNumber(right)) + callFrame[dst] = JSValuePtr(jsNumber(callFrame, left / right)); else { - JSValue* result = jsNumber(callFrame, dividend->toNumber(callFrame) / divisor->toNumber(callFrame)); - VM_CHECK_EXCEPTION(); + JSValuePtr result = jsNumber(callFrame, dividend.toNumber(callFrame) / divisor.toNumber(callFrame)); + CHECK_FOR_EXCEPTION(); callFrame[dst] = result; } ++vPC; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_mod) { + DEFINE_OPCODE(op_mod) { /* mod dst(r) dividend(r) divisor(r) Divides register dividend (converted to number) by @@ -1939,23 +1875,27 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, int dividend = (++vPC)->u.operand; int divisor = (++vPC)->u.operand; - JSValue* dividendValue = callFrame[dividend].jsValue(callFrame); - JSValue* divisorValue = callFrame[divisor].jsValue(callFrame); + JSValuePtr dividendValue = callFrame[dividend].jsValue(callFrame); + JSValuePtr divisorValue = callFrame[divisor].jsValue(callFrame); - if (JSImmediate::areBothImmediateNumbers(dividendValue, divisorValue) && divisorValue != JSImmediate::from(0)) { - callFrame[dst] = JSImmediate::from(JSImmediate::getTruncatedInt32(dividendValue) % JSImmediate::getTruncatedInt32(divisorValue)); + if (JSValuePtr::areBothInt32Fast(dividendValue, divisorValue) && divisorValue != js0()) { + // We expect the result of the modulus of a number that was representable as an int32 to also be representable + // as an int32. + JSValuePtr result = JSValuePtr::makeInt32Fast(dividendValue.getInt32Fast() % divisorValue.getInt32Fast()); + ASSERT(result); + callFrame[dst] = result; ++vPC; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - double d = dividendValue->toNumber(callFrame); - JSValue* result = jsNumber(callFrame, fmod(d, divisorValue->toNumber(callFrame))); - VM_CHECK_EXCEPTION(); + double d = dividendValue.toNumber(callFrame); + JSValuePtr result = jsNumber(callFrame, fmod(d, divisorValue.toNumber(callFrame))); + CHECK_FOR_EXCEPTION(); callFrame[dst] = result; ++vPC; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_sub) { + DEFINE_OPCODE(op_sub) { /* sub dst(r) src1(r) src2(r) Subtracts register src2 (converted to number) from register @@ -1963,23 +1903,23 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, register dst. */ int dst = (++vPC)->u.operand; - JSValue* src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame); - JSValue* src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame); + JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame); + JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame); double left; double right; - if (JSImmediate::canDoFastAdditiveOperations(src1) && JSImmediate::canDoFastAdditiveOperations(src2)) - callFrame[dst] = JSImmediate::subImmediateNumbers(src1, src2); - else if (fastIsNumber(src1, left) && fastIsNumber(src2, right)) - callFrame[dst] = jsNumber(callFrame, left - right); + if (JSFastMath::canDoFastAdditiveOperations(src1, src2)) + callFrame[dst] = JSValuePtr(JSFastMath::subImmediateNumbers(src1, src2)); + else if (src1.getNumber(left) && src2.getNumber(right)) + callFrame[dst] = JSValuePtr(jsNumber(callFrame, left - right)); else { - JSValue* result = jsNumber(callFrame, src1->toNumber(callFrame) - src2->toNumber(callFrame)); - VM_CHECK_EXCEPTION(); + JSValuePtr result = jsNumber(callFrame, src1.toNumber(callFrame) - src2.toNumber(callFrame)); + CHECK_FOR_EXCEPTION(); callFrame[dst] = result; } vPC += 2; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_lshift) { + DEFINE_OPCODE(op_lshift) { /* lshift dst(r) val(r) shift(r) Performs left shift of register val (converted to int32) by @@ -1987,24 +1927,24 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, in register dst. */ int dst = (++vPC)->u.operand; - JSValue* val = callFrame[(++vPC)->u.operand].jsValue(callFrame); - JSValue* shift = callFrame[(++vPC)->u.operand].jsValue(callFrame); + JSValuePtr val = callFrame[(++vPC)->u.operand].jsValue(callFrame); + JSValuePtr shift = callFrame[(++vPC)->u.operand].jsValue(callFrame); int32_t left; uint32_t right; - if (JSImmediate::areBothImmediateNumbers(val, shift)) - callFrame[dst] = jsNumber(callFrame, JSImmediate::getTruncatedInt32(val) << (JSImmediate::getTruncatedUInt32(shift) & 0x1f)); - else if (fastToInt32(val, left) && fastToUInt32(shift, right)) - callFrame[dst] = jsNumber(callFrame, left << (right & 0x1f)); + if (JSValuePtr::areBothInt32Fast(val, shift)) + callFrame[dst] = JSValuePtr(jsNumber(callFrame, val.getInt32Fast() << (shift.getInt32Fast() & 0x1f))); + else if (val.numberToInt32(left) && shift.numberToUInt32(right)) + callFrame[dst] = JSValuePtr(jsNumber(callFrame, left << (right & 0x1f))); else { - JSValue* result = jsNumber(callFrame, (val->toInt32(callFrame)) << (shift->toUInt32(callFrame) & 0x1f)); - VM_CHECK_EXCEPTION(); + JSValuePtr result = jsNumber(callFrame, (val.toInt32(callFrame)) << (shift.toUInt32(callFrame) & 0x1f)); + CHECK_FOR_EXCEPTION(); callFrame[dst] = result; } ++vPC; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_rshift) { + DEFINE_OPCODE(op_rshift) { /* rshift dst(r) val(r) shift(r) Performs arithmetic right shift of register val (converted @@ -2012,24 +1952,24 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, uint32), and puts the result in register dst. */ int dst = (++vPC)->u.operand; - JSValue* val = callFrame[(++vPC)->u.operand].jsValue(callFrame); - JSValue* shift = callFrame[(++vPC)->u.operand].jsValue(callFrame); + JSValuePtr val = callFrame[(++vPC)->u.operand].jsValue(callFrame); + JSValuePtr shift = callFrame[(++vPC)->u.operand].jsValue(callFrame); int32_t left; uint32_t right; - if (JSImmediate::areBothImmediateNumbers(val, shift)) - callFrame[dst] = JSImmediate::rightShiftImmediateNumbers(val, shift); - else if (fastToInt32(val, left) && fastToUInt32(shift, right)) - callFrame[dst] = jsNumber(callFrame, left >> (right & 0x1f)); + if (JSFastMath::canDoFastRshift(val, shift)) + callFrame[dst] = JSValuePtr(JSFastMath::rightShiftImmediateNumbers(val, shift)); + else if (val.numberToInt32(left) && shift.numberToUInt32(right)) + callFrame[dst] = JSValuePtr(jsNumber(callFrame, left >> (right & 0x1f))); else { - JSValue* result = jsNumber(callFrame, (val->toInt32(callFrame)) >> (shift->toUInt32(callFrame) & 0x1f)); - VM_CHECK_EXCEPTION(); + JSValuePtr result = jsNumber(callFrame, (val.toInt32(callFrame)) >> (shift.toUInt32(callFrame) & 0x1f)); + CHECK_FOR_EXCEPTION(); callFrame[dst] = result; } ++vPC; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_urshift) { + DEFINE_OPCODE(op_urshift) { /* rshift dst(r) val(r) shift(r) Performs logical right shift of register val (converted @@ -2037,20 +1977,20 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, uint32), and puts the result in register dst. */ int dst = (++vPC)->u.operand; - JSValue* val = callFrame[(++vPC)->u.operand].jsValue(callFrame); - JSValue* shift = callFrame[(++vPC)->u.operand].jsValue(callFrame); - if (JSImmediate::areBothImmediateNumbers(val, shift) && !JSImmediate::isNegative(val)) - callFrame[dst] = JSImmediate::rightShiftImmediateNumbers(val, shift); + JSValuePtr val = callFrame[(++vPC)->u.operand].jsValue(callFrame); + JSValuePtr shift = callFrame[(++vPC)->u.operand].jsValue(callFrame); + if (JSFastMath::canDoFastUrshift(val, shift)) + callFrame[dst] = JSValuePtr(JSFastMath::rightShiftImmediateNumbers(val, shift)); else { - JSValue* result = jsNumber(callFrame, (val->toUInt32(callFrame)) >> (shift->toUInt32(callFrame) & 0x1f)); - VM_CHECK_EXCEPTION(); + JSValuePtr result = jsNumber(callFrame, (val.toUInt32(callFrame)) >> (shift.toUInt32(callFrame) & 0x1f)); + CHECK_FOR_EXCEPTION(); callFrame[dst] = result; } ++vPC; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_bitand) { + DEFINE_OPCODE(op_bitand) { /* bitand dst(r) src1(r) src2(r) Computes bitwise AND of register src1 (converted to int32) @@ -2058,24 +1998,24 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, in register dst. */ int dst = (++vPC)->u.operand; - JSValue* src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame); - JSValue* src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame); + JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame); + JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame); int32_t left; int32_t right; - if (JSImmediate::areBothImmediateNumbers(src1, src2)) - callFrame[dst] = JSImmediate::andImmediateNumbers(src1, src2); - else if (fastToInt32(src1, left) && fastToInt32(src2, right)) - callFrame[dst] = jsNumber(callFrame, left & right); + if (JSFastMath::canDoFastBitwiseOperations(src1, src2)) + callFrame[dst] = JSValuePtr(JSFastMath::andImmediateNumbers(src1, src2)); + else if (src1.numberToInt32(left) && src2.numberToInt32(right)) + callFrame[dst] = JSValuePtr(jsNumber(callFrame, left & right)); else { - JSValue* result = jsNumber(callFrame, src1->toInt32(callFrame) & src2->toInt32(callFrame)); - VM_CHECK_EXCEPTION(); + JSValuePtr result = jsNumber(callFrame, src1.toInt32(callFrame) & src2.toInt32(callFrame)); + CHECK_FOR_EXCEPTION(); callFrame[dst] = result; } vPC += 2; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_bitxor) { + DEFINE_OPCODE(op_bitxor) { /* bitxor dst(r) src1(r) src2(r) Computes bitwise XOR of register src1 (converted to int32) @@ -2083,24 +2023,24 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, in register dst. */ int dst = (++vPC)->u.operand; - JSValue* src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame); - JSValue* src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame); + JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame); + JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame); int32_t left; int32_t right; - if (JSImmediate::areBothImmediateNumbers(src1, src2)) - callFrame[dst] = JSImmediate::xorImmediateNumbers(src1, src2); - else if (fastToInt32(src1, left) && fastToInt32(src2, right)) - callFrame[dst] = jsNumber(callFrame, left ^ right); + if (JSFastMath::canDoFastBitwiseOperations(src1, src2)) + callFrame[dst] = JSValuePtr(JSFastMath::xorImmediateNumbers(src1, src2)); + else if (src1.numberToInt32(left) && src2.numberToInt32(right)) + callFrame[dst] = JSValuePtr(jsNumber(callFrame, left ^ right)); else { - JSValue* result = jsNumber(callFrame, src1->toInt32(callFrame) ^ src2->toInt32(callFrame)); - VM_CHECK_EXCEPTION(); + JSValuePtr result = jsNumber(callFrame, src1.toInt32(callFrame) ^ src2.toInt32(callFrame)); + CHECK_FOR_EXCEPTION(); callFrame[dst] = result; } vPC += 2; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_bitor) { + DEFINE_OPCODE(op_bitor) { /* bitor dst(r) src1(r) src2(r) Computes bitwise OR of register src1 (converted to int32) @@ -2108,43 +2048,43 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, result in register dst. */ int dst = (++vPC)->u.operand; - JSValue* src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame); - JSValue* src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame); + JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame); + JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame); int32_t left; int32_t right; - if (JSImmediate::areBothImmediateNumbers(src1, src2)) - callFrame[dst] = JSImmediate::orImmediateNumbers(src1, src2); - else if (fastToInt32(src1, left) && fastToInt32(src2, right)) - callFrame[dst] = jsNumber(callFrame, left | right); + if (JSFastMath::canDoFastBitwiseOperations(src1, src2)) + callFrame[dst] = JSValuePtr(JSFastMath::orImmediateNumbers(src1, src2)); + else if (src1.numberToInt32(left) && src2.numberToInt32(right)) + callFrame[dst] = JSValuePtr(jsNumber(callFrame, left | right)); else { - JSValue* result = jsNumber(callFrame, src1->toInt32(callFrame) | src2->toInt32(callFrame)); - VM_CHECK_EXCEPTION(); + JSValuePtr result = jsNumber(callFrame, src1.toInt32(callFrame) | src2.toInt32(callFrame)); + CHECK_FOR_EXCEPTION(); callFrame[dst] = result; } vPC += 2; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_bitnot) { + DEFINE_OPCODE(op_bitnot) { /* bitnot dst(r) src(r) Computes bitwise NOT of register src1 (converted to int32), and puts the result in register dst. */ int dst = (++vPC)->u.operand; - JSValue* src = callFrame[(++vPC)->u.operand].jsValue(callFrame); + JSValuePtr src = callFrame[(++vPC)->u.operand].jsValue(callFrame); int32_t value; - if (fastToInt32(src, value)) - callFrame[dst] = jsNumber(callFrame, ~value); + if (src.numberToInt32(value)) + callFrame[dst] = JSValuePtr(jsNumber(callFrame, ~value)); else { - JSValue* result = jsNumber(callFrame, ~src->toInt32(callFrame)); - VM_CHECK_EXCEPTION(); + JSValuePtr result = jsNumber(callFrame, ~src.toInt32(callFrame)); + CHECK_FOR_EXCEPTION(); callFrame[dst] = result; } ++vPC; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_not) { + DEFINE_OPCODE(op_not) { /* not dst(r) src(r) Computes logical NOT of register src (converted to @@ -2152,14 +2092,14 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, */ int dst = (++vPC)->u.operand; int src = (++vPC)->u.operand; - JSValue* result = jsBoolean(!callFrame[src].jsValue(callFrame)->toBoolean(callFrame)); - VM_CHECK_EXCEPTION(); + JSValuePtr result = jsBoolean(!callFrame[src].jsValue(callFrame).toBoolean(callFrame)); + CHECK_FOR_EXCEPTION(); callFrame[dst] = result; ++vPC; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_instanceof) { + DEFINE_OPCODE(op_instanceof) { /* instanceof dst(r) value(r) constructor(r) constructorProto(r) Tests whether register value is an instance of register @@ -2177,18 +2117,18 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, int base = vPC[3].u.operand; int baseProto = vPC[4].u.operand; - JSValue* baseVal = callFrame[base].jsValue(callFrame); + JSValuePtr baseVal = callFrame[base].jsValue(callFrame); if (isNotObject(callFrame, true, callFrame->codeBlock(), vPC, baseVal, exceptionValue)) goto vm_throw; JSObject* baseObj = asObject(baseVal); - callFrame[dst] = jsBoolean(baseObj->structureID()->typeInfo().implementsHasInstance() ? baseObj->hasInstance(callFrame, callFrame[value].jsValue(callFrame), callFrame[baseProto].jsValue(callFrame)) : false); + callFrame[dst] = jsBoolean(baseObj->structure()->typeInfo().implementsHasInstance() ? baseObj->hasInstance(callFrame, callFrame[value].jsValue(callFrame), callFrame[baseProto].jsValue(callFrame)) : false); vPC += 5; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_typeof) { + DEFINE_OPCODE(op_typeof) { /* typeof dst(r) src(r) Determines the type string for src according to ECMAScript @@ -2196,12 +2136,12 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, */ int dst = (++vPC)->u.operand; int src = (++vPC)->u.operand; - callFrame[dst] = jsTypeStringForValue(callFrame, callFrame[src].jsValue(callFrame)); + callFrame[dst] = JSValuePtr(jsTypeStringForValue(callFrame, callFrame[src].jsValue(callFrame))); ++vPC; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_is_undefined) { + DEFINE_OPCODE(op_is_undefined) { /* is_undefined dst(r) src(r) Determines whether the type string for src according to @@ -2210,13 +2150,13 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, */ int dst = (++vPC)->u.operand; int src = (++vPC)->u.operand; - JSValue* v = callFrame[src].jsValue(callFrame); - callFrame[dst] = jsBoolean(JSImmediate::isImmediate(v) ? v->isUndefined() : v->asCell()->structureID()->typeInfo().masqueradesAsUndefined()); + JSValuePtr v = callFrame[src].jsValue(callFrame); + callFrame[dst] = jsBoolean(v.isCell() ? v.asCell()->structure()->typeInfo().masqueradesAsUndefined() : v.isUndefined()); ++vPC; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_is_boolean) { + DEFINE_OPCODE(op_is_boolean) { /* is_boolean dst(r) src(r) Determines whether the type string for src according to @@ -2225,12 +2165,12 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, */ int dst = (++vPC)->u.operand; int src = (++vPC)->u.operand; - callFrame[dst] = jsBoolean(callFrame[src].jsValue(callFrame)->isBoolean()); + callFrame[dst] = jsBoolean(callFrame[src].jsValue(callFrame).isBoolean()); ++vPC; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_is_number) { + DEFINE_OPCODE(op_is_number) { /* is_number dst(r) src(r) Determines whether the type string for src according to @@ -2239,12 +2179,12 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, */ int dst = (++vPC)->u.operand; int src = (++vPC)->u.operand; - callFrame[dst] = jsBoolean(callFrame[src].jsValue(callFrame)->isNumber()); + callFrame[dst] = jsBoolean(callFrame[src].jsValue(callFrame).isNumber()); ++vPC; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_is_string) { + DEFINE_OPCODE(op_is_string) { /* is_string dst(r) src(r) Determines whether the type string for src according to @@ -2253,12 +2193,12 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, */ int dst = (++vPC)->u.operand; int src = (++vPC)->u.operand; - callFrame[dst] = jsBoolean(callFrame[src].jsValue(callFrame)->isString()); + callFrame[dst] = jsBoolean(callFrame[src].jsValue(callFrame).isString()); ++vPC; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_is_object) { + DEFINE_OPCODE(op_is_object) { /* is_object dst(r) src(r) Determines whether the type string for src according to @@ -2270,9 +2210,9 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, callFrame[dst] = jsBoolean(jsIsObjectType(callFrame[src].jsValue(callFrame))); ++vPC; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_is_function) { + DEFINE_OPCODE(op_is_function) { /* is_function dst(r) src(r) Determines whether the type string for src according to @@ -2284,9 +2224,9 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, callFrame[dst] = jsBoolean(jsIsFunctionType(callFrame[src].jsValue(callFrame))); ++vPC; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_in) { + DEFINE_OPCODE(op_in) { /* in dst(r) property(r) base(r) Tests whether register base has a property named register @@ -2299,27 +2239,27 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, int property = (++vPC)->u.operand; int base = (++vPC)->u.operand; - JSValue* baseVal = callFrame[base].jsValue(callFrame); + JSValuePtr baseVal = callFrame[base].jsValue(callFrame); if (isNotObject(callFrame, false, callFrame->codeBlock(), vPC, baseVal, exceptionValue)) goto vm_throw; JSObject* baseObj = asObject(baseVal); - JSValue* propName = callFrame[property].jsValue(callFrame); + JSValuePtr propName = callFrame[property].jsValue(callFrame); uint32_t i; - if (propName->getUInt32(i)) + if (propName.getUInt32(i)) callFrame[dst] = jsBoolean(baseObj->hasProperty(callFrame, i)); else { - Identifier property(callFrame, propName->toString(callFrame)); - VM_CHECK_EXCEPTION(); + Identifier property(callFrame, propName.toString(callFrame)); + CHECK_FOR_EXCEPTION(); callFrame[dst] = jsBoolean(baseObj->hasProperty(callFrame, property)); } ++vPC; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_resolve) { + DEFINE_OPCODE(op_resolve) { /* resolve dst(r) property(id) Looks up the property named by identifier property in the @@ -2330,9 +2270,9 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, goto vm_throw; vPC += 3; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_resolve_skip) { + DEFINE_OPCODE(op_resolve_skip) { /* resolve_skip dst(r) property(id) skip(n) Looks up the property named by identifier property in the @@ -2344,24 +2284,24 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, vPC += 4; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_resolve_global) { - /* resolve_skip dst(r) globalObject(c) property(id) structureID(sID) offset(n) + DEFINE_OPCODE(op_resolve_global) { + /* resolve_skip dst(r) globalObject(c) property(id) structure(sID) offset(n) Performs a dynamic property lookup for the given property, on the provided - global object. If structureID matches the StructureID of the global then perform + global object. If structure matches the Structure of the global then perform a fast lookup using the case offset, otherwise fall back to a full resolve and - cache the new structureID and offset + cache the new structure and offset */ if (UNLIKELY(!resolveGlobal(callFrame, vPC, exceptionValue))) goto vm_throw; vPC += 6; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_get_global_var) { + DEFINE_OPCODE(op_get_global_var) { /* get_global_var dst(r) globalObject(c) index(n) Gets the global var at global slot index and places it in register dst. @@ -2373,9 +2313,9 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, callFrame[dst] = scope->registerAt(index); ++vPC; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_put_global_var) { + DEFINE_OPCODE(op_put_global_var) { /* put_global_var globalObject(c) index(n) value(r) Puts value into global slot index. @@ -2385,11 +2325,11 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, int index = (++vPC)->u.operand; int value = (++vPC)->u.operand; - scope->registerAt(index) = callFrame[value].jsValue(callFrame); + scope->registerAt(index) = JSValuePtr(callFrame[value].jsValue(callFrame)); ++vPC; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_get_scoped_var) { + DEFINE_OPCODE(op_get_scoped_var) { /* get_scoped_var dst(r) index(n) skip(n) Loads the contents of the index-th local from the scope skip nodes from @@ -2397,7 +2337,7 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, */ int dst = (++vPC)->u.operand; int index = (++vPC)->u.operand; - int skip = (++vPC)->u.operand + callFrame->codeBlock()->needsFullScopeChain; + int skip = (++vPC)->u.operand + callFrame->codeBlock()->needsFullScopeChain(); ScopeChainNode* scopeChain = callFrame->scopeChain(); ScopeChainIterator iter = scopeChain->begin(); @@ -2412,14 +2352,14 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, JSVariableObject* scope = static_cast<JSVariableObject*>(*iter); callFrame[dst] = scope->registerAt(index); ++vPC; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_put_scoped_var) { + DEFINE_OPCODE(op_put_scoped_var) { /* put_scoped_var index(n) skip(n) value(r) */ int index = (++vPC)->u.operand; - int skip = (++vPC)->u.operand + callFrame->codeBlock()->needsFullScopeChain; + int skip = (++vPC)->u.operand + callFrame->codeBlock()->needsFullScopeChain(); int value = (++vPC)->u.operand; ScopeChainNode* scopeChain = callFrame->scopeChain(); @@ -2433,11 +2373,11 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, ASSERT((*iter)->isVariableObject()); JSVariableObject* scope = static_cast<JSVariableObject*>(*iter); - scope->registerAt(index) = callFrame[value].jsValue(callFrame); + scope->registerAt(index) = JSValuePtr(callFrame[value].jsValue(callFrame)); ++vPC; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_resolve_base) { + DEFINE_OPCODE(op_resolve_base) { /* resolve_base dst(r) property(id) Searches the scope chain for an object containing @@ -2448,9 +2388,9 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, resolveBase(callFrame, vPC); vPC += 3; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_resolve_with_base) { + DEFINE_OPCODE(op_resolve_with_base) { /* resolve_with_base baseDst(r) propDst(r) property(id) Searches the scope chain for an object containing @@ -2466,9 +2406,9 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, goto vm_throw; vPC += 4; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_resolve_func) { + DEFINE_OPCODE(op_resolve_func) { /* resolve_func baseDst(r) funcDst(r) property(id) Searches the scope chain for an object containing @@ -2487,10 +2427,10 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, goto vm_throw; vPC += 4; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_get_by_id) { - /* get_by_id dst(r) base(r) property(id) structureID(sID) nop(n) nop(n) nop(n) + DEFINE_OPCODE(op_get_by_id) { + /* get_by_id dst(r) base(r) property(id) structure(sID) nop(n) nop(n) nop(n) Generic property access: Gets the property named by identifier property from the value base, and puts the result in register dst. @@ -2500,127 +2440,144 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, int property = vPC[3].u.operand; CodeBlock* codeBlock = callFrame->codeBlock(); - Identifier& ident = codeBlock->identifiers[property]; - JSValue* baseValue = callFrame[base].jsValue(callFrame); + Identifier& ident = codeBlock->identifier(property); + JSValuePtr baseValue = callFrame[base].jsValue(callFrame); PropertySlot slot(baseValue); - JSValue* result = baseValue->get(callFrame, ident, slot); - VM_CHECK_EXCEPTION(); + JSValuePtr result = baseValue.get(callFrame, ident, slot); + CHECK_FOR_EXCEPTION(); tryCacheGetByID(callFrame, codeBlock, vPC, baseValue, ident, slot); callFrame[dst] = result; vPC += 8; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_get_by_id_self) { - /* op_get_by_id_self dst(r) base(r) property(id) structureID(sID) offset(n) nop(n) nop(n) + DEFINE_OPCODE(op_get_by_id_self) { + /* op_get_by_id_self dst(r) base(r) property(id) structure(sID) offset(n) nop(n) nop(n) Cached property access: Attempts to get a cached property from the value base. If the cache misses, op_get_by_id_self reverts to op_get_by_id. */ int base = vPC[2].u.operand; - JSValue* baseValue = callFrame[base].jsValue(callFrame); + JSValuePtr baseValue = callFrame[base].jsValue(callFrame); - if (LIKELY(!JSImmediate::isImmediate(baseValue))) { + if (LIKELY(baseValue.isCell())) { JSCell* baseCell = asCell(baseValue); - StructureID* structureID = vPC[4].u.structureID; + Structure* structure = vPC[4].u.structure; - if (LIKELY(baseCell->structureID() == structureID)) { + if (LIKELY(baseCell->structure() == structure)) { ASSERT(baseCell->isObject()); JSObject* baseObject = asObject(baseCell); int dst = vPC[1].u.operand; int offset = vPC[5].u.operand; - ASSERT(baseObject->get(callFrame, callFrame->codeBlock()->identifiers[vPC[3].u.operand]) == baseObject->getDirectOffset(offset)); - callFrame[dst] = baseObject->getDirectOffset(offset); + ASSERT(baseObject->get(callFrame, callFrame->codeBlock()->identifier(vPC[3].u.operand)) == baseObject->getDirectOffset(offset)); + callFrame[dst] = JSValuePtr(baseObject->getDirectOffset(offset)); vPC += 8; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } } uncacheGetByID(callFrame->codeBlock(), vPC); - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_get_by_id_proto) { - /* op_get_by_id_proto dst(r) base(r) property(id) structureID(sID) protoStructureID(sID) offset(n) nop(n) + DEFINE_OPCODE(op_get_by_id_proto) { + /* op_get_by_id_proto dst(r) base(r) property(id) structure(sID) prototypeStructure(sID) offset(n) nop(n) Cached property access: Attempts to get a cached property from the value base's prototype. If the cache misses, op_get_by_id_proto reverts to op_get_by_id. */ int base = vPC[2].u.operand; - JSValue* baseValue = callFrame[base].jsValue(callFrame); + JSValuePtr baseValue = callFrame[base].jsValue(callFrame); - if (LIKELY(!JSImmediate::isImmediate(baseValue))) { + if (LIKELY(baseValue.isCell())) { JSCell* baseCell = asCell(baseValue); - StructureID* structureID = vPC[4].u.structureID; + Structure* structure = vPC[4].u.structure; - if (LIKELY(baseCell->structureID() == structureID)) { - ASSERT(structureID->prototypeForLookup(callFrame)->isObject()); - JSObject* protoObject = asObject(structureID->prototypeForLookup(callFrame)); - StructureID* protoStructureID = vPC[5].u.structureID; + if (LIKELY(baseCell->structure() == structure)) { + ASSERT(structure->prototypeForLookup(callFrame).isObject()); + JSObject* protoObject = asObject(structure->prototypeForLookup(callFrame)); + Structure* prototypeStructure = vPC[5].u.structure; - if (LIKELY(protoObject->structureID() == protoStructureID)) { + if (LIKELY(protoObject->structure() == prototypeStructure)) { int dst = vPC[1].u.operand; int offset = vPC[6].u.operand; - ASSERT(protoObject->get(callFrame, callFrame->codeBlock()->identifiers[vPC[3].u.operand]) == protoObject->getDirectOffset(offset)); - callFrame[dst] = protoObject->getDirectOffset(offset); + ASSERT(protoObject->get(callFrame, callFrame->codeBlock()->identifier(vPC[3].u.operand)) == protoObject->getDirectOffset(offset)); + callFrame[dst] = JSValuePtr(protoObject->getDirectOffset(offset)); vPC += 8; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } } } uncacheGetByID(callFrame->codeBlock(), vPC); - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_get_by_id_chain) { - /* op_get_by_id_chain dst(r) base(r) property(id) structureID(sID) structureIDChain(sIDc) count(n) offset(n) + DEFINE_OPCODE(op_get_by_id_self_list) { + // Polymorphic self access caching currently only supported when JITting. + ASSERT_NOT_REACHED(); + // This case of the switch must not be empty, else (op_get_by_id_self_list == op_get_by_id_chain)! + vPC += 8; + NEXT_INSTRUCTION(); + } + DEFINE_OPCODE(op_get_by_id_proto_list) { + // Polymorphic prototype access caching currently only supported when JITting. + ASSERT_NOT_REACHED(); + // This case of the switch must not be empty, else (op_get_by_id_proto_list == op_get_by_id_chain)! + vPC += 8; + NEXT_INSTRUCTION(); + } + DEFINE_OPCODE(op_get_by_id_chain) { + /* op_get_by_id_chain dst(r) base(r) property(id) structure(sID) structureChain(chain) count(n) offset(n) Cached property access: Attempts to get a cached property from the value base's prototype chain. If the cache misses, op_get_by_id_chain reverts to op_get_by_id. */ int base = vPC[2].u.operand; - JSValue* baseValue = callFrame[base].jsValue(callFrame); + JSValuePtr baseValue = callFrame[base].jsValue(callFrame); - if (LIKELY(!JSImmediate::isImmediate(baseValue))) { + if (LIKELY(baseValue.isCell())) { JSCell* baseCell = asCell(baseValue); - StructureID* structureID = vPC[4].u.structureID; + Structure* structure = vPC[4].u.structure; - if (LIKELY(baseCell->structureID() == structureID)) { - RefPtr<StructureID>* it = vPC[5].u.structureIDChain->head(); + if (LIKELY(baseCell->structure() == structure)) { + RefPtr<Structure>* it = vPC[5].u.structureChain->head(); size_t count = vPC[6].u.operand; - RefPtr<StructureID>* end = it + count; + RefPtr<Structure>* end = it + count; - JSObject* baseObject = asObject(baseCell); - while (1) { - baseObject = asObject(baseObject->structureID()->prototypeForLookup(callFrame)); - if (UNLIKELY(baseObject->structureID() != (*it).get())) + while (true) { + JSObject* baseObject = asObject(baseCell->structure()->prototypeForLookup(callFrame)); + + if (UNLIKELY(baseObject->structure() != (*it).get())) break; if (++it == end) { int dst = vPC[1].u.operand; int offset = vPC[7].u.operand; - ASSERT(baseObject->get(callFrame, callFrame->codeBlock()->identifiers[vPC[3].u.operand]) == baseObject->getDirectOffset(offset)); - callFrame[dst] = baseObject->getDirectOffset(offset); + ASSERT(baseObject->get(callFrame, callFrame->codeBlock()->identifier(vPC[3].u.operand)) == baseObject->getDirectOffset(offset)); + callFrame[dst] = JSValuePtr(baseObject->getDirectOffset(offset)); vPC += 8; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } + + // Update baseCell, so that next time around the loop we'll pick up the prototype's prototype. + baseCell = baseObject; } } } uncacheGetByID(callFrame->codeBlock(), vPC); - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_get_by_id_generic) { + DEFINE_OPCODE(op_get_by_id_generic) { /* op_get_by_id_generic dst(r) base(r) property(id) nop(sID) nop(n) nop(n) nop(n) Generic property access: Gets the property named by identifier @@ -2630,17 +2587,17 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, int base = vPC[2].u.operand; int property = vPC[3].u.operand; - Identifier& ident = callFrame->codeBlock()->identifiers[property]; - JSValue* baseValue = callFrame[base].jsValue(callFrame); + Identifier& ident = callFrame->codeBlock()->identifier(property); + JSValuePtr baseValue = callFrame[base].jsValue(callFrame); PropertySlot slot(baseValue); - JSValue* result = baseValue->get(callFrame, ident, slot); - VM_CHECK_EXCEPTION(); + JSValuePtr result = baseValue.get(callFrame, ident, slot); + CHECK_FOR_EXCEPTION(); callFrame[dst] = result; vPC += 8; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_get_array_length) { + DEFINE_OPCODE(op_get_array_length) { /* op_get_array_length dst(r) base(r) property(id) nop(sID) nop(n) nop(n) nop(n) Cached property access: Gets the length of the array in register base, @@ -2649,18 +2606,18 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, */ int base = vPC[2].u.operand; - JSValue* baseValue = callFrame[base].jsValue(callFrame); + JSValuePtr baseValue = callFrame[base].jsValue(callFrame); if (LIKELY(isJSArray(baseValue))) { int dst = vPC[1].u.operand; - callFrame[dst] = jsNumber(callFrame, asArray(baseValue)->length()); + callFrame[dst] = JSValuePtr(jsNumber(callFrame, asArray(baseValue)->length())); vPC += 8; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } uncacheGetByID(callFrame->codeBlock(), vPC); - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_get_string_length) { + DEFINE_OPCODE(op_get_string_length) { /* op_get_string_length dst(r) base(r) property(id) nop(sID) nop(n) nop(n) nop(n) Cached property access: Gets the length of the string in register base, @@ -2669,18 +2626,18 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, */ int base = vPC[2].u.operand; - JSValue* baseValue = callFrame[base].jsValue(callFrame); + JSValuePtr baseValue = callFrame[base].jsValue(callFrame); if (LIKELY(isJSString(baseValue))) { int dst = vPC[1].u.operand; - callFrame[dst] = jsNumber(callFrame, asString(baseValue)->value().size()); + callFrame[dst] = JSValuePtr(jsNumber(callFrame, asString(baseValue)->value().size())); vPC += 8; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } uncacheGetByID(callFrame->codeBlock(), vPC); - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_put_by_id) { + DEFINE_OPCODE(op_put_by_id) { /* put_by_id base(r) property(id) value(r) nop(n) nop(n) nop(n) nop(n) Generic property access: Sets the property named by identifier @@ -2695,19 +2652,19 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, int value = vPC[3].u.operand; CodeBlock* codeBlock = callFrame->codeBlock(); - JSValue* baseValue = callFrame[base].jsValue(callFrame); - Identifier& ident = codeBlock->identifiers[property]; + JSValuePtr baseValue = callFrame[base].jsValue(callFrame); + Identifier& ident = codeBlock->identifier(property); PutPropertySlot slot; - baseValue->put(callFrame, ident, callFrame[value].jsValue(callFrame), slot); - VM_CHECK_EXCEPTION(); + baseValue.put(callFrame, ident, callFrame[value].jsValue(callFrame), slot); + CHECK_FOR_EXCEPTION(); tryCachePutByID(callFrame, codeBlock, vPC, baseValue, slot); vPC += 8; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_put_by_id_transition) { - /* op_put_by_id_transition base(r) property(id) value(r) oldStructureID(sID) newStructureID(sID) structureIDChain(sIDc) offset(n) + DEFINE_OPCODE(op_put_by_id_transition) { + /* op_put_by_id_transition base(r) property(id) value(r) oldStructure(sID) newStructure(sID) structureChain(chain) offset(n) Cached property access: Attempts to set a new property with a cached transition property named by identifier property, belonging to register base, @@ -2718,46 +2675,46 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, the register file. */ int base = vPC[1].u.operand; - JSValue* baseValue = callFrame[base].jsValue(callFrame); + JSValuePtr baseValue = callFrame[base].jsValue(callFrame); - if (LIKELY(!JSImmediate::isImmediate(baseValue))) { + if (LIKELY(baseValue.isCell())) { JSCell* baseCell = asCell(baseValue); - StructureID* oldStructureID = vPC[4].u.structureID; - StructureID* newStructureID = vPC[5].u.structureID; + Structure* oldStructure = vPC[4].u.structure; + Structure* newStructure = vPC[5].u.structure; - if (LIKELY(baseCell->structureID() == oldStructureID)) { + if (LIKELY(baseCell->structure() == oldStructure)) { ASSERT(baseCell->isObject()); JSObject* baseObject = asObject(baseCell); - RefPtr<StructureID>* it = vPC[6].u.structureIDChain->head(); + RefPtr<Structure>* it = vPC[6].u.structureChain->head(); - JSValue* proto = baseObject->structureID()->prototypeForLookup(callFrame); - while (!proto->isNull()) { - if (UNLIKELY(asObject(proto)->structureID() != (*it).get())) { + JSValuePtr proto = baseObject->structure()->prototypeForLookup(callFrame); + while (!proto.isNull()) { + if (UNLIKELY(asObject(proto)->structure() != (*it).get())) { uncachePutByID(callFrame->codeBlock(), vPC); - NEXT_OPCODE; + NEXT_INSTRUCTION(); } ++it; - proto = asObject(proto)->structureID()->prototypeForLookup(callFrame); + proto = asObject(proto)->structure()->prototypeForLookup(callFrame); } - baseObject->transitionTo(newStructureID); + baseObject->transitionTo(newStructure); int value = vPC[3].u.operand; unsigned offset = vPC[7].u.operand; - ASSERT(baseObject->offsetForLocation(baseObject->getDirectLocation(callFrame->codeBlock()->identifiers[vPC[2].u.operand])) == offset); + ASSERT(baseObject->offsetForLocation(baseObject->getDirectLocation(callFrame->codeBlock()->identifier(vPC[2].u.operand))) == offset); baseObject->putDirectOffset(offset, callFrame[value].jsValue(callFrame)); vPC += 8; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } } uncachePutByID(callFrame->codeBlock(), vPC); - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_put_by_id_replace) { - /* op_put_by_id_replace base(r) property(id) value(r) structureID(sID) offset(n) nop(n) nop(n) + DEFINE_OPCODE(op_put_by_id_replace) { + /* op_put_by_id_replace base(r) property(id) value(r) structure(sID) offset(n) nop(n) nop(n) Cached property access: Attempts to set a pre-existing, cached property named by identifier property, belonging to register base, @@ -2768,30 +2725,30 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, the register file. */ int base = vPC[1].u.operand; - JSValue* baseValue = callFrame[base].jsValue(callFrame); + JSValuePtr baseValue = callFrame[base].jsValue(callFrame); - if (LIKELY(!JSImmediate::isImmediate(baseValue))) { + if (LIKELY(baseValue.isCell())) { JSCell* baseCell = asCell(baseValue); - StructureID* structureID = vPC[4].u.structureID; + Structure* structure = vPC[4].u.structure; - if (LIKELY(baseCell->structureID() == structureID)) { + if (LIKELY(baseCell->structure() == structure)) { ASSERT(baseCell->isObject()); JSObject* baseObject = asObject(baseCell); int value = vPC[3].u.operand; unsigned offset = vPC[5].u.operand; - ASSERT(baseObject->offsetForLocation(baseObject->getDirectLocation(callFrame->codeBlock()->identifiers[vPC[2].u.operand])) == offset); + ASSERT(baseObject->offsetForLocation(baseObject->getDirectLocation(callFrame->codeBlock()->identifier(vPC[2].u.operand))) == offset); baseObject->putDirectOffset(offset, callFrame[value].jsValue(callFrame)); vPC += 8; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } } uncachePutByID(callFrame->codeBlock(), vPC); - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_put_by_id_generic) { + DEFINE_OPCODE(op_put_by_id_generic) { /* op_put_by_id_generic base(r) property(id) value(r) nop(n) nop(n) nop(n) nop(n) Generic property access: Sets the property named by identifier @@ -2804,16 +2761,16 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, int property = vPC[2].u.operand; int value = vPC[3].u.operand; - JSValue* baseValue = callFrame[base].jsValue(callFrame); - Identifier& ident = callFrame->codeBlock()->identifiers[property]; + JSValuePtr baseValue = callFrame[base].jsValue(callFrame); + Identifier& ident = callFrame->codeBlock()->identifier(property); PutPropertySlot slot; - baseValue->put(callFrame, ident, callFrame[value].jsValue(callFrame), slot); - VM_CHECK_EXCEPTION(); + baseValue.put(callFrame, ident, callFrame[value].jsValue(callFrame), slot); + CHECK_FOR_EXCEPTION(); vPC += 8; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_del_by_id) { + DEFINE_OPCODE(op_del_by_id) { /* del_by_id dst(r) base(r) property(id) Converts register base to Object, deletes the property @@ -2825,15 +2782,15 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, int base = (++vPC)->u.operand; int property = (++vPC)->u.operand; - JSObject* baseObj = callFrame[base].jsValue(callFrame)->toObject(callFrame); - Identifier& ident = callFrame->codeBlock()->identifiers[property]; - JSValue* result = jsBoolean(baseObj->deleteProperty(callFrame, ident)); - VM_CHECK_EXCEPTION(); + JSObject* baseObj = callFrame[base].jsValue(callFrame).toObject(callFrame); + Identifier& ident = callFrame->codeBlock()->identifier(property); + JSValuePtr result = jsBoolean(baseObj->deleteProperty(callFrame, ident)); + CHECK_FOR_EXCEPTION(); callFrame[dst] = result; ++vPC; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_get_by_val) { + DEFINE_OPCODE(op_get_by_val) { /* get_by_val dst(r) base(r) property(r) Converts register base to Object, gets the property named @@ -2845,14 +2802,13 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, int base = (++vPC)->u.operand; int property = (++vPC)->u.operand; - JSValue* baseValue = callFrame[base].jsValue(callFrame); - JSValue* subscript = callFrame[property].jsValue(callFrame); + JSValuePtr baseValue = callFrame[base].jsValue(callFrame); + JSValuePtr subscript = callFrame[property].jsValue(callFrame); - JSValue* result; - unsigned i; + JSValuePtr result; - bool isUInt32 = JSImmediate::getUInt32(subscript, i); - if (LIKELY(isUInt32)) { + if (LIKELY(subscript.isUInt32Fast())) { + uint32_t i = subscript.getUInt32Fast(); if (isJSArray(baseValue)) { JSArray* jsArray = asArray(baseValue); if (jsArray->canGetIndex(i)) @@ -2861,19 +2817,21 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, result = jsArray->JSArray::get(callFrame, i); } else if (isJSString(baseValue) && asString(baseValue)->canGetIndex(i)) result = asString(baseValue)->getIndex(&callFrame->globalData(), i); + else if (isJSByteArray(baseValue) && asByteArray(baseValue)->canAccessIndex(i)) + result = asByteArray(baseValue)->getIndex(callFrame, i); else - result = baseValue->get(callFrame, i); + result = baseValue.get(callFrame, i); } else { - Identifier property(callFrame, subscript->toString(callFrame)); - result = baseValue->get(callFrame, property); + Identifier property(callFrame, subscript.toString(callFrame)); + result = baseValue.get(callFrame, property); } - VM_CHECK_EXCEPTION(); + CHECK_FOR_EXCEPTION(); callFrame[dst] = result; ++vPC; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_put_by_val) { + DEFINE_OPCODE(op_put_by_val) { /* put_by_val base(r) property(r) value(r) Sets register value on register base as the property named @@ -2888,34 +2846,42 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, int property = (++vPC)->u.operand; int value = (++vPC)->u.operand; - JSValue* baseValue = callFrame[base].jsValue(callFrame); - JSValue* subscript = callFrame[property].jsValue(callFrame); + JSValuePtr baseValue = callFrame[base].jsValue(callFrame); + JSValuePtr subscript = callFrame[property].jsValue(callFrame); - unsigned i; - - bool isUInt32 = JSImmediate::getUInt32(subscript, i); - if (LIKELY(isUInt32)) { + if (LIKELY(subscript.isUInt32Fast())) { + uint32_t i = subscript.getUInt32Fast(); if (isJSArray(baseValue)) { JSArray* jsArray = asArray(baseValue); if (jsArray->canSetIndex(i)) jsArray->setIndex(i, callFrame[value].jsValue(callFrame)); else jsArray->JSArray::put(callFrame, i, callFrame[value].jsValue(callFrame)); + } else if (isJSByteArray(baseValue) && asByteArray(baseValue)->canAccessIndex(i)) { + JSByteArray* jsByteArray = asByteArray(baseValue); + double dValue = 0; + JSValuePtr jsValue = callFrame[value].jsValue(callFrame); + if (jsValue.isInt32Fast()) + jsByteArray->setIndex(i, jsValue.getInt32Fast()); + else if (jsValue.getNumber(dValue)) + jsByteArray->setIndex(i, dValue); + else + baseValue.put(callFrame, i, jsValue); } else - baseValue->put(callFrame, i, callFrame[value].jsValue(callFrame)); + baseValue.put(callFrame, i, callFrame[value].jsValue(callFrame)); } else { - Identifier property(callFrame, subscript->toString(callFrame)); + Identifier property(callFrame, subscript.toString(callFrame)); if (!globalData->exception) { // Don't put to an object if toString threw an exception. PutPropertySlot slot; - baseValue->put(callFrame, property, callFrame[value].jsValue(callFrame), slot); + baseValue.put(callFrame, property, callFrame[value].jsValue(callFrame), slot); } } - VM_CHECK_EXCEPTION(); + CHECK_FOR_EXCEPTION(); ++vPC; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_del_by_val) { + DEFINE_OPCODE(op_del_by_val) { /* del_by_val dst(r) base(r) property(r) Converts register base to Object, deletes the property @@ -2927,26 +2893,26 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, int base = (++vPC)->u.operand; int property = (++vPC)->u.operand; - JSObject* baseObj = callFrame[base].jsValue(callFrame)->toObject(callFrame); // may throw + JSObject* baseObj = callFrame[base].jsValue(callFrame).toObject(callFrame); // may throw - JSValue* subscript = callFrame[property].jsValue(callFrame); - JSValue* result; + JSValuePtr subscript = callFrame[property].jsValue(callFrame); + JSValuePtr result; uint32_t i; - if (subscript->getUInt32(i)) + if (subscript.getUInt32(i)) result = jsBoolean(baseObj->deleteProperty(callFrame, i)); else { - VM_CHECK_EXCEPTION(); - Identifier property(callFrame, subscript->toString(callFrame)); - VM_CHECK_EXCEPTION(); + CHECK_FOR_EXCEPTION(); + Identifier property(callFrame, subscript.toString(callFrame)); + CHECK_FOR_EXCEPTION(); result = jsBoolean(baseObj->deleteProperty(callFrame, property)); } - VM_CHECK_EXCEPTION(); + CHECK_FOR_EXCEPTION(); callFrame[dst] = result; ++vPC; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_put_by_index) { + DEFINE_OPCODE(op_put_by_index) { /* put_by_index base(r) property(n) value(r) Sets register value on register base as the property named @@ -2962,12 +2928,12 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, unsigned property = (++vPC)->u.operand; int value = (++vPC)->u.operand; - callFrame[base].jsValue(callFrame)->put(callFrame, property, callFrame[value].jsValue(callFrame)); + callFrame[base].jsValue(callFrame).put(callFrame, property, callFrame[value].jsValue(callFrame)); ++vPC; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_loop) { + DEFINE_OPCODE(op_loop) { /* loop target(offset) Jumps unconditionally to offset target from the current @@ -2982,9 +2948,9 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, int target = (++vPC)->u.operand; CHECK_FOR_TIMEOUT(); vPC += target; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_jmp) { + DEFINE_OPCODE(op_jmp) { /* jmp target(offset) Jumps unconditionally to offset target from the current @@ -2996,9 +2962,9 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, int target = (++vPC)->u.operand; vPC += target; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_loop_if_true) { + DEFINE_OPCODE(op_loop_if_true) { /* loop_if_true cond(r) target(offset) Jumps to offset target from the current instruction, if and @@ -3009,16 +2975,16 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, */ int cond = (++vPC)->u.operand; int target = (++vPC)->u.operand; - if (callFrame[cond].jsValue(callFrame)->toBoolean(callFrame)) { + if (callFrame[cond].jsValue(callFrame).toBoolean(callFrame)) { vPC += target; CHECK_FOR_TIMEOUT(); - NEXT_OPCODE; + NEXT_INSTRUCTION(); } ++vPC; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_jtrue) { + DEFINE_OPCODE(op_jtrue) { /* jtrue cond(r) target(offset) Jumps to offset target from the current instruction, if and @@ -3026,15 +2992,15 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, */ int cond = (++vPC)->u.operand; int target = (++vPC)->u.operand; - if (callFrame[cond].jsValue(callFrame)->toBoolean(callFrame)) { + if (callFrame[cond].jsValue(callFrame).toBoolean(callFrame)) { vPC += target; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } ++vPC; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_jfalse) { + DEFINE_OPCODE(op_jfalse) { /* jfalse cond(r) target(offset) Jumps to offset target from the current instruction, if and @@ -3042,15 +3008,15 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, */ int cond = (++vPC)->u.operand; int target = (++vPC)->u.operand; - if (!callFrame[cond].jsValue(callFrame)->toBoolean(callFrame)) { + if (!callFrame[cond].jsValue(callFrame).toBoolean(callFrame)) { vPC += target; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } ++vPC; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_jeq_null) { + DEFINE_OPCODE(op_jeq_null) { /* jeq_null src(r) target(offset) Jumps to offset target from the current instruction, if and @@ -3058,17 +3024,17 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, */ int src = (++vPC)->u.operand; int target = (++vPC)->u.operand; - JSValue* srcValue = callFrame[src].jsValue(callFrame); + JSValuePtr srcValue = callFrame[src].jsValue(callFrame); - if (srcValue->isUndefinedOrNull() || (!JSImmediate::isImmediate(srcValue) && srcValue->asCell()->structureID()->typeInfo().masqueradesAsUndefined())) { + if (srcValue.isUndefinedOrNull() || (srcValue.isCell() && srcValue.asCell()->structure()->typeInfo().masqueradesAsUndefined())) { vPC += target; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } ++vPC; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_jneq_null) { + DEFINE_OPCODE(op_jneq_null) { /* jneq_null src(r) target(offset) Jumps to offset target from the current instruction, if and @@ -3076,17 +3042,17 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, */ int src = (++vPC)->u.operand; int target = (++vPC)->u.operand; - JSValue* srcValue = callFrame[src].jsValue(callFrame); + JSValuePtr srcValue = callFrame[src].jsValue(callFrame); - if (!srcValue->isUndefinedOrNull() || (!JSImmediate::isImmediate(srcValue) && !srcValue->asCell()->structureID()->typeInfo().masqueradesAsUndefined())) { + if (!srcValue.isUndefinedOrNull() || (srcValue.isCell() && !srcValue.asCell()->structure()->typeInfo().masqueradesAsUndefined())) { vPC += target; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } ++vPC; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_loop_if_less) { + DEFINE_OPCODE(op_loop_if_less) { /* loop_if_less src1(r) src2(r) target(offset) Checks whether register src1 is less than register src2, as @@ -3097,23 +3063,23 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, Additionally this loop instruction may terminate JS execution is the JS timeout is reached. */ - JSValue* src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame); - JSValue* src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame); + JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame); + JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame); int target = (++vPC)->u.operand; bool result = jsLess(callFrame, src1, src2); - VM_CHECK_EXCEPTION(); + CHECK_FOR_EXCEPTION(); if (result) { vPC += target; CHECK_FOR_TIMEOUT(); - NEXT_OPCODE; + NEXT_INSTRUCTION(); } ++vPC; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_loop_if_lesseq) { + DEFINE_OPCODE(op_loop_if_lesseq) { /* loop_if_lesseq src1(r) src2(r) target(offset) Checks whether register src1 is less than or equal to register @@ -3124,23 +3090,23 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, Additionally this loop instruction may terminate JS execution is the JS timeout is reached. */ - JSValue* src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame); - JSValue* src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame); + JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame); + JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame); int target = (++vPC)->u.operand; bool result = jsLessEq(callFrame, src1, src2); - VM_CHECK_EXCEPTION(); + CHECK_FOR_EXCEPTION(); if (result) { vPC += target; CHECK_FOR_TIMEOUT(); - NEXT_OPCODE; + NEXT_INSTRUCTION(); } ++vPC; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_jnless) { + DEFINE_OPCODE(op_jnless) { /* jnless src1(r) src2(r) target(offset) Checks whether register src1 is less than register src2, as @@ -3148,22 +3114,22 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, target from the current instruction, if and only if the result of the comparison is false. */ - JSValue* src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame); - JSValue* src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame); + JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame); + JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame); int target = (++vPC)->u.operand; bool result = jsLess(callFrame, src1, src2); - VM_CHECK_EXCEPTION(); + CHECK_FOR_EXCEPTION(); if (!result) { vPC += target; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } ++vPC; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_switch_imm) { + DEFINE_OPCODE(op_switch_imm) { /* switch_imm tableIndex(n) defaultOffset(offset) scrutinee(r) Performs a range checked switch on the scrutinee value, using @@ -3174,16 +3140,19 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, */ int tableIndex = (++vPC)->u.operand; int defaultOffset = (++vPC)->u.operand; - JSValue* scrutinee = callFrame[(++vPC)->u.operand].jsValue(callFrame); - if (!JSImmediate::isNumber(scrutinee)) - vPC += defaultOffset; + JSValuePtr scrutinee = callFrame[(++vPC)->u.operand].jsValue(callFrame); + if (scrutinee.isInt32Fast()) + vPC += callFrame->codeBlock()->immediateSwitchJumpTable(tableIndex).offsetForValue(scrutinee.getInt32Fast(), defaultOffset); else { - int32_t value = JSImmediate::getTruncatedInt32(scrutinee); - vPC += callFrame->codeBlock()->immediateSwitchJumpTables[tableIndex].offsetForValue(value, defaultOffset); + int32_t value; + if (scrutinee.numberToInt32(value)) + vPC += callFrame->codeBlock()->immediateSwitchJumpTable(tableIndex).offsetForValue(value, defaultOffset); + else + vPC += defaultOffset; } - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_switch_char) { + DEFINE_OPCODE(op_switch_char) { /* switch_char tableIndex(n) defaultOffset(offset) scrutinee(r) Performs a range checked switch on the scrutinee value, using @@ -3194,19 +3163,19 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, */ int tableIndex = (++vPC)->u.operand; int defaultOffset = (++vPC)->u.operand; - JSValue* scrutinee = callFrame[(++vPC)->u.operand].jsValue(callFrame); - if (!scrutinee->isString()) + JSValuePtr scrutinee = callFrame[(++vPC)->u.operand].jsValue(callFrame); + if (!scrutinee.isString()) vPC += defaultOffset; else { UString::Rep* value = asString(scrutinee)->value().rep(); if (value->size() != 1) vPC += defaultOffset; else - vPC += callFrame->codeBlock()->characterSwitchJumpTables[tableIndex].offsetForValue(value->data()[0], defaultOffset); + vPC += callFrame->codeBlock()->characterSwitchJumpTable(tableIndex).offsetForValue(value->data()[0], defaultOffset); } - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_switch_string) { + DEFINE_OPCODE(op_switch_string) { /* switch_string tableIndex(n) defaultOffset(offset) scrutinee(r) Performs a sparse hashmap based switch on the value in the scrutinee @@ -3217,14 +3186,14 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, */ int tableIndex = (++vPC)->u.operand; int defaultOffset = (++vPC)->u.operand; - JSValue* scrutinee = callFrame[(++vPC)->u.operand].jsValue(callFrame); - if (!scrutinee->isString()) + JSValuePtr scrutinee = callFrame[(++vPC)->u.operand].jsValue(callFrame); + if (!scrutinee.isString()) vPC += defaultOffset; else - vPC += callFrame->codeBlock()->stringSwitchJumpTables[tableIndex].offsetForValue(asString(scrutinee)->value().rep(), defaultOffset); - NEXT_OPCODE; + vPC += callFrame->codeBlock()->stringSwitchJumpTable(tableIndex).offsetForValue(asString(scrutinee)->value().rep(), defaultOffset); + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_new_func) { + DEFINE_OPCODE(op_new_func) { /* new_func dst(r) func(f) Constructs a new Function instance from function func and @@ -3235,12 +3204,12 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, int dst = (++vPC)->u.operand; int func = (++vPC)->u.operand; - callFrame[dst] = callFrame->codeBlock()->functions[func]->makeFunction(callFrame, callFrame->scopeChain()); + callFrame[dst] = callFrame->codeBlock()->function(func)->makeFunction(callFrame, callFrame->scopeChain()); ++vPC; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_new_func_exp) { + DEFINE_OPCODE(op_new_func_exp) { /* new_func_exp dst(r) func(f) Constructs a new Function instance from function func and @@ -3251,13 +3220,13 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, int dst = (++vPC)->u.operand; int func = (++vPC)->u.operand; - callFrame[dst] = callFrame->codeBlock()->functionExpressions[func]->makeFunction(callFrame, callFrame->scopeChain()); + callFrame[dst] = callFrame->codeBlock()->functionExpression(func)->makeFunction(callFrame, callFrame->scopeChain()); ++vPC; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_call_eval) { - /* call_eval dst(r) func(r) thisVal(r) firstArg(r) argCount(n) + DEFINE_OPCODE(op_call_eval) { + /* call_eval dst(r) func(r) argCount(n) registerOffset(n) Call a function named "eval" with no explicit "this" value (which may therefore be the eval operator). If register @@ -3270,95 +3239,56 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, int dst = vPC[1].u.operand; int func = vPC[2].u.operand; - int thisVal = vPC[3].u.operand; - int firstArg = vPC[4].u.operand; - int argCount = vPC[5].u.operand; + int argCount = vPC[3].u.operand; + int registerOffset = vPC[4].u.operand; - JSValue* funcVal = callFrame[func].jsValue(callFrame); - JSValue* baseVal = callFrame[thisVal].jsValue(callFrame); + JSValuePtr funcVal = callFrame[func].jsValue(callFrame); - ScopeChainNode* scopeChain = callFrame->scopeChain(); - if (baseVal == scopeChain->globalObject() && funcVal == scopeChain->globalObject()->evalFunction()) { - JSObject* thisObject = asObject(callFrame[callFrame->codeBlock()->thisRegister].jsValue(callFrame)); - JSValue* result = callEval(callFrame, thisObject, scopeChain, registerFile, firstArg, argCount, exceptionValue); + Register* newCallFrame = callFrame->registers() + registerOffset; + Register* argv = newCallFrame - RegisterFile::CallFrameHeaderSize - argCount; + JSValuePtr thisValue = argv[0].jsValue(callFrame); + JSGlobalObject* globalObject = callFrame->scopeChain()->globalObject(); + + if (thisValue == globalObject && funcVal == globalObject->evalFunction()) { + JSValuePtr result = callEval(callFrame, registerFile, argv, argCount, registerOffset, exceptionValue); if (exceptionValue) goto vm_throw; - callFrame[dst] = result; - vPC += 7; - NEXT_OPCODE; + vPC += 5; + NEXT_INSTRUCTION(); } - // We didn't find the blessed version of eval, so reset vPC and process - // this instruction as a normal function call, supplying the proper 'this' - // value. - callFrame[thisVal] = baseVal->toThisObject(callFrame); - -#if HAVE(COMPUTED_GOTO) - // Hack around gcc performance quirk by performing an indirect goto - // in order to set the vPC -- attempting to do so directly results in a - // significant regression. - goto *op_call_indirect; // indirect goto -> op_call -#endif + // We didn't find the blessed version of eval, so process this + // instruction as a normal function call. // fall through to op_call } - BEGIN_OPCODE(op_call) { - /* call dst(r) func(r) thisVal(r) firstArg(r) argCount(n) registerOffset(n) + DEFINE_OPCODE(op_call) { + /* call dst(r) func(r) argCount(n) registerOffset(n) - Perform a function call. Specifically, call register func - with a "this" value of register thisVal, and put the result - in register dst. - - The arguments start at register firstArg and go up to - argCount, but the "this" value is considered an implicit - first argument, so the argCount should be one greater than - the number of explicit arguments passed, and the register - after firstArg should contain the actual first - argument. This opcode will copy from the thisVal register - to the firstArg register, unless the register index of - thisVal is the special missing this object marker, which is - 2^31-1; in that case, the global object will be used as the - "this" value. - - If func is a native code function, then this opcode calls - it and returns the value immediately. - - But if it is a JS function, then the current scope chain - and code block is set to the function's, and we slide the - register window so that the arguments would form the first - few local registers of the called function's register - window. In addition, a call frame header is written - immediately before the arguments; see the call frame - documentation for an explanation of how many registers a - call frame takes and what they contain. That many registers - before the firstArg register will be overwritten by the - call. In addition, any registers higher than firstArg + - argCount may be overwritten. Once this setup is complete, - execution continues from the called function's first - argument, and does not return until a "ret" opcode is - encountered. + Perform a function call. + + registerOffset is the distance the callFrame pointer should move + before the VM initializes the new call frame's header. + + dst is where op_ret should store its result. */ int dst = vPC[1].u.operand; int func = vPC[2].u.operand; - int thisVal = vPC[3].u.operand; - int firstArg = vPC[4].u.operand; - int argCount = vPC[5].u.operand; - int registerOffset = vPC[6].u.operand; + int argCount = vPC[3].u.operand; + int registerOffset = vPC[4].u.operand; - JSValue* v = callFrame[func].jsValue(callFrame); + JSValuePtr v = callFrame[func].jsValue(callFrame); CallData callData; - CallType callType = v->getCallData(callData); + CallType callType = v.getCallData(callData); if (callType == CallTypeJS) { ScopeChainNode* callDataScopeChain = callData.js.scopeChain; FunctionBodyNode* functionBodyNode = callData.js.functionBody; - CodeBlock* newCodeBlock = &functionBodyNode->byteCode(callDataScopeChain); + CodeBlock* newCodeBlock = &functionBodyNode->bytecode(callDataScopeChain); - callFrame[firstArg] = thisVal == missingThisObjectMarker() ? callFrame->globalThisValue() : callFrame[thisVal].jsValue(callFrame); - CallFrame* previousCallFrame = callFrame; callFrame = slideRegisterWindowForCall(newCodeBlock, registerFile, callFrame, registerOffset, argCount); @@ -3368,43 +3298,48 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, goto vm_throw; } - callFrame->init(newCodeBlock, vPC + 7, callDataScopeChain, previousCallFrame, dst, argCount, asFunction(v)); - vPC = newCodeBlock->instructions.begin(); + callFrame->init(newCodeBlock, vPC + 5, callDataScopeChain, previousCallFrame, dst, argCount, asFunction(v)); + vPC = newCodeBlock->instructions().begin(); #if ENABLE(OPCODE_STATS) OpcodeStats::resetLastInstruction(); #endif - NEXT_OPCODE; + NEXT_INSTRUCTION(); } if (callType == CallTypeHost) { - JSValue* thisValue = thisVal == missingThisObjectMarker() ? callFrame->globalThisValue() : callFrame[thisVal].jsValue(callFrame); - ArgList args(callFrame->registers() + firstArg + 1, argCount - 1); - ScopeChainNode* scopeChain = callFrame->scopeChain(); CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + registerOffset); - newCallFrame->init(0, vPC + 7, scopeChain, callFrame, dst, argCount, 0); + newCallFrame->init(0, vPC + 5, scopeChain, callFrame, dst, argCount, 0); - JSValue* returnValue; + Register* thisRegister = newCallFrame->registers() - RegisterFile::CallFrameHeaderSize - argCount; + ArgList args(thisRegister + 1, argCount - 1); + + // FIXME: All host methods should be calling toThisObject, but this is not presently the case. + JSValuePtr thisValue = thisRegister->jsValue(callFrame); + if (thisValue == jsNull()) + thisValue = callFrame->globalThisValue(); + + JSValuePtr returnValue; { SamplingTool::HostCallRecord callRecord(m_sampler); returnValue = callData.native.function(newCallFrame, asObject(v), thisValue, args); } - VM_CHECK_EXCEPTION(); + CHECK_FOR_EXCEPTION(); - callFrame[dst] = returnValue; + callFrame[dst] = JSValuePtr(returnValue); - vPC += 7; - NEXT_OPCODE; + vPC += 5; + NEXT_INSTRUCTION(); } ASSERT(callType == CallTypeNone); - exceptionValue = createNotAFunctionError(callFrame, v, vPC, callFrame->codeBlock()); + exceptionValue = createNotAFunctionError(callFrame, v, vPC - callFrame->codeBlock()->instructions().begin(), callFrame->codeBlock()); goto vm_throw; } - BEGIN_OPCODE(op_tear_off_activation) { + DEFINE_OPCODE(op_tear_off_activation) { /* tear_off_activation activation(r) Copy all locals and parameters to new memory allocated on @@ -3418,14 +3353,14 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, */ int src = (++vPC)->u.operand; - ASSERT(callFrame->codeBlock()->needsFullScopeChain); + ASSERT(callFrame->codeBlock()->needsFullScopeChain()); asActivation(callFrame[src].getJSValue())->copyRegisters(callFrame->optionalCalleeArguments()); ++vPC; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_tear_off_arguments) { + DEFINE_OPCODE(op_tear_off_arguments) { /* tear_off_arguments Copy all arguments to new memory allocated on the heap, @@ -3438,14 +3373,14 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, This opcode should only be used immediately before op_ret. */ - ASSERT(callFrame->codeBlock()->usesArguments && !callFrame->codeBlock()->needsFullScopeChain); + ASSERT(callFrame->codeBlock()->usesArguments() && !callFrame->codeBlock()->needsFullScopeChain()); callFrame->optionalCalleeArguments()->copyRegisters(); ++vPC; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_ret) { + DEFINE_OPCODE(op_ret) { /* ret result(r) Return register result as the return value of the current @@ -3457,10 +3392,10 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, int result = (++vPC)->u.operand; - if (callFrame->codeBlock()->needsFullScopeChain) + if (callFrame->codeBlock()->needsFullScopeChain()) callFrame->scopeChain()->deref(); - JSValue* returnValue = callFrame[result].jsValue(callFrame); + JSValuePtr returnValue = callFrame[result].jsValue(callFrame); vPC = callFrame->returnPC(); int dst = callFrame->returnValueRegister(); @@ -3469,11 +3404,11 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, if (callFrame->hasHostCallFrameFlag()) return returnValue; - callFrame[dst] = returnValue; + callFrame[dst] = JSValuePtr(returnValue); - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_enter) { + DEFINE_OPCODE(op_enter) { /* enter Initializes local variables to undefined and fills constant @@ -3487,16 +3422,16 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, size_t i = 0; CodeBlock* codeBlock = callFrame->codeBlock(); - for (size_t count = codeBlock->numVars; i < count; ++i) + for (size_t count = codeBlock->m_numVars; i < count; ++i) callFrame[i] = jsUndefined(); - for (size_t count = codeBlock->constantRegisters.size(), j = 0; j < count; ++i, ++j) - callFrame[i] = codeBlock->constantRegisters[j]; + for (size_t count = codeBlock->numberOfConstantRegisters(), j = 0; j < count; ++i, ++j) + callFrame[i] = codeBlock->constantRegister(j); ++vPC; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_enter_with_activation) { + DEFINE_OPCODE(op_enter_with_activation) { /* enter_with_activation dst(r) Initializes local variables to undefined, fills constant @@ -3512,21 +3447,21 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, size_t i = 0; CodeBlock* codeBlock = callFrame->codeBlock(); - for (size_t count = codeBlock->numVars; i < count; ++i) + for (size_t count = codeBlock->m_numVars; i < count; ++i) callFrame[i] = jsUndefined(); - for (size_t count = codeBlock->constantRegisters.size(), j = 0; j < count; ++i, ++j) - callFrame[i] = codeBlock->constantRegisters[j]; + for (size_t count = codeBlock->numberOfConstantRegisters(), j = 0; j < count; ++i, ++j) + callFrame[i] = codeBlock->constantRegister(j); int dst = (++vPC)->u.operand; - JSActivation* activation = new (globalData) JSActivation(callFrame, static_cast<FunctionBodyNode*>(codeBlock->ownerNode)); + JSActivation* activation = new (globalData) JSActivation(callFrame, static_cast<FunctionBodyNode*>(codeBlock->ownerNode())); callFrame[dst] = activation; callFrame->setScopeChain(callFrame->scopeChain()->copy()->push(activation)); ++vPC; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_convert_this) { + DEFINE_OPCODE(op_convert_this) { /* convert_this this(r) Takes the value in the 'this' register, converts it to a @@ -3539,14 +3474,14 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, */ int thisRegister = (++vPC)->u.operand; - JSValue* thisVal = callFrame[thisRegister].getJSValue(); - if (thisVal->needsThisConversion()) - callFrame[thisRegister] = thisVal->toThisObject(callFrame); + JSValuePtr thisVal = callFrame[thisRegister].getJSValue(); + if (thisVal.needsThisConversion()) + callFrame[thisRegister] = JSValuePtr(thisVal.toThisObject(callFrame)); ++vPC; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_create_arguments) { + DEFINE_OPCODE(op_create_arguments) { /* create_arguments Creates the 'arguments' object and places it in both the @@ -3562,49 +3497,49 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, callFrame[RegisterFile::ArgumentsRegister] = arguments; ++vPC; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_construct) { - /* construct dst(r) constr(r) constrProto(r) firstArg(r) argCount(n) registerOffset(n) + DEFINE_OPCODE(op_construct) { + /* construct dst(r) func(r) argCount(n) registerOffset(n) proto(r) thisRegister(r) - Invoke register "constr" as a constructor. For JS + Invoke register "func" as a constructor. For JS functions, the calling convention is exactly as for the "call" opcode, except that the "this" value is a newly - created Object. For native constructors, a null "this" - value is passed. In either case, the firstArg and argCount + created Object. For native constructors, no "this" + value is passed. In either case, the argCount and registerOffset registers are interpreted as for the "call" opcode. - Register constrProto must contain the prototype property of - register constsr. This is to enable polymorphic inline + Register proto must contain the prototype property of + register func. This is to enable polymorphic inline caching of this lookup. */ int dst = vPC[1].u.operand; - int constr = vPC[2].u.operand; - int constrProto = vPC[3].u.operand; - int firstArg = vPC[4].u.operand; - int argCount = vPC[5].u.operand; - int registerOffset = vPC[6].u.operand; + int func = vPC[2].u.operand; + int argCount = vPC[3].u.operand; + int registerOffset = vPC[4].u.operand; + int proto = vPC[5].u.operand; + int thisRegister = vPC[6].u.operand; - JSValue* v = callFrame[constr].jsValue(callFrame); + JSValuePtr v = callFrame[func].jsValue(callFrame); ConstructData constructData; - ConstructType constructType = v->getConstructData(constructData); + ConstructType constructType = v.getConstructData(constructData); if (constructType == ConstructTypeJS) { ScopeChainNode* callDataScopeChain = constructData.js.scopeChain; FunctionBodyNode* functionBodyNode = constructData.js.functionBody; - CodeBlock* newCodeBlock = &functionBodyNode->byteCode(callDataScopeChain); + CodeBlock* newCodeBlock = &functionBodyNode->bytecode(callDataScopeChain); - StructureID* structure; - JSValue* prototype = callFrame[constrProto].jsValue(callFrame); - if (prototype->isObject()) + Structure* structure; + JSValuePtr prototype = callFrame[proto].jsValue(callFrame); + if (prototype.isObject()) structure = asObject(prototype)->inheritorID(); else structure = callDataScopeChain->globalObject()->emptyObjectStructure(); JSObject* newObject = new (globalData) JSObject(structure); - callFrame[firstArg] = newObject; // "this" value + callFrame[thisRegister] = JSValuePtr(newObject); // "this" value CallFrame* previousCallFrame = callFrame; @@ -3616,40 +3551,40 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, } callFrame->init(newCodeBlock, vPC + 7, callDataScopeChain, previousCallFrame, dst, argCount, asFunction(v)); - vPC = newCodeBlock->instructions.begin(); + vPC = newCodeBlock->instructions().begin(); #if ENABLE(OPCODE_STATS) OpcodeStats::resetLastInstruction(); #endif - NEXT_OPCODE; + NEXT_INSTRUCTION(); } if (constructType == ConstructTypeHost) { - ArgList args(callFrame->registers() + firstArg + 1, argCount - 1); + ArgList args(callFrame->registers() + thisRegister + 1, argCount - 1); ScopeChainNode* scopeChain = callFrame->scopeChain(); CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + registerOffset); newCallFrame->init(0, vPC + 7, scopeChain, callFrame, dst, argCount, 0); - JSValue* returnValue; + JSValuePtr returnValue; { SamplingTool::HostCallRecord callRecord(m_sampler); returnValue = constructData.native.function(newCallFrame, asObject(v), args); } - VM_CHECK_EXCEPTION(); - callFrame[dst] = returnValue; + CHECK_FOR_EXCEPTION(); + callFrame[dst] = JSValuePtr(returnValue); vPC += 7; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } ASSERT(constructType == ConstructTypeNone); - exceptionValue = createNotAConstructorError(callFrame, v, vPC, callFrame->codeBlock()); + exceptionValue = createNotAConstructorError(callFrame, v, vPC - callFrame->codeBlock()->instructions().begin(), callFrame->codeBlock()); goto vm_throw; } - BEGIN_OPCODE(op_construct_verify) { + DEFINE_OPCODE(op_construct_verify) { /* construct_verify dst(r) override(r) Verifies that register dst holds an object. If not, moves @@ -3657,34 +3592,36 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, */ int dst = vPC[1].u.operand;; - if (LIKELY(callFrame[dst].jsValue(callFrame)->isObject())) { + if (LIKELY(callFrame[dst].jsValue(callFrame).isObject())) { vPC += 3; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } int override = vPC[2].u.operand; callFrame[dst] = callFrame[override]; vPC += 3; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_push_scope) { + DEFINE_OPCODE(op_push_scope) { /* push_scope scope(r) Converts register scope to object, and pushes it onto the top - of the current scope chain. + of the current scope chain. The contents of the register scope + are replaced by the result of toObject conversion of the scope. */ int scope = (++vPC)->u.operand; - JSValue* v = callFrame[scope].jsValue(callFrame); - JSObject* o = v->toObject(callFrame); - VM_CHECK_EXCEPTION(); + JSValuePtr v = callFrame[scope].jsValue(callFrame); + JSObject* o = v.toObject(callFrame); + CHECK_FOR_EXCEPTION(); + callFrame[scope] = JSValuePtr(o); callFrame->setScopeChain(callFrame->scopeChain()->push(o)); ++vPC; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_pop_scope) { + DEFINE_OPCODE(op_pop_scope) { /* pop_scope Removes the top item from the current scope chain. @@ -3692,9 +3629,9 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, callFrame->setScopeChain(callFrame->scopeChain()->pop()); ++vPC; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_get_pnames) { + DEFINE_OPCODE(op_get_pnames) { /* get_pnames dst(r) base(r) Creates a property name list for register base and puts it @@ -3707,9 +3644,9 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, callFrame[dst] = JSPropertyNameIterator::create(callFrame, callFrame[base].jsValue(callFrame)); ++vPC; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_next_pname) { + DEFINE_OPCODE(op_next_pname) { /* next_pname dst(r) iter(r) target(offset) Tries to copies the next name from property name list in @@ -3723,18 +3660,18 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, int target = (++vPC)->u.operand; JSPropertyNameIterator* it = callFrame[iter].propertyNameIterator(); - if (JSValue* temp = it->next(callFrame)) { + if (JSValuePtr temp = it->next(callFrame)) { CHECK_FOR_TIMEOUT(); - callFrame[dst] = temp; + callFrame[dst] = JSValuePtr(temp); vPC += target; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } it->invalidate(); ++vPC; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_jmp_scopes) { + DEFINE_OPCODE(op_jmp_scopes) { /* jmp_scopes count(n) target(offset) Removes the a number of items from the current scope chain @@ -3750,13 +3687,13 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, callFrame->setScopeChain(tmp); vPC += target; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } #if HAVE(COMPUTED_GOTO) // Appease GCC goto *(&&skip_new_scope); #endif - BEGIN_OPCODE(op_push_new_scope) { + DEFINE_OPCODE(op_push_new_scope) { /* new_scope dst(r) property(id) value(r) Constructs a new StaticScopeObject with property set to value. That scope @@ -3766,12 +3703,12 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, callFrame->setScopeChain(createExceptionScope(callFrame, vPC)); vPC += 4; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } #if HAVE(COMPUTED_GOTO) skip_new_scope: #endif - BEGIN_OPCODE(op_catch) { + DEFINE_OPCODE(op_catch) { /* catch ex(r) Retrieves the VMs current exception and puts it in register @@ -3785,9 +3722,9 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, exceptionValue = noValue(); ++vPC; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_throw) { + DEFINE_OPCODE(op_throw) { /* throw ex(r) Throws register ex as an exception. This involves three @@ -3801,37 +3738,28 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, int ex = (++vPC)->u.operand; exceptionValue = callFrame[ex].jsValue(callFrame); - handlerVPC = throwException(callFrame, exceptionValue, vPC, true); - if (!handlerVPC) { + handler = throwException(callFrame, exceptionValue, vPC - callFrame->codeBlock()->instructions().begin(), true); + if (!handler) { *exception = exceptionValue; return jsNull(); } -#if HAVE(COMPUTED_GOTO) - // Hack around gcc performance quirk by performing an indirect goto - // in order to set the vPC -- attempting to do so directly results in a - // significant regression. - goto *op_throw_end_indirect; // indirect goto -> op_throw_end + vPC = callFrame->codeBlock()->instructions().begin() + handler->target; + NEXT_INSTRUCTION(); } - op_throw_end: { -#endif - - vPC = handlerVPC; - NEXT_OPCODE; - } - BEGIN_OPCODE(op_unexpected_load) { + DEFINE_OPCODE(op_unexpected_load) { /* unexpected_load load dst(r) src(k) Copies constant src to register dst. */ int dst = (++vPC)->u.operand; int src = (++vPC)->u.operand; - callFrame[dst] = callFrame->codeBlock()->unexpectedConstants[src]; + callFrame[dst] = JSValuePtr(callFrame->codeBlock()->unexpectedConstant(src)); ++vPC; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_new_error) { + DEFINE_OPCODE(op_new_error) { /* new_error dst(r) type(n) message(k) Constructs a new Error instance using the original @@ -3844,19 +3772,19 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, int message = (++vPC)->u.operand; CodeBlock* codeBlock = callFrame->codeBlock(); - callFrame[dst] = Error::create(callFrame, (ErrorType)type, codeBlock->unexpectedConstants[message]->toString(callFrame), codeBlock->lineNumberForVPC(vPC), codeBlock->ownerNode->sourceID(), codeBlock->ownerNode->sourceURL()); + callFrame[dst] = JSValuePtr(Error::create(callFrame, (ErrorType)type, codeBlock->unexpectedConstant(message).toString(callFrame), codeBlock->lineNumberForBytecodeOffset(callFrame, vPC - codeBlock->instructions().begin()), codeBlock->ownerNode()->sourceID(), codeBlock->ownerNode()->sourceURL())); ++vPC; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_end) { + DEFINE_OPCODE(op_end) { /* end result(r) Return register result as the value of a global or eval program. Return control to the calling native code. */ - if (callFrame->codeBlock()->needsFullScopeChain) { + if (callFrame->codeBlock()->needsFullScopeChain()) { ScopeChainNode* scopeChain = callFrame->scopeChain(); ASSERT(scopeChain->refCount > 1); scopeChain->deref(); @@ -3864,7 +3792,7 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, int result = (++vPC)->u.operand; return callFrame[result].jsValue(callFrame); } - BEGIN_OPCODE(op_put_getter) { + DEFINE_OPCODE(op_put_getter) { /* put_getter base(r) property(id) function(r) Sets register function on register base as the getter named @@ -3879,16 +3807,16 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, int property = (++vPC)->u.operand; int function = (++vPC)->u.operand; - ASSERT(callFrame[base].jsValue(callFrame)->isObject()); + ASSERT(callFrame[base].jsValue(callFrame).isObject()); JSObject* baseObj = asObject(callFrame[base].jsValue(callFrame)); - Identifier& ident = callFrame->codeBlock()->identifiers[property]; - ASSERT(callFrame[function].jsValue(callFrame)->isObject()); + Identifier& ident = callFrame->codeBlock()->identifier(property); + ASSERT(callFrame[function].jsValue(callFrame).isObject()); baseObj->defineGetter(callFrame, ident, asObject(callFrame[function].jsValue(callFrame))); ++vPC; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_put_setter) { + DEFINE_OPCODE(op_put_setter) { /* put_setter base(r) property(id) function(r) Sets register function on register base as the setter named @@ -3903,16 +3831,16 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, int property = (++vPC)->u.operand; int function = (++vPC)->u.operand; - ASSERT(callFrame[base].jsValue(callFrame)->isObject()); + ASSERT(callFrame[base].jsValue(callFrame).isObject()); JSObject* baseObj = asObject(callFrame[base].jsValue(callFrame)); - Identifier& ident = callFrame->codeBlock()->identifiers[property]; - ASSERT(callFrame[function].jsValue(callFrame)->isObject()); + Identifier& ident = callFrame->codeBlock()->identifier(property); + ASSERT(callFrame[function].jsValue(callFrame).isObject()); baseObj->defineSetter(callFrame, ident, asObject(callFrame[function].jsValue(callFrame))); ++vPC; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_jsr) { + DEFINE_OPCODE(op_jsr) { /* jsr retAddrDst(r) target(offset) Places the address of the next instruction into the retAddrDst @@ -3923,9 +3851,9 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, callFrame[retAddrDst] = vPC + 1; vPC += target; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_sret) { + DEFINE_OPCODE(op_sret) { /* sret retAddrSrc(r) Jumps to the address stored in the retAddrSrc register. This @@ -3934,9 +3862,9 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, */ int retAddrSrc = (++vPC)->u.operand; vPC = callFrame[retAddrSrc].vPC(); - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_debug) { + DEFINE_OPCODE(op_debug) { /* debug debugHookID(n) firstLine(n) lastLine(n) Notifies the debugger of the current state of execution. This opcode @@ -3949,9 +3877,9 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, debug(callFrame, static_cast<DebugHookID>(debugHookID), firstLine, lastLine); ++vPC; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_profile_will_call) { + DEFINE_OPCODE(op_profile_will_call) { /* op_profile_will_call function(r) Notifies the profiler of the beginning of a function call. This opcode @@ -3963,9 +3891,9 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, (*enabledProfilerReference)->willExecute(callFrame, callFrame[function].jsValue(callFrame)); vPC += 2; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } - BEGIN_OPCODE(op_profile_did_call) { + DEFINE_OPCODE(op_profile_did_call) { /* op_profile_did_call function(r) Notifies the profiler of the end of a function call. This opcode @@ -3977,7 +3905,7 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, (*enabledProfilerReference)->didExecute(callFrame, callFrame[function].jsValue(callFrame)); vPC += 2; - NEXT_OPCODE; + NEXT_INSTRUCTION(); } vm_throw: { globalData->exception = noValue(); @@ -3986,34 +3914,35 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, // cannot fathom if we don't assign to the exceptionValue before branching) exceptionValue = createInterruptedExecutionException(globalData); } - handlerVPC = throwException(callFrame, exceptionValue, vPC, false); - if (!handlerVPC) { + handler = throwException(callFrame, exceptionValue, vPC - callFrame->codeBlock()->instructions().begin(), false); + if (!handler) { *exception = exceptionValue; return jsNull(); } - vPC = handlerVPC; - NEXT_OPCODE; + + vPC = callFrame->codeBlock()->instructions().begin() + handler->target; + NEXT_INSTRUCTION(); } } #if !HAVE(COMPUTED_GOTO) } // iterator loop ends #endif - #undef NEXT_OPCODE - #undef BEGIN_OPCODE - #undef VM_CHECK_EXCEPTION + #undef NEXT_INSTRUCTION + #undef DEFINE_OPCODE + #undef CHECK_FOR_EXCEPTION #undef CHECK_FOR_TIMEOUT } -JSValue* Machine::retrieveArguments(CallFrame* callFrame, JSFunction* function) const +JSValuePtr Interpreter::retrieveArguments(CallFrame* callFrame, JSFunction* function) const { CallFrame* functionCallFrame = findFunctionCallFrame(callFrame, function); if (!functionCallFrame) return jsNull(); CodeBlock* codeBlock = functionCallFrame->codeBlock(); - if (codeBlock->usesArguments) { - ASSERT(codeBlock->codeType == FunctionCode); - SymbolTable& symbolTable = static_cast<FunctionBodyNode*>(codeBlock->ownerNode)->symbolTable(); + if (codeBlock->usesArguments()) { + ASSERT(codeBlock->codeType() == FunctionCode); + SymbolTable& symbolTable = codeBlock->symbolTable(); int argumentsIndex = symbolTable.get(functionCallFrame->propertyNames().arguments.ustring().rep()).getIndex(); return functionCallFrame[argumentsIndex].jsValue(callFrame); } @@ -4028,7 +3957,7 @@ JSValue* Machine::retrieveArguments(CallFrame* callFrame, JSFunction* function) return arguments; } -JSValue* Machine::retrieveCaller(CallFrame* callFrame, InternalFunction* function) const +JSValuePtr Interpreter::retrieveCaller(CallFrame* callFrame, InternalFunction* function) const { CallFrame* functionCallFrame = findFunctionCallFrame(callFrame, function); if (!functionCallFrame) @@ -4038,14 +3967,14 @@ JSValue* Machine::retrieveCaller(CallFrame* callFrame, InternalFunction* functio if (callerFrame->hasHostCallFrameFlag()) return jsNull(); - JSValue* caller = callerFrame->callee(); + JSValuePtr caller = callerFrame->callee(); if (!caller) return jsNull(); return caller; } -void Machine::retrieveLastCaller(CallFrame* callFrame, int& lineNumber, intptr_t& sourceID, UString& sourceURL, JSValue*& function) const +void Interpreter::retrieveLastCaller(CallFrame* callFrame, int& lineNumber, intptr_t& sourceID, UString& sourceURL, JSValuePtr& function) const { function = noValue(); lineNumber = -1; @@ -4059,14 +3988,14 @@ void Machine::retrieveLastCaller(CallFrame* callFrame, int& lineNumber, intptr_t if (!callerCodeBlock) return; - Instruction* vPC = vPCForPC(callerCodeBlock, callFrame->returnPC()); - lineNumber = callerCodeBlock->lineNumberForVPC(vPC - 1); - sourceID = callerCodeBlock->ownerNode->sourceID(); - sourceURL = callerCodeBlock->ownerNode->sourceURL(); + unsigned bytecodeOffset = bytecodeOffsetForPC(callerFrame, callerCodeBlock, callFrame->returnPC()); + lineNumber = callerCodeBlock->lineNumberForBytecodeOffset(callerFrame, bytecodeOffset - 1); + sourceID = callerCodeBlock->ownerNode()->sourceID(); + sourceURL = callerCodeBlock->ownerNode()->sourceURL(); function = callerFrame->callee(); } -CallFrame* Machine::findFunctionCallFrame(CallFrame* callFrame, InternalFunction* function) +CallFrame* Interpreter::findFunctionCallFrame(CallFrame* callFrame, InternalFunction* function) { for (CallFrame* candidate = callFrame; candidate; candidate = candidate->callerFrame()->removeHostCallFrameFlag()) { if (candidate->callee() == function) @@ -4075,220 +4004,169 @@ CallFrame* Machine::findFunctionCallFrame(CallFrame* callFrame, InternalFunction return 0; } -#if ENABLE(CTI) +#if ENABLE(JIT) -NEVER_INLINE void Machine::tryCTICachePutByID(CallFrame* callFrame, CodeBlock* codeBlock, void* returnAddress, JSValue* baseValue, const PutPropertySlot& slot) +#if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS) + +NEVER_INLINE void Interpreter::tryCTICachePutByID(CallFrame* callFrame, CodeBlock* codeBlock, void* returnAddress, JSValuePtr baseValue, const PutPropertySlot& slot) { // The interpreter checks for recursion here; I do not believe this can occur in CTI. - if (JSImmediate::isImmediate(baseValue)) + if (!baseValue.isCell()) return; // Uncacheable: give up. if (!slot.isCacheable()) { - ctiRepatchCallByReturnAddress(returnAddress, reinterpret_cast<void*>(cti_op_put_by_id_generic)); + ctiPatchCallByReturnAddress(returnAddress, reinterpret_cast<void*>(cti_op_put_by_id_generic)); return; } JSCell* baseCell = asCell(baseValue); - StructureID* structureID = baseCell->structureID(); + Structure* structure = baseCell->structure(); - if (structureID->isDictionary()) { - ctiRepatchCallByReturnAddress(returnAddress, reinterpret_cast<void*>(cti_op_put_by_id_generic)); + if (structure->isDictionary()) { + ctiPatchCallByReturnAddress(returnAddress, reinterpret_cast<void*>(cti_op_put_by_id_generic)); return; } - // In the interpreter the last structure is trapped here; in CTI we use the - // *_second method to achieve a similar (but not quite the same) effect. - - unsigned vPCIndex = codeBlock->ctiReturnAddressVPCMap.get(returnAddress); - Instruction* vPC = codeBlock->instructions.begin() + vPCIndex; - - // Cache hit: Specialize instruction and ref StructureIDs. - // If baseCell != base, then baseCell must be a proxy for another object. if (baseCell != slot.base()) { - ctiRepatchCallByReturnAddress(returnAddress, reinterpret_cast<void*>(cti_op_put_by_id_generic)); + ctiPatchCallByReturnAddress(returnAddress, reinterpret_cast<void*>(cti_op_put_by_id_generic)); return; } - // StructureID transition, cache transition info + StructureStubInfo* stubInfo = &codeBlock->getStubInfo(returnAddress); + + // Cache hit: Specialize instruction and ref Structures. + + // Structure transition, cache transition info if (slot.type() == PutPropertySlot::NewProperty) { - vPC[0] = getOpcode(op_put_by_id_transition); - vPC[4] = structureID->previousID(); - vPC[5] = structureID; - StructureIDChain* chain = structureID->cachedPrototypeChain(); + StructureChain* chain = structure->cachedPrototypeChain(); if (!chain) { - chain = cachePrototypeChain(callFrame, structureID); + chain = cachePrototypeChain(callFrame, structure); if (!chain) { - // This happens if someone has manually inserted null into the prototype chain - vPC[0] = getOpcode(op_put_by_id_generic); + // This happens if someone has manually inserted null into the prototype chain + stubInfo->opcodeID = op_put_by_id_generic; return; } } - vPC[6] = chain; - vPC[7] = slot.cachedOffset(); - codeBlock->refStructureIDs(vPC); - CTI::compilePutByIdTransition(this, callFrame, codeBlock, structureID->previousID(), structureID, slot.cachedOffset(), chain, returnAddress); + stubInfo->initPutByIdTransition(structure->previousID(), structure, chain); + JIT::compilePutByIdTransition(callFrame->scopeChain()->globalData, codeBlock, stubInfo, structure->previousID(), structure, slot.cachedOffset(), chain, returnAddress); return; } - vPC[0] = getOpcode(op_put_by_id_replace); - vPC[4] = structureID; - vPC[5] = slot.cachedOffset(); - codeBlock->refStructureIDs(vPC); + stubInfo->initPutByIdReplace(structure); #if USE(CTI_REPATCH_PIC) UNUSED_PARAM(callFrame); - CTI::patchPutByIdReplace(codeBlock, structureID, slot.cachedOffset(), returnAddress); + JIT::patchPutByIdReplace(stubInfo, structure, slot.cachedOffset(), returnAddress); #else - CTI::compilePutByIdReplace(this, callFrame, codeBlock, structureID, slot.cachedOffset(), returnAddress); + JIT::compilePutByIdReplace(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, structure, slot.cachedOffset(), returnAddress); #endif } -void* Machine::getCTIArrayLengthTrampoline(CallFrame* callFrame, CodeBlock* codeBlock) -{ - if (!m_ctiArrayLengthTrampoline) - m_ctiArrayLengthTrampoline = CTI::compileArrayLengthTrampoline(this, callFrame, codeBlock); - - return m_ctiArrayLengthTrampoline; -} - -void* Machine::getCTIStringLengthTrampoline(CallFrame* callFrame, CodeBlock* codeBlock) -{ - if (!m_ctiStringLengthTrampoline) - m_ctiStringLengthTrampoline = CTI::compileStringLengthTrampoline(this, callFrame, codeBlock); - - return m_ctiStringLengthTrampoline; -} - -NEVER_INLINE void Machine::tryCTICacheGetByID(CallFrame* callFrame, CodeBlock* codeBlock, void* returnAddress, JSValue* baseValue, const Identifier& propertyName, const PropertySlot& slot) +NEVER_INLINE void Interpreter::tryCTICacheGetByID(CallFrame* callFrame, CodeBlock* codeBlock, void* returnAddress, JSValuePtr baseValue, const Identifier& propertyName, const PropertySlot& slot) { // FIXME: Write a test that proves we need to check for recursion here just // like the interpreter does, then add a check for recursion. // FIXME: Cache property access for immediates. - if (JSImmediate::isImmediate(baseValue)) { - ctiRepatchCallByReturnAddress(returnAddress, reinterpret_cast<void*>(cti_op_get_by_id_generic)); + if (!baseValue.isCell()) { + ctiPatchCallByReturnAddress(returnAddress, reinterpret_cast<void*>(cti_op_get_by_id_generic)); return; } if (isJSArray(baseValue) && propertyName == callFrame->propertyNames().length) { #if USE(CTI_REPATCH_PIC) - CTI::compilePatchGetArrayLength(this, callFrame, codeBlock, returnAddress); + JIT::compilePatchGetArrayLength(callFrame->scopeChain()->globalData, codeBlock, returnAddress); #else - ctiRepatchCallByReturnAddress(returnAddress, getCTIArrayLengthTrampoline(callFrame, codeBlock)); + ctiPatchCallByReturnAddress(returnAddress, m_ctiArrayLengthTrampoline); #endif return; } if (isJSString(baseValue) && propertyName == callFrame->propertyNames().length) { - // The tradeoff of compiling an repatched inline string length access routine does not seem + // The tradeoff of compiling an patched inline string length access routine does not seem // to pay off, so we currently only do this for arrays. - ctiRepatchCallByReturnAddress(returnAddress, getCTIStringLengthTrampoline(callFrame, codeBlock)); + ctiPatchCallByReturnAddress(returnAddress, m_ctiStringLengthTrampoline); return; } // Uncacheable: give up. if (!slot.isCacheable()) { - ctiRepatchCallByReturnAddress(returnAddress, reinterpret_cast<void*>(cti_op_get_by_id_generic)); + ctiPatchCallByReturnAddress(returnAddress, reinterpret_cast<void*>(cti_op_get_by_id_generic)); return; } JSCell* baseCell = asCell(baseValue); - StructureID* structureID = baseCell->structureID(); + Structure* structure = baseCell->structure(); - if (structureID->isDictionary()) { - ctiRepatchCallByReturnAddress(returnAddress, reinterpret_cast<void*>(cti_op_get_by_id_generic)); + if (structure->isDictionary()) { + ctiPatchCallByReturnAddress(returnAddress, reinterpret_cast<void*>(cti_op_get_by_id_generic)); return; } // In the interpreter the last structure is trapped here; in CTI we use the // *_second method to achieve a similar (but not quite the same) effect. - unsigned vPCIndex = codeBlock->ctiReturnAddressVPCMap.get(returnAddress); - Instruction* vPC = codeBlock->instructions.begin() + vPCIndex; + StructureStubInfo* stubInfo = &codeBlock->getStubInfo(returnAddress); - // Cache hit: Specialize instruction and ref StructureIDs. + // Cache hit: Specialize instruction and ref Structures. if (slot.slotBase() == baseValue) { - // set this up, so derefStructureIDs can do it's job. - vPC[0] = getOpcode(op_get_by_id_self); - vPC[4] = structureID; - vPC[5] = slot.cachedOffset(); - codeBlock->refStructureIDs(vPC); + // set this up, so derefStructures can do it's job. + stubInfo->initGetByIdSelf(structure); #if USE(CTI_REPATCH_PIC) - CTI::patchGetByIdSelf(codeBlock, structureID, slot.cachedOffset(), returnAddress); + JIT::patchGetByIdSelf(stubInfo, structure, slot.cachedOffset(), returnAddress); #else - CTI::compileGetByIdSelf(this, callFrame, codeBlock, structureID, slot.cachedOffset(), returnAddress); + JIT::compileGetByIdSelf(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, structure, slot.cachedOffset(), returnAddress); #endif return; } - if (slot.slotBase() == structureID->prototypeForLookup(callFrame)) { - ASSERT(slot.slotBase()->isObject()); + if (slot.slotBase() == structure->prototypeForLookup(callFrame)) { + ASSERT(slot.slotBase().isObject()); JSObject* slotBaseObject = asObject(slot.slotBase()); - // Heavy access to a prototype is a good indication that it's not being - // used as a dictionary. - if (slotBaseObject->structureID()->isDictionary()) { - RefPtr<StructureID> transition = StructureID::fromDictionaryTransition(slotBaseObject->structureID()); - slotBaseObject->setStructureID(transition.release()); - asObject(baseValue)->structureID()->setCachedPrototypeChain(0); + // Since we're accessing a prototype in a loop, it's a good bet that it + // should not be treated as a dictionary. + if (slotBaseObject->structure()->isDictionary()) { + RefPtr<Structure> transition = Structure::fromDictionaryTransition(slotBaseObject->structure()); + slotBaseObject->setStructure(transition.release()); + asCell(baseValue)->structure()->setCachedPrototypeChain(0); } + + stubInfo->initGetByIdProto(structure, slotBaseObject->structure()); - vPC[0] = getOpcode(op_get_by_id_proto); - vPC[4] = structureID; - vPC[5] = slotBaseObject->structureID(); - vPC[6] = slot.cachedOffset(); - codeBlock->refStructureIDs(vPC); - - CTI::compileGetByIdProto(this, callFrame, codeBlock, structureID, slotBaseObject->structureID(), slot.cachedOffset(), returnAddress); + JIT::compileGetByIdProto(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, structure, slotBaseObject->structure(), slot.cachedOffset(), returnAddress); return; } - size_t count = 0; - JSObject* o = asObject(baseValue); - while (slot.slotBase() != o) { - JSValue* v = o->structureID()->prototypeForLookup(callFrame); - - // If we didn't find slotBase in baseValue's prototype chain, then baseValue - // must be a proxy for another object. - - if (v->isNull()) { - vPC[0] = getOpcode(op_get_by_id_generic); - return; - } - - o = asObject(v); - - // Heavy access to a prototype is a good indication that it's not being - // used as a dictionary. - if (o->structureID()->isDictionary()) { - RefPtr<StructureID> transition = StructureID::fromDictionaryTransition(o->structureID()); - o->setStructureID(transition.release()); - asObject(baseValue)->structureID()->setCachedPrototypeChain(0); - } - - ++count; + size_t count = countPrototypeChainEntriesAndCheckForProxies(callFrame, baseValue, slot); + if (!count) { + stubInfo->opcodeID = op_get_by_id_generic; + return; } - StructureIDChain* chain = structureID->cachedPrototypeChain(); + StructureChain* chain = structure->cachedPrototypeChain(); if (!chain) - chain = cachePrototypeChain(callFrame, structureID); - + chain = cachePrototypeChain(callFrame, structure); ASSERT(chain); - vPC[0] = getOpcode(op_get_by_id_chain); - vPC[4] = structureID; - vPC[5] = chain; - vPC[6] = count; - vPC[7] = slot.cachedOffset(); - codeBlock->refStructureIDs(vPC); - CTI::compileGetByIdChain(this, callFrame, codeBlock, structureID, chain, count, slot.cachedOffset(), returnAddress); + stubInfo->initGetByIdChain(structure, chain); + + JIT::compileGetByIdChain(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, structure, chain, count, slot.cachedOffset(), returnAddress); } +#endif + +#if USE(JIT_STUB_ARGUMENT_VA_LIST) +#define SETUP_VA_LISTL_ARGS va_list vl_args; va_start(vl_args, args) +#else // JIT_STUB_ARGUMENT_REGISTER or JIT_STUB_ARGUMENT_STACK +#define SETUP_VA_LISTL_ARGS +#endif + #ifndef NDEBUG extern "C" { @@ -4318,15 +4196,15 @@ struct StackHack { void* savedReturnAddress; }; -#define CTI_STACK_HACK() StackHack stackHack(&CTI_RETURN_ADDRESS_SLOT) -#define CTI_SET_RETURN_ADDRESS(address) stackHack.savedReturnAddress = address -#define CTI_RETURN_ADDRESS stackHack.savedReturnAddress +#define BEGIN_STUB_FUNCTION() SETUP_VA_LISTL_ARGS; StackHack stackHack(&STUB_RETURN_ADDRESS_SLOT) +#define STUB_SET_RETURN_ADDRESS(address) stackHack.savedReturnAddress = address +#define STUB_RETURN_ADDRESS stackHack.savedReturnAddress #else -#define CTI_STACK_HACK() (void)0 -#define CTI_SET_RETURN_ADDRESS(address) ctiSetReturnAddress(&CTI_RETURN_ADDRESS_SLOT, address); -#define CTI_RETURN_ADDRESS CTI_RETURN_ADDRESS_SLOT +#define BEGIN_STUB_FUNCTION() SETUP_VA_LISTL_ARGS +#define STUB_SET_RETURN_ADDRESS(address) ctiSetReturnAddress(&STUB_RETURN_ADDRESS_SLOT, address); +#define STUB_RETURN_ADDRESS STUB_RETURN_ADDRESS_SLOT #endif @@ -4334,11 +4212,17 @@ struct StackHack { // to get the address of the ctiVMThrowTrampoline function. It's also // good to keep the code size down by leaving as much of the exception // handling code out of line as possible. -static NEVER_INLINE void setUpThrowTrampolineReturnAddress(JSGlobalData* globalData, void*& returnAddress) +static NEVER_INLINE void returnToThrowTrampoline(JSGlobalData* globalData, void* exceptionLocation, void*& returnAddressSlot) { ASSERT(globalData->exception); - globalData->throwReturnAddress = returnAddress; - ctiSetReturnAddress(&returnAddress, reinterpret_cast<void*>(ctiVMThrowTrampoline)); + globalData->exceptionLocation = exceptionLocation; + ctiSetReturnAddress(&returnAddressSlot, reinterpret_cast<void*>(ctiVMThrowTrampoline)); +} + +static NEVER_INLINE void throwStackOverflowError(CallFrame* callFrame, JSGlobalData* globalData, void* exceptionLocation, void*& returnAddressSlot) +{ + globalData->exception = createStackOverflowError(callFrame); + returnToThrowTrampoline(globalData, exceptionLocation, returnAddressSlot); } #define VM_THROW_EXCEPTION() \ @@ -4349,23 +4233,22 @@ static NEVER_INLINE void setUpThrowTrampolineReturnAddress(JSGlobalData* globalD #define VM_THROW_EXCEPTION_2() \ do { \ VM_THROW_EXCEPTION_AT_END(); \ - VoidPtrPairValue pair = {{ 0, 0 }}; \ - return pair.i; \ + RETURN_PAIR(0, 0); \ } while (0) #define VM_THROW_EXCEPTION_AT_END() \ - setUpThrowTrampolineReturnAddress(ARG_globalData, CTI_RETURN_ADDRESS) + returnToThrowTrampoline(ARG_globalData, STUB_RETURN_ADDRESS, STUB_RETURN_ADDRESS) -#define VM_CHECK_EXCEPTION() \ +#define CHECK_FOR_EXCEPTION() \ do { \ if (UNLIKELY(ARG_globalData->exception != noValue())) \ VM_THROW_EXCEPTION(); \ } while (0) -#define VM_CHECK_EXCEPTION_AT_END() \ +#define CHECK_FOR_EXCEPTION_AT_END() \ do { \ if (UNLIKELY(ARG_globalData->exception != noValue())) \ VM_THROW_EXCEPTION_AT_END(); \ } while (0) -#define VM_CHECK_EXCEPTION_VOID() \ +#define CHECK_FOR_EXCEPTION_VOID() \ do { \ if (UNLIKELY(ARG_globalData->exception != noValue())) { \ VM_THROW_EXCEPTION_AT_END(); \ @@ -4373,433 +4256,614 @@ static NEVER_INLINE void setUpThrowTrampolineReturnAddress(JSGlobalData* globalD } \ } while (0) -JSObject* Machine::cti_op_convert_this(CTI_ARGS) +JSObject* Interpreter::cti_op_convert_this(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); - JSValue* v1 = ARG_src1; + JSValuePtr v1 = ARG_src1; CallFrame* callFrame = ARG_callFrame; - JSObject* result = v1->toThisObject(callFrame); - VM_CHECK_EXCEPTION_AT_END(); + JSObject* result = v1.toThisObject(callFrame); + CHECK_FOR_EXCEPTION_AT_END(); return result; } -void Machine::cti_op_end(CTI_ARGS) +void Interpreter::cti_op_end(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); ScopeChainNode* scopeChain = ARG_callFrame->scopeChain(); ASSERT(scopeChain->refCount > 1); scopeChain->deref(); } -JSValue* Machine::cti_op_add(CTI_ARGS) +JSValueEncodedAsPointer* Interpreter::cti_op_add(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); - JSValue* v1 = ARG_src1; - JSValue* v2 = ARG_src2; + JSValuePtr v1 = ARG_src1; + JSValuePtr v2 = ARG_src2; double left; double right = 0.0; - bool rightIsNumber = fastIsNumber(v2, right); - if (rightIsNumber && fastIsNumber(v1, left)) - return jsNumber(ARG_globalData, left + right); + bool rightIsNumber = v2.getNumber(right); + if (rightIsNumber && v1.getNumber(left)) + return JSValuePtr::encode(jsNumber(ARG_globalData, left + right)); CallFrame* callFrame = ARG_callFrame; - bool leftIsString = v1->isString(); - if (leftIsString && v2->isString()) { + bool leftIsString = v1.isString(); + if (leftIsString && v2.isString()) { RefPtr<UString::Rep> value = concatenate(asString(v1)->value().rep(), asString(v2)->value().rep()); if (UNLIKELY(!value)) { throwOutOfMemoryError(callFrame); VM_THROW_EXCEPTION(); } - return jsString(ARG_globalData, value.release()); + return JSValuePtr::encode(jsString(ARG_globalData, value.release())); } if (rightIsNumber & leftIsString) { - RefPtr<UString::Rep> value = JSImmediate::isImmediate(v2) ? - concatenate(asString(v1)->value().rep(), JSImmediate::getTruncatedInt32(v2)) : + RefPtr<UString::Rep> value = v2.isInt32Fast() ? + concatenate(asString(v1)->value().rep(), v2.getInt32Fast()) : concatenate(asString(v1)->value().rep(), right); if (UNLIKELY(!value)) { throwOutOfMemoryError(callFrame); VM_THROW_EXCEPTION(); } - return jsString(ARG_globalData, value.release()); + return JSValuePtr::encode(jsString(ARG_globalData, value.release())); } // All other cases are pretty uncommon - JSValue* result = jsAddSlowCase(callFrame, v1, v2); - VM_CHECK_EXCEPTION_AT_END(); - return result; + JSValuePtr result = jsAddSlowCase(callFrame, v1, v2); + CHECK_FOR_EXCEPTION_AT_END(); + return JSValuePtr::encode(result); } -JSValue* Machine::cti_op_pre_inc(CTI_ARGS) +JSValueEncodedAsPointer* Interpreter::cti_op_pre_inc(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); - JSValue* v = ARG_src1; + JSValuePtr v = ARG_src1; CallFrame* callFrame = ARG_callFrame; - JSValue* result = jsNumber(ARG_globalData, v->toNumber(callFrame) + 1); - VM_CHECK_EXCEPTION_AT_END(); - return result; + JSValuePtr result = jsNumber(ARG_globalData, v.toNumber(callFrame) + 1); + CHECK_FOR_EXCEPTION_AT_END(); + return JSValuePtr::encode(result); } -void Machine::cti_timeout_check(CTI_ARGS) +int Interpreter::cti_timeout_check(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); + Interpreter* interpreter = ARG_globalData->interpreter; - if (ARG_globalData->machine->checkTimeout(ARG_callFrame->dynamicGlobalObject())) { + if (interpreter->checkTimeout(ARG_callFrame->dynamicGlobalObject())) { ARG_globalData->exception = createInterruptedExecutionException(ARG_globalData); VM_THROW_EXCEPTION_AT_END(); } + + return interpreter->m_ticksUntilNextTimeoutCheck; } -NEVER_INLINE void Machine::throwStackOverflowPreviousFrame(CallFrame* callFrame, JSGlobalData* globalData, void*& returnAddress) -{ - globalData->exception = createStackOverflowError(callFrame->callerFrame()); - globalData->throwReturnAddress = callFrame->returnPC(); - ctiSetReturnAddress(&returnAddress, reinterpret_cast<void*>(ctiVMThrowTrampoline)); -} - -void Machine::cti_register_file_check(CTI_ARGS) +void Interpreter::cti_register_file_check(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); - if (LIKELY(ARG_registerFile->grow(ARG_callFrame + ARG_callFrame->codeBlock()->numCalleeRegisters))) + if (LIKELY(ARG_registerFile->grow(ARG_callFrame + ARG_callFrame->codeBlock()->m_numCalleeRegisters))) return; - ARG_setCallFrame(ARG_callFrame->callerFrame()); - throwStackOverflowPreviousFrame(ARG_callFrame, ARG_globalData, CTI_RETURN_ADDRESS); + // Rewind to the previous call frame because op_call already optimistically + // moved the call frame forward. + CallFrame* oldCallFrame = ARG_callFrame->callerFrame(); + ARG_setCallFrame(oldCallFrame); + throwStackOverflowError(oldCallFrame, ARG_globalData, oldCallFrame->returnPC(), STUB_RETURN_ADDRESS); } -int Machine::cti_op_loop_if_less(CTI_ARGS) +int Interpreter::cti_op_loop_if_less(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); - JSValue* src1 = ARG_src1; - JSValue* src2 = ARG_src2; + JSValuePtr src1 = ARG_src1; + JSValuePtr src2 = ARG_src2; CallFrame* callFrame = ARG_callFrame; bool result = jsLess(callFrame, src1, src2); - VM_CHECK_EXCEPTION_AT_END(); + CHECK_FOR_EXCEPTION_AT_END(); return result; } -int Machine::cti_op_loop_if_lesseq(CTI_ARGS) +int Interpreter::cti_op_loop_if_lesseq(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); - JSValue* src1 = ARG_src1; - JSValue* src2 = ARG_src2; + JSValuePtr src1 = ARG_src1; + JSValuePtr src2 = ARG_src2; CallFrame* callFrame = ARG_callFrame; bool result = jsLessEq(callFrame, src1, src2); - VM_CHECK_EXCEPTION_AT_END(); + CHECK_FOR_EXCEPTION_AT_END(); return result; } -JSObject* Machine::cti_op_new_object(CTI_ARGS) +JSObject* Interpreter::cti_op_new_object(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); return constructEmptyObject(ARG_callFrame); } -void Machine::cti_op_put_by_id(CTI_ARGS) +void Interpreter::cti_op_put_by_id_generic(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); + + PutPropertySlot slot; + ARG_src1.put(ARG_callFrame, *ARG_id2, ARG_src3, slot); + CHECK_FOR_EXCEPTION_AT_END(); +} + +JSValueEncodedAsPointer* Interpreter::cti_op_get_by_id_generic(STUB_ARGS) +{ + BEGIN_STUB_FUNCTION(); CallFrame* callFrame = ARG_callFrame; Identifier& ident = *ARG_id2; - PutPropertySlot slot; - ARG_src1->put(callFrame, ident, ARG_src3, slot); - - ctiRepatchCallByReturnAddress(CTI_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_put_by_id_second)); + JSValuePtr baseValue = ARG_src1; + PropertySlot slot(baseValue); + JSValuePtr result = baseValue.get(callFrame, ident, slot); - VM_CHECK_EXCEPTION_AT_END(); + CHECK_FOR_EXCEPTION_AT_END(); + return JSValuePtr::encode(result); } -void Machine::cti_op_put_by_id_second(CTI_ARGS) +#if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS) + +void Interpreter::cti_op_put_by_id(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); + + CallFrame* callFrame = ARG_callFrame; + Identifier& ident = *ARG_id2; PutPropertySlot slot; - ARG_src1->put(ARG_callFrame, *ARG_id2, ARG_src3, slot); - ARG_globalData->machine->tryCTICachePutByID(ARG_callFrame, ARG_callFrame->codeBlock(), CTI_RETURN_ADDRESS, ARG_src1, slot); - VM_CHECK_EXCEPTION_AT_END(); + ARG_src1.put(callFrame, ident, ARG_src3, slot); + + ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_put_by_id_second)); + + CHECK_FOR_EXCEPTION_AT_END(); } -void Machine::cti_op_put_by_id_generic(CTI_ARGS) +void Interpreter::cti_op_put_by_id_second(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); PutPropertySlot slot; - ARG_src1->put(ARG_callFrame, *ARG_id2, ARG_src3, slot); - VM_CHECK_EXCEPTION_AT_END(); + ARG_src1.put(ARG_callFrame, *ARG_id2, ARG_src3, slot); + ARG_globalData->interpreter->tryCTICachePutByID(ARG_callFrame, ARG_callFrame->codeBlock(), STUB_RETURN_ADDRESS, ARG_src1, slot); + CHECK_FOR_EXCEPTION_AT_END(); } -void Machine::cti_op_put_by_id_fail(CTI_ARGS) +void Interpreter::cti_op_put_by_id_fail(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); CallFrame* callFrame = ARG_callFrame; Identifier& ident = *ARG_id2; PutPropertySlot slot; - ARG_src1->put(callFrame, ident, ARG_src3, slot); + ARG_src1.put(callFrame, ident, ARG_src3, slot); - // should probably uncachePutByID() ... this would mean doing a vPC lookup - might be worth just bleeding this until the end. - ctiRepatchCallByReturnAddress(CTI_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_put_by_id_generic)); - - VM_CHECK_EXCEPTION_AT_END(); + CHECK_FOR_EXCEPTION_AT_END(); } -JSValue* Machine::cti_op_get_by_id(CTI_ARGS) +JSValueEncodedAsPointer* Interpreter::cti_op_get_by_id(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); CallFrame* callFrame = ARG_callFrame; Identifier& ident = *ARG_id2; - JSValue* baseValue = ARG_src1; + JSValuePtr baseValue = ARG_src1; PropertySlot slot(baseValue); - JSValue* result = baseValue->get(callFrame, ident, slot); + JSValuePtr result = baseValue.get(callFrame, ident, slot); - ctiRepatchCallByReturnAddress(CTI_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_get_by_id_second)); + ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_get_by_id_second)); - VM_CHECK_EXCEPTION_AT_END(); - return result; + CHECK_FOR_EXCEPTION_AT_END(); + return JSValuePtr::encode(result); } -JSValue* Machine::cti_op_get_by_id_second(CTI_ARGS) +JSValueEncodedAsPointer* Interpreter::cti_op_get_by_id_second(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); CallFrame* callFrame = ARG_callFrame; Identifier& ident = *ARG_id2; - JSValue* baseValue = ARG_src1; + JSValuePtr baseValue = ARG_src1; PropertySlot slot(baseValue); - JSValue* result = baseValue->get(callFrame, ident, slot); + JSValuePtr result = baseValue.get(callFrame, ident, slot); - ARG_globalData->machine->tryCTICacheGetByID(callFrame, callFrame->codeBlock(), CTI_RETURN_ADDRESS, baseValue, ident, slot); + ARG_globalData->interpreter->tryCTICacheGetByID(callFrame, callFrame->codeBlock(), STUB_RETURN_ADDRESS, baseValue, ident, slot); - VM_CHECK_EXCEPTION_AT_END(); - return result; + CHECK_FOR_EXCEPTION_AT_END(); + return JSValuePtr::encode(result); } -JSValue* Machine::cti_op_get_by_id_generic(CTI_ARGS) +JSValueEncodedAsPointer* Interpreter::cti_op_get_by_id_self_fail(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); CallFrame* callFrame = ARG_callFrame; Identifier& ident = *ARG_id2; - JSValue* baseValue = ARG_src1; + JSValuePtr baseValue = ARG_src1; PropertySlot slot(baseValue); - JSValue* result = baseValue->get(callFrame, ident, slot); + JSValuePtr result = baseValue.get(callFrame, ident, slot); - VM_CHECK_EXCEPTION_AT_END(); - return result; + CHECK_FOR_EXCEPTION(); + + if (baseValue.isCell() + && slot.isCacheable() + && !asCell(baseValue)->structure()->isDictionary() + && slot.slotBase() == baseValue) { + + CodeBlock* codeBlock = callFrame->codeBlock(); + StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS); + + ASSERT(slot.slotBase().isObject()); + + PolymorphicAccessStructureList* polymorphicStructureList; + int listIndex = 1; + + if (stubInfo->opcodeID == op_get_by_id_self) { + ASSERT(!stubInfo->stubRoutine); + polymorphicStructureList = new PolymorphicAccessStructureList(0, stubInfo->u.getByIdSelf.baseObjectStructure); + stubInfo->initGetByIdSelfList(polymorphicStructureList, 2); + } else { + polymorphicStructureList = stubInfo->u.getByIdSelfList.structureList; + listIndex = stubInfo->u.getByIdSelfList.listSize; + stubInfo->u.getByIdSelfList.listSize++; + } + + JIT::compileGetByIdSelfList(callFrame->scopeChain()->globalData, codeBlock, stubInfo, polymorphicStructureList, listIndex, asCell(baseValue)->structure(), slot.cachedOffset()); + + if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1)) + ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_get_by_id_generic)); + } else { + ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_get_by_id_generic)); + } + return JSValuePtr::encode(result); +} + +static PolymorphicAccessStructureList* getPolymorphicAccessStructureListSlot(StructureStubInfo* stubInfo, int& listIndex) +{ + PolymorphicAccessStructureList* prototypeStructureList = 0; + listIndex = 1; + + switch (stubInfo->opcodeID) { + case op_get_by_id_proto: + prototypeStructureList = new PolymorphicAccessStructureList(stubInfo->stubRoutine, stubInfo->u.getByIdProto.baseObjectStructure, stubInfo->u.getByIdProto.prototypeStructure); + stubInfo->stubRoutine = 0; + stubInfo->initGetByIdProtoList(prototypeStructureList, 2); + break; + case op_get_by_id_chain: + prototypeStructureList = new PolymorphicAccessStructureList(stubInfo->stubRoutine, stubInfo->u.getByIdChain.baseObjectStructure, stubInfo->u.getByIdChain.chain); + stubInfo->stubRoutine = 0; + stubInfo->initGetByIdProtoList(prototypeStructureList, 2); + break; + case op_get_by_id_proto_list: + prototypeStructureList = stubInfo->u.getByIdProtoList.structureList; + listIndex = stubInfo->u.getByIdProtoList.listSize; + stubInfo->u.getByIdProtoList.listSize++; + break; + default: + ASSERT_NOT_REACHED(); + } + + ASSERT(listIndex < POLYMORPHIC_LIST_CACHE_SIZE); + return prototypeStructureList; } -JSValue* Machine::cti_op_get_by_id_fail(CTI_ARGS) +JSValueEncodedAsPointer* Interpreter::cti_op_get_by_id_proto_list(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); CallFrame* callFrame = ARG_callFrame; - Identifier& ident = *ARG_id2; - JSValue* baseValue = ARG_src1; + JSValuePtr baseValue = ARG_src1; PropertySlot slot(baseValue); - JSValue* result = baseValue->get(callFrame, ident, slot); + JSValuePtr result = baseValue.get(callFrame, *ARG_id2, slot); - // should probably uncacheGetByID() ... this would mean doing a vPC lookup - might be worth just bleeding this until the end. - ctiRepatchCallByReturnAddress(CTI_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_get_by_id_generic)); + CHECK_FOR_EXCEPTION(); - VM_CHECK_EXCEPTION_AT_END(); - return result; + if (!baseValue.isCell() || !slot.isCacheable() || asCell(baseValue)->structure()->isDictionary()) { + ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_get_by_id_proto_fail)); + return JSValuePtr::encode(result); + } + + Structure* structure = asCell(baseValue)->structure(); + CodeBlock* codeBlock = callFrame->codeBlock(); + StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS); + + ASSERT(slot.slotBase().isObject()); + JSObject* slotBaseObject = asObject(slot.slotBase()); + + if (slot.slotBase() == baseValue) + ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_get_by_id_proto_fail)); + else if (slot.slotBase() == asCell(baseValue)->structure()->prototypeForLookup(callFrame)) { + // Since we're accessing a prototype in a loop, it's a good bet that it + // should not be treated as a dictionary. + if (slotBaseObject->structure()->isDictionary()) { + RefPtr<Structure> transition = Structure::fromDictionaryTransition(slotBaseObject->structure()); + slotBaseObject->setStructure(transition.release()); + asCell(baseValue)->structure()->setCachedPrototypeChain(0); + } + + int listIndex; + PolymorphicAccessStructureList* prototypeStructureList = getPolymorphicAccessStructureListSlot(stubInfo, listIndex); + + JIT::compileGetByIdProtoList(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, prototypeStructureList, listIndex, structure, slotBaseObject->structure(), slot.cachedOffset()); + + if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1)) + ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_get_by_id_proto_list_full)); + } else if (size_t count = countPrototypeChainEntriesAndCheckForProxies(callFrame, baseValue, slot)) { + StructureChain* chain = structure->cachedPrototypeChain(); + if (!chain) + chain = cachePrototypeChain(callFrame, structure); + ASSERT(chain); + + int listIndex; + PolymorphicAccessStructureList* prototypeStructureList = getPolymorphicAccessStructureListSlot(stubInfo, listIndex); + + JIT::compileGetByIdChainList(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, prototypeStructureList, listIndex, structure, chain, count, slot.cachedOffset()); + + if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1)) + ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_get_by_id_proto_list_full)); + } else + ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_get_by_id_proto_fail)); + + return JSValuePtr::encode(result); +} + +JSValueEncodedAsPointer* Interpreter::cti_op_get_by_id_proto_list_full(STUB_ARGS) +{ + BEGIN_STUB_FUNCTION(); + + JSValuePtr baseValue = ARG_src1; + PropertySlot slot(baseValue); + JSValuePtr result = baseValue.get(ARG_callFrame, *ARG_id2, slot); + + CHECK_FOR_EXCEPTION_AT_END(); + return JSValuePtr::encode(result); } -JSValue* Machine::cti_op_instanceof(CTI_ARGS) +JSValueEncodedAsPointer* Interpreter::cti_op_get_by_id_proto_fail(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); + + JSValuePtr baseValue = ARG_src1; + PropertySlot slot(baseValue); + JSValuePtr result = baseValue.get(ARG_callFrame, *ARG_id2, slot); + + CHECK_FOR_EXCEPTION_AT_END(); + return JSValuePtr::encode(result); +} + +JSValueEncodedAsPointer* Interpreter::cti_op_get_by_id_array_fail(STUB_ARGS) +{ + BEGIN_STUB_FUNCTION(); + + JSValuePtr baseValue = ARG_src1; + PropertySlot slot(baseValue); + JSValuePtr result = baseValue.get(ARG_callFrame, *ARG_id2, slot); + + CHECK_FOR_EXCEPTION_AT_END(); + return JSValuePtr::encode(result); +} + +JSValueEncodedAsPointer* Interpreter::cti_op_get_by_id_string_fail(STUB_ARGS) +{ + BEGIN_STUB_FUNCTION(); + + JSValuePtr baseValue = ARG_src1; + PropertySlot slot(baseValue); + JSValuePtr result = baseValue.get(ARG_callFrame, *ARG_id2, slot); + + CHECK_FOR_EXCEPTION_AT_END(); + return JSValuePtr::encode(result); +} + +#endif + +JSValueEncodedAsPointer* Interpreter::cti_op_instanceof(STUB_ARGS) +{ + BEGIN_STUB_FUNCTION(); CallFrame* callFrame = ARG_callFrame; - JSValue* value = ARG_src1; - JSValue* baseVal = ARG_src2; - JSValue* proto = ARG_src3; + JSValuePtr value = ARG_src1; + JSValuePtr baseVal = ARG_src2; + JSValuePtr proto = ARG_src3; // at least one of these checks must have failed to get to the slow case - ASSERT(JSImmediate::isAnyImmediate(value, baseVal, proto) - || !value->isObject() || !baseVal->isObject() || !proto->isObject() - || (asObject(baseVal)->structureID()->typeInfo().flags() & (ImplementsHasInstance | OverridesHasInstance)) != ImplementsHasInstance); + ASSERT(!value.isCell() || !baseVal.isCell() || !proto.isCell() + || !value.isObject() || !baseVal.isObject() || !proto.isObject() + || (asObject(baseVal)->structure()->typeInfo().flags() & (ImplementsHasInstance | OverridesHasInstance)) != ImplementsHasInstance); - if (!baseVal->isObject()) { + if (!baseVal.isObject()) { CallFrame* callFrame = ARG_callFrame; CodeBlock* codeBlock = callFrame->codeBlock(); - ASSERT(codeBlock->ctiReturnAddressVPCMap.contains(CTI_RETURN_ADDRESS)); - unsigned vPCIndex = codeBlock->ctiReturnAddressVPCMap.get(CTI_RETURN_ADDRESS); - ARG_globalData->exception = createInvalidParamError(callFrame, "instanceof", baseVal, codeBlock->instructions.begin() + vPCIndex, codeBlock); + unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS); + ARG_globalData->exception = createInvalidParamError(callFrame, "instanceof", baseVal, vPCIndex, codeBlock); VM_THROW_EXCEPTION(); } - if (!asObject(baseVal)->structureID()->typeInfo().implementsHasInstance()) - return jsBoolean(false); + if (!asObject(baseVal)->structure()->typeInfo().implementsHasInstance()) + return JSValuePtr::encode(jsBoolean(false)); - if (!proto->isObject()) { + if (!proto.isObject()) { throwError(callFrame, TypeError, "instanceof called on an object with an invalid prototype property."); VM_THROW_EXCEPTION(); } - if (!value->isObject()) - return jsBoolean(false); + if (!value.isObject()) + return JSValuePtr::encode(jsBoolean(false)); - JSValue* result = jsBoolean(asObject(baseVal)->hasInstance(callFrame, value, proto)); - VM_CHECK_EXCEPTION_AT_END(); + JSValuePtr result = jsBoolean(asObject(baseVal)->hasInstance(callFrame, value, proto)); + CHECK_FOR_EXCEPTION_AT_END(); - return result; + return JSValuePtr::encode(result); } -JSValue* Machine::cti_op_del_by_id(CTI_ARGS) +JSValueEncodedAsPointer* Interpreter::cti_op_del_by_id(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); CallFrame* callFrame = ARG_callFrame; - Identifier& ident = *ARG_id2; - JSObject* baseObj = ARG_src1->toObject(callFrame); + JSObject* baseObj = ARG_src1.toObject(callFrame); - JSValue* result = jsBoolean(baseObj->deleteProperty(callFrame, ident)); - VM_CHECK_EXCEPTION_AT_END(); - return result; + JSValuePtr result = jsBoolean(baseObj->deleteProperty(callFrame, *ARG_id2)); + CHECK_FOR_EXCEPTION_AT_END(); + return JSValuePtr::encode(result); } -JSValue* Machine::cti_op_mul(CTI_ARGS) +JSValueEncodedAsPointer* Interpreter::cti_op_mul(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); - JSValue* src1 = ARG_src1; - JSValue* src2 = ARG_src2; + JSValuePtr src1 = ARG_src1; + JSValuePtr src2 = ARG_src2; double left; double right; - if (fastIsNumber(src1, left) && fastIsNumber(src2, right)) - return jsNumber(ARG_globalData, left * right); + if (src1.getNumber(left) && src2.getNumber(right)) + return JSValuePtr::encode(jsNumber(ARG_globalData, left * right)); CallFrame* callFrame = ARG_callFrame; - JSValue* result = jsNumber(ARG_globalData, src1->toNumber(callFrame) * src2->toNumber(callFrame)); - VM_CHECK_EXCEPTION_AT_END(); - return result; + JSValuePtr result = jsNumber(ARG_globalData, src1.toNumber(callFrame) * src2.toNumber(callFrame)); + CHECK_FOR_EXCEPTION_AT_END(); + return JSValuePtr::encode(result); } -JSObject* Machine::cti_op_new_func(CTI_ARGS) +JSObject* Interpreter::cti_op_new_func(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); return ARG_func1->makeFunction(ARG_callFrame, ARG_callFrame->scopeChain()); } -VoidPtrPair Machine::cti_op_call_JSFunction(CTI_ARGS) +void* Interpreter::cti_op_call_JSFunction(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); #ifndef NDEBUG CallData callData; - ASSERT(ARG_src1->getCallData(callData) == CallTypeJS); + ASSERT(ARG_src1.getCallData(callData) == CallTypeJS); #endif ScopeChainNode* callDataScopeChain = asFunction(ARG_src1)->m_scopeChain.node(); - CodeBlock* newCodeBlock = &asFunction(ARG_src1)->m_body->byteCode(callDataScopeChain); + CodeBlock* newCodeBlock = &asFunction(ARG_src1)->body()->bytecode(callDataScopeChain); + + if (!newCodeBlock->jitCode()) + JIT::compile(ARG_globalData, newCodeBlock); + + return newCodeBlock; +} + +VoidPtrPair Interpreter::cti_op_call_arityCheck(STUB_ARGS) +{ + BEGIN_STUB_FUNCTION(); + CallFrame* callFrame = ARG_callFrame; - size_t registerOffset = ARG_int2; + CodeBlock* newCodeBlock = ARG_codeBlock4; int argCount = ARG_int3; - if (LIKELY(argCount == newCodeBlock->numParameters)) { - VoidPtrPairValue pair = {{ newCodeBlock, CallFrame::create(callFrame->registers() + registerOffset) }}; - return pair.i; - } + ASSERT(argCount != newCodeBlock->m_numParameters); + + CallFrame* oldCallFrame = callFrame->callerFrame(); - if (argCount > newCodeBlock->numParameters) { - size_t numParameters = newCodeBlock->numParameters; - Register* r = callFrame->registers() + registerOffset + numParameters; + if (argCount > newCodeBlock->m_numParameters) { + size_t numParameters = newCodeBlock->m_numParameters; + Register* r = callFrame->registers() + numParameters; Register* argv = r - RegisterFile::CallFrameHeaderSize - numParameters - argCount; for (size_t i = 0; i < numParameters; ++i) argv[i + argCount] = argv[i]; - VoidPtrPairValue pair = {{ newCodeBlock, CallFrame::create(r) }}; - return pair.i; - } + callFrame = CallFrame::create(r); + callFrame->setCallerFrame(oldCallFrame); + } else { + size_t omittedArgCount = newCodeBlock->m_numParameters - argCount; + Register* r = callFrame->registers() + omittedArgCount; + Register* newEnd = r + newCodeBlock->m_numCalleeRegisters; + if (!ARG_registerFile->grow(newEnd)) { + // Rewind to the previous call frame because op_call already optimistically + // moved the call frame forward. + ARG_setCallFrame(oldCallFrame); + throwStackOverflowError(oldCallFrame, ARG_globalData, ARG_returnAddress2, STUB_RETURN_ADDRESS); + RETURN_PAIR(0, 0); + } - size_t omittedArgCount = newCodeBlock->numParameters - argCount; - Register* r = callFrame->registers() + registerOffset + omittedArgCount; - Register* newEnd = r + newCodeBlock->numCalleeRegisters; - if (!ARG_registerFile->grow(newEnd)) { - ARG_globalData->exception = createStackOverflowError(callFrame); - VM_THROW_EXCEPTION_2(); - } + Register* argv = r - RegisterFile::CallFrameHeaderSize - omittedArgCount; + for (size_t i = 0; i < omittedArgCount; ++i) + argv[i] = jsUndefined(); - Register* argv = r - RegisterFile::CallFrameHeaderSize - omittedArgCount; - for (size_t i = 0; i < omittedArgCount; ++i) - argv[i] = jsUndefined(); + callFrame = CallFrame::create(r); + callFrame->setCallerFrame(oldCallFrame); + } - VoidPtrPairValue pair = {{ newCodeBlock, CallFrame::create(r) }}; - return pair.i; + RETURN_PAIR(newCodeBlock, callFrame); } -void* Machine::cti_vm_lazyLinkCall(CTI_ARGS) +void* Interpreter::cti_vm_dontLazyLinkCall(STUB_ARGS) { - CTI_STACK_HACK(); - - Machine* machine = ARG_globalData->machine; - CallFrame* callFrame = CallFrame::create(ARG_callFrame); + BEGIN_STUB_FUNCTION(); JSFunction* callee = asFunction(ARG_src1); - CodeBlock* codeBlock = &callee->m_body->byteCode(callee->m_scopeChain.node()); - if (!codeBlock->ctiCode) - CTI::compile(machine, callFrame, codeBlock); + CodeBlock* codeBlock = &callee->body()->bytecode(callee->m_scopeChain.node()); + if (!codeBlock->jitCode()) + JIT::compile(ARG_globalData, codeBlock); - CTI::linkCall(callee, codeBlock, codeBlock->ctiCode, ARG_linkInfo2, ARG_int3); + ctiPatchCallByReturnAddress(ARG_returnAddress2, ARG_globalData->interpreter->m_ctiVirtualCallLink); - return codeBlock->ctiCode; + return codeBlock->jitCode(); } -void* Machine::cti_vm_compile(CTI_ARGS) +void* Interpreter::cti_vm_lazyLinkCall(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); + + JSFunction* callee = asFunction(ARG_src1); + CodeBlock* codeBlock = &callee->body()->bytecode(callee->m_scopeChain.node()); + if (!codeBlock->jitCode()) + JIT::compile(ARG_globalData, codeBlock); + + CallLinkInfo* callLinkInfo = &ARG_callFrame->callerFrame()->codeBlock()->getCallLinkInfo(ARG_returnAddress2); + JIT::linkCall(callee, codeBlock, codeBlock->jitCode(), callLinkInfo, ARG_int3); - CodeBlock* codeBlock = ARG_callFrame->codeBlock(); - if (!codeBlock->ctiCode) - CTI::compile(ARG_globalData->machine, ARG_callFrame, codeBlock); - return codeBlock->ctiCode; + return codeBlock->jitCode(); } -JSObject* Machine::cti_op_push_activation(CTI_ARGS) +JSObject* Interpreter::cti_op_push_activation(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); - JSActivation* activation = new (ARG_globalData) JSActivation(ARG_callFrame, static_cast<FunctionBodyNode*>(ARG_callFrame->codeBlock()->ownerNode)); + JSActivation* activation = new (ARG_globalData) JSActivation(ARG_callFrame, static_cast<FunctionBodyNode*>(ARG_callFrame->codeBlock()->ownerNode())); ARG_callFrame->setScopeChain(ARG_callFrame->scopeChain()->copy()->push(activation)); return activation; } -JSValue* Machine::cti_op_call_NotJSFunction(CTI_ARGS) +JSValueEncodedAsPointer* Interpreter::cti_op_call_NotJSFunction(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); - JSValue* funcVal = ARG_src1; + JSValuePtr funcVal = ARG_src1; CallData callData; - CallType callType = funcVal->getCallData(callData); + CallType callType = funcVal.getCallData(callData); ASSERT(callType != CallTypeJS); @@ -4809,98 +4873,107 @@ JSValue* Machine::cti_op_call_NotJSFunction(CTI_ARGS) CallFrame* previousCallFrame = ARG_callFrame; CallFrame* callFrame = CallFrame::create(previousCallFrame->registers() + registerOffset); - callFrame->init(0, ARG_instr4 + 1, previousCallFrame->scopeChain(), previousCallFrame, 0, argCount, 0); + callFrame->init(0, static_cast<Instruction*>(STUB_RETURN_ADDRESS), previousCallFrame->scopeChain(), previousCallFrame, 0, argCount, 0); ARG_setCallFrame(callFrame); Register* argv = ARG_callFrame->registers() - RegisterFile::CallFrameHeaderSize - argCount; ArgList argList(argv + 1, argCount - 1); - JSValue* returnValue; + JSValuePtr returnValue; { SamplingTool::HostCallRecord callRecord(CTI_SAMPLER); - returnValue = callData.native.function(callFrame, asObject(funcVal), argv[0].jsValue(callFrame), argList); + + // FIXME: All host methods should be calling toThisObject, but this is not presently the case. + JSValuePtr thisValue = argv[0].jsValue(callFrame); + if (thisValue == jsNull()) + thisValue = callFrame->globalThisValue(); + + returnValue = callData.native.function(callFrame, asObject(funcVal), thisValue, argList); } ARG_setCallFrame(previousCallFrame); - VM_CHECK_EXCEPTION(); + CHECK_FOR_EXCEPTION(); - return returnValue; + return JSValuePtr::encode(returnValue); } ASSERT(callType == CallTypeNone); - ARG_globalData->exception = createNotAFunctionError(ARG_callFrame, funcVal, ARG_instr4, ARG_callFrame->codeBlock()); + CallFrame* callFrame = ARG_callFrame; + CodeBlock* codeBlock = callFrame->codeBlock(); + unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS); + ARG_globalData->exception = createNotAFunctionError(ARG_callFrame, funcVal, vPCIndex, codeBlock); VM_THROW_EXCEPTION(); } -void Machine::cti_op_create_arguments(CTI_ARGS) +void Interpreter::cti_op_create_arguments(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); Arguments* arguments = new (ARG_globalData) Arguments(ARG_callFrame); ARG_callFrame->setCalleeArguments(arguments); ARG_callFrame[RegisterFile::ArgumentsRegister] = arguments; } -void Machine::cti_op_create_arguments_no_params(CTI_ARGS) +void Interpreter::cti_op_create_arguments_no_params(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); Arguments* arguments = new (ARG_globalData) Arguments(ARG_callFrame, Arguments::NoParameters); ARG_callFrame->setCalleeArguments(arguments); ARG_callFrame[RegisterFile::ArgumentsRegister] = arguments; } -void Machine::cti_op_tear_off_activation(CTI_ARGS) +void Interpreter::cti_op_tear_off_activation(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); - ASSERT(ARG_callFrame->codeBlock()->needsFullScopeChain); + ASSERT(ARG_callFrame->codeBlock()->needsFullScopeChain()); asActivation(ARG_src1)->copyRegisters(ARG_callFrame->optionalCalleeArguments()); } -void Machine::cti_op_tear_off_arguments(CTI_ARGS) +void Interpreter::cti_op_tear_off_arguments(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); - ASSERT(ARG_callFrame->codeBlock()->usesArguments && !ARG_callFrame->codeBlock()->needsFullScopeChain); + ASSERT(ARG_callFrame->codeBlock()->usesArguments() && !ARG_callFrame->codeBlock()->needsFullScopeChain()); ARG_callFrame->optionalCalleeArguments()->copyRegisters(); } -void Machine::cti_op_profile_will_call(CTI_ARGS) +void Interpreter::cti_op_profile_will_call(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); ASSERT(*ARG_profilerReference); (*ARG_profilerReference)->willExecute(ARG_callFrame, ARG_src1); } -void Machine::cti_op_profile_did_call(CTI_ARGS) +void Interpreter::cti_op_profile_did_call(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); ASSERT(*ARG_profilerReference); (*ARG_profilerReference)->didExecute(ARG_callFrame, ARG_src1); } -void Machine::cti_op_ret_scopeChain(CTI_ARGS) +void Interpreter::cti_op_ret_scopeChain(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); - ASSERT(ARG_callFrame->codeBlock()->needsFullScopeChain); + ASSERT(ARG_callFrame->codeBlock()->needsFullScopeChain()); ARG_callFrame->scopeChain()->deref(); } -JSObject* Machine::cti_op_new_array(CTI_ARGS) +JSObject* Interpreter::cti_op_new_array(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); - ArgList argList(ARG_registers1, ARG_int2); + ArgList argList(&ARG_callFrame->registers()[ARG_int1], ARG_int2); return constructArray(ARG_callFrame, argList); } -JSValue* Machine::cti_op_resolve(CTI_ARGS) +JSValueEncodedAsPointer* Interpreter::cti_op_resolve(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); CallFrame* callFrame = ARG_callFrame; ScopeChainNode* scopeChain = callFrame->scopeChain(); @@ -4914,167 +4987,140 @@ JSValue* Machine::cti_op_resolve(CTI_ARGS) JSObject* o = *iter; PropertySlot slot(o); if (o->getPropertySlot(callFrame, ident, slot)) { - JSValue* result = slot.getValue(callFrame, ident); - VM_CHECK_EXCEPTION_AT_END(); - return result; + JSValuePtr result = slot.getValue(callFrame, ident); + CHECK_FOR_EXCEPTION_AT_END(); + return JSValuePtr::encode(result); } } while (++iter != end); CodeBlock* codeBlock = callFrame->codeBlock(); - ASSERT(codeBlock->ctiReturnAddressVPCMap.contains(CTI_RETURN_ADDRESS)); - unsigned vPCIndex = codeBlock->ctiReturnAddressVPCMap.get(CTI_RETURN_ADDRESS); - ARG_globalData->exception = createUndefinedVariableError(callFrame, ident, codeBlock->instructions.begin() + vPCIndex, codeBlock); + unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS); + ARG_globalData->exception = createUndefinedVariableError(callFrame, ident, vPCIndex, codeBlock); VM_THROW_EXCEPTION(); } -JSObject* Machine::cti_op_construct_JSConstructFast(CTI_ARGS) +JSObject* Interpreter::cti_op_construct_JSConstruct(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); #ifndef NDEBUG ConstructData constructData; ASSERT(asFunction(ARG_src1)->getConstructData(constructData) == ConstructTypeJS); #endif - StructureID* structure; - if (ARG_src2->isObject()) - structure = asObject(ARG_src2)->inheritorID(); + Structure* structure; + if (ARG_src4.isObject()) + structure = asObject(ARG_src4)->inheritorID(); else structure = asFunction(ARG_src1)->m_scopeChain.node()->globalObject()->emptyObjectStructure(); return new (ARG_globalData) JSObject(structure); } -VoidPtrPair Machine::cti_op_construct_JSConstruct(CTI_ARGS) +JSValueEncodedAsPointer* Interpreter::cti_op_construct_NotJSConstruct(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); CallFrame* callFrame = ARG_callFrame; - JSFunction* constructor = asFunction(ARG_src1); - int registerOffset = ARG_int2; + JSValuePtr constrVal = ARG_src1; int argCount = ARG_int3; - JSValue* constrProtoVal = ARG_src5; - int firstArg = ARG_int6; + int thisRegister = ARG_int5; -#ifndef NDEBUG ConstructData constructData; - ASSERT(constructor->getConstructData(constructData) == ConstructTypeJS); -#endif - - ScopeChainNode* callDataScopeChain = constructor->m_scopeChain.node(); - FunctionBodyNode* functionBodyNode = constructor->m_body.get(); - CodeBlock* newCodeBlock = &functionBodyNode->byteCode(callDataScopeChain); - - StructureID* structure; - if (constrProtoVal->isObject()) - structure = asObject(constrProtoVal)->inheritorID(); - else - structure = callDataScopeChain->globalObject()->emptyObjectStructure(); - JSObject* newObject = new (ARG_globalData) JSObject(structure); - callFrame[firstArg] = newObject; // "this" value - - if (LIKELY(argCount == newCodeBlock->numParameters)) { - VoidPtrPairValue pair = {{ newCodeBlock, CallFrame::create(callFrame->registers() + registerOffset) }}; - return pair.i; - } - - if (argCount > newCodeBlock->numParameters) { - size_t numParameters = newCodeBlock->numParameters; - Register* r = callFrame->registers() + registerOffset + numParameters; - - Register* argv = r - RegisterFile::CallFrameHeaderSize - numParameters - argCount; - for (size_t i = 0; i < numParameters; ++i) - argv[i + argCount] = argv[i]; - - VoidPtrPairValue pair = {{ newCodeBlock, CallFrame::create(r) }}; - return pair.i; - } - - size_t omittedArgCount = newCodeBlock->numParameters - argCount; - Register* r = callFrame->registers() + registerOffset + omittedArgCount; - Register* newEnd = r + newCodeBlock->numCalleeRegisters; - if (!ARG_registerFile->grow(newEnd)) { - ARG_globalData->exception = createStackOverflowError(callFrame); - VM_THROW_EXCEPTION_2(); - } - - Register* argv = r - RegisterFile::CallFrameHeaderSize - omittedArgCount; - for (size_t i = 0; i < omittedArgCount; ++i) - argv[i] = jsUndefined(); - - VoidPtrPairValue pair = {{ newCodeBlock, CallFrame::create(r) }}; - return pair.i; -} - -JSValue* Machine::cti_op_construct_NotJSConstruct(CTI_ARGS) -{ - CTI_STACK_HACK(); - - CallFrame* callFrame = ARG_callFrame; - - JSValue* constrVal = ARG_src1; - int argCount = ARG_int3; - int firstArg = ARG_int6; - - ConstructData constructData; - ConstructType constructType = constrVal->getConstructData(constructData); + ConstructType constructType = constrVal.getConstructData(constructData); if (constructType == ConstructTypeHost) { - ArgList argList(callFrame->registers() + firstArg + 1, argCount - 1); + ArgList argList(callFrame->registers() + thisRegister + 1, argCount - 1); - JSValue* returnValue; + JSValuePtr returnValue; { SamplingTool::HostCallRecord callRecord(CTI_SAMPLER); returnValue = constructData.native.function(callFrame, asObject(constrVal), argList); } - VM_CHECK_EXCEPTION(); + CHECK_FOR_EXCEPTION(); - return returnValue; + return JSValuePtr::encode(returnValue); } ASSERT(constructType == ConstructTypeNone); - ARG_globalData->exception = createNotAConstructorError(callFrame, constrVal, ARG_instr4, callFrame->codeBlock()); + CodeBlock* codeBlock = callFrame->codeBlock(); + unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS); + ARG_globalData->exception = createNotAConstructorError(callFrame, constrVal, vPCIndex, codeBlock); VM_THROW_EXCEPTION(); } -JSValue* Machine::cti_op_get_by_val(CTI_ARGS) +JSValueEncodedAsPointer* Interpreter::cti_op_get_by_val(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); CallFrame* callFrame = ARG_callFrame; - Machine* machine = ARG_globalData->machine; + Interpreter* interpreter = ARG_globalData->interpreter; - JSValue* baseValue = ARG_src1; - JSValue* subscript = ARG_src2; + JSValuePtr baseValue = ARG_src1; + JSValuePtr subscript = ARG_src2; - JSValue* result; - unsigned i; + JSValuePtr result; - bool isUInt32 = JSImmediate::getUInt32(subscript, i); - if (LIKELY(isUInt32)) { - if (machine->isJSArray(baseValue)) { + if (LIKELY(subscript.isUInt32Fast())) { + uint32_t i = subscript.getUInt32Fast(); + if (interpreter->isJSArray(baseValue)) { JSArray* jsArray = asArray(baseValue); if (jsArray->canGetIndex(i)) result = jsArray->getIndex(i); else result = jsArray->JSArray::get(callFrame, i); - } else if (machine->isJSString(baseValue) && asString(baseValue)->canGetIndex(i)) + } else if (interpreter->isJSString(baseValue) && asString(baseValue)->canGetIndex(i)) result = asString(baseValue)->getIndex(ARG_globalData, i); - else - result = baseValue->get(callFrame, i); + else if (interpreter->isJSByteArray(baseValue) && asByteArray(baseValue)->canAccessIndex(i)) { + // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks. + ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_get_by_val_byte_array)); + return JSValuePtr::encode(asByteArray(baseValue)->getIndex(callFrame, i)); + } else + result = baseValue.get(callFrame, i); } else { - Identifier property(callFrame, subscript->toString(callFrame)); - result = baseValue->get(callFrame, property); + Identifier property(callFrame, subscript.toString(callFrame)); + result = baseValue.get(callFrame, property); } - VM_CHECK_EXCEPTION_AT_END(); - return result; + CHECK_FOR_EXCEPTION_AT_END(); + return JSValuePtr::encode(result); } -VoidPtrPair Machine::cti_op_resolve_func(CTI_ARGS) +JSValueEncodedAsPointer* Interpreter::cti_op_get_by_val_byte_array(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); + + CallFrame* callFrame = ARG_callFrame; + Interpreter* interpreter = ARG_globalData->interpreter; + + JSValuePtr baseValue = ARG_src1; + JSValuePtr subscript = ARG_src2; + + JSValuePtr result; + + if (LIKELY(subscript.isUInt32Fast())) { + uint32_t i = subscript.getUInt32Fast(); + if (interpreter->isJSByteArray(baseValue) && asByteArray(baseValue)->canAccessIndex(i)) { + // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks. + return JSValuePtr::encode(asByteArray(baseValue)->getIndex(callFrame, i)); + } + + result = baseValue.get(callFrame, i); + if (!interpreter->isJSByteArray(baseValue)) + ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_get_by_val)); + } else { + Identifier property(callFrame, subscript.toString(callFrame)); + result = baseValue.get(callFrame, property); + } + + CHECK_FOR_EXCEPTION_AT_END(); + return JSValuePtr::encode(result); +} + +VoidPtrPair Interpreter::cti_op_resolve_func(STUB_ARGS) +{ + BEGIN_STUB_FUNCTION(); CallFrame* callFrame = ARG_callFrame; ScopeChainNode* scopeChain = callFrame->scopeChain(); @@ -5100,149 +5146,206 @@ VoidPtrPair Machine::cti_op_resolve_func(CTI_ARGS) // that in host objects you always get a valid object for this. // We also handle wrapper substitution for the global object at the same time. JSObject* thisObj = base->toThisObject(callFrame); - JSValue* result = slot.getValue(callFrame, ident); - VM_CHECK_EXCEPTION_AT_END(); + JSValuePtr result = slot.getValue(callFrame, ident); + CHECK_FOR_EXCEPTION_AT_END(); - VoidPtrPairValue pair = {{ thisObj, asPointer(result) }}; - return pair.i; + RETURN_PAIR(thisObj, JSValuePtr::encode(result)); } ++iter; } while (iter != end); CodeBlock* codeBlock = callFrame->codeBlock(); - ASSERT(codeBlock->ctiReturnAddressVPCMap.contains(CTI_RETURN_ADDRESS)); - unsigned vPCIndex = codeBlock->ctiReturnAddressVPCMap.get(CTI_RETURN_ADDRESS); - ARG_globalData->exception = createUndefinedVariableError(callFrame, ident, codeBlock->instructions.begin() + vPCIndex, codeBlock); + unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS); + ARG_globalData->exception = createUndefinedVariableError(callFrame, ident, vPCIndex, codeBlock); VM_THROW_EXCEPTION_2(); } -JSValue* Machine::cti_op_sub(CTI_ARGS) +JSValueEncodedAsPointer* Interpreter::cti_op_sub(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); - JSValue* src1 = ARG_src1; - JSValue* src2 = ARG_src2; + JSValuePtr src1 = ARG_src1; + JSValuePtr src2 = ARG_src2; double left; double right; - if (fastIsNumber(src1, left) && fastIsNumber(src2, right)) - return jsNumber(ARG_globalData, left - right); + if (src1.getNumber(left) && src2.getNumber(right)) + return JSValuePtr::encode(jsNumber(ARG_globalData, left - right)); CallFrame* callFrame = ARG_callFrame; - JSValue* result = jsNumber(ARG_globalData, src1->toNumber(callFrame) - src2->toNumber(callFrame)); - VM_CHECK_EXCEPTION_AT_END(); - return result; + JSValuePtr result = jsNumber(ARG_globalData, src1.toNumber(callFrame) - src2.toNumber(callFrame)); + CHECK_FOR_EXCEPTION_AT_END(); + return JSValuePtr::encode(result); } -void Machine::cti_op_put_by_val(CTI_ARGS) +void Interpreter::cti_op_put_by_val(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); CallFrame* callFrame = ARG_callFrame; - Machine* machine = ARG_globalData->machine; - - JSValue* baseValue = ARG_src1; - JSValue* subscript = ARG_src2; - JSValue* value = ARG_src3; + Interpreter* interpreter = ARG_globalData->interpreter; - unsigned i; + JSValuePtr baseValue = ARG_src1; + JSValuePtr subscript = ARG_src2; + JSValuePtr value = ARG_src3; - bool isUInt32 = JSImmediate::getUInt32(subscript, i); - if (LIKELY(isUInt32)) { - if (machine->isJSArray(baseValue)) { + if (LIKELY(subscript.isUInt32Fast())) { + uint32_t i = subscript.getUInt32Fast(); + if (interpreter->isJSArray(baseValue)) { JSArray* jsArray = asArray(baseValue); if (jsArray->canSetIndex(i)) jsArray->setIndex(i, value); else jsArray->JSArray::put(callFrame, i, value); + } else if (interpreter->isJSByteArray(baseValue) && asByteArray(baseValue)->canAccessIndex(i)) { + JSByteArray* jsByteArray = asByteArray(baseValue); + ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, reinterpret_cast<void*>(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.isInt32Fast()) { + jsByteArray->setIndex(i, value.getInt32Fast()); + return; + } else { + double dValue = 0; + if (value.getNumber(dValue)) { + jsByteArray->setIndex(i, dValue); + return; + } + } + + baseValue.put(callFrame, i, value); } else - baseValue->put(callFrame, i, value); + baseValue.put(callFrame, i, value); } else { - Identifier property(callFrame, subscript->toString(callFrame)); + Identifier property(callFrame, subscript.toString(callFrame)); if (!ARG_globalData->exception) { // Don't put to an object if toString threw an exception. PutPropertySlot slot; - baseValue->put(callFrame, property, value, slot); + baseValue.put(callFrame, property, value, slot); } } - VM_CHECK_EXCEPTION_AT_END(); + CHECK_FOR_EXCEPTION_AT_END(); } -void Machine::cti_op_put_by_val_array(CTI_ARGS) +void Interpreter::cti_op_put_by_val_array(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); CallFrame* callFrame = ARG_callFrame; - JSValue* baseValue = ARG_src1; + JSValuePtr baseValue = ARG_src1; int i = ARG_int2; - JSValue* value = ARG_src3; + JSValuePtr value = ARG_src3; - ASSERT(ARG_globalData->machine->isJSArray(baseValue)); + ASSERT(ARG_globalData->interpreter->isJSArray(baseValue)); if (LIKELY(i >= 0)) asArray(baseValue)->JSArray::put(callFrame, i, value); else { - Identifier property(callFrame, JSImmediate::from(i)->toString(callFrame)); + // This should work since we're re-boxing an immediate unboxed in JIT code. + ASSERT(JSValuePtr::makeInt32Fast(i)); + Identifier property(callFrame, JSValuePtr::makeInt32Fast(i).toString(callFrame)); // FIXME: can toString throw an exception here? if (!ARG_globalData->exception) { // Don't put to an object if toString threw an exception. PutPropertySlot slot; - baseValue->put(callFrame, property, value, slot); + baseValue.put(callFrame, property, value, slot); } } - VM_CHECK_EXCEPTION_AT_END(); + CHECK_FOR_EXCEPTION_AT_END(); } -JSValue* Machine::cti_op_lesseq(CTI_ARGS) +void Interpreter::cti_op_put_by_val_byte_array(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); + + CallFrame* callFrame = ARG_callFrame; + Interpreter* interpreter = ARG_globalData->interpreter; + + JSValuePtr baseValue = ARG_src1; + JSValuePtr subscript = ARG_src2; + JSValuePtr value = ARG_src3; + + if (LIKELY(subscript.isUInt32Fast())) { + uint32_t i = subscript.getUInt32Fast(); + if (interpreter->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.isInt32Fast()) { + jsByteArray->setIndex(i, value.getInt32Fast()); + return; + } else { + double dValue = 0; + if (value.getNumber(dValue)) { + jsByteArray->setIndex(i, dValue); + return; + } + } + } + + if (!interpreter->isJSByteArray(baseValue)) + ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_put_by_val)); + baseValue.put(callFrame, i, value); + } else { + Identifier property(callFrame, subscript.toString(callFrame)); + if (!ARG_globalData->exception) { // Don't put to an object if toString threw an exception. + PutPropertySlot slot; + baseValue.put(callFrame, property, value, slot); + } + } + + CHECK_FOR_EXCEPTION_AT_END(); +} + +JSValueEncodedAsPointer* Interpreter::cti_op_lesseq(STUB_ARGS) +{ + BEGIN_STUB_FUNCTION(); CallFrame* callFrame = ARG_callFrame; - JSValue* result = jsBoolean(jsLessEq(callFrame, ARG_src1, ARG_src2)); - VM_CHECK_EXCEPTION_AT_END(); - return result; + JSValuePtr result = jsBoolean(jsLessEq(callFrame, ARG_src1, ARG_src2)); + CHECK_FOR_EXCEPTION_AT_END(); + return JSValuePtr::encode(result); } -int Machine::cti_op_loop_if_true(CTI_ARGS) +int Interpreter::cti_op_loop_if_true(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); - JSValue* src1 = ARG_src1; + JSValuePtr src1 = ARG_src1; CallFrame* callFrame = ARG_callFrame; - bool result = src1->toBoolean(callFrame); - VM_CHECK_EXCEPTION_AT_END(); + bool result = src1.toBoolean(callFrame); + CHECK_FOR_EXCEPTION_AT_END(); return result; } -JSValue* Machine::cti_op_negate(CTI_ARGS) +JSValueEncodedAsPointer* Interpreter::cti_op_negate(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); - JSValue* src = ARG_src1; + JSValuePtr src = ARG_src1; double v; - if (fastIsNumber(src, v)) - return jsNumber(ARG_globalData, -v); + if (src.getNumber(v)) + return JSValuePtr::encode(jsNumber(ARG_globalData, -v)); CallFrame* callFrame = ARG_callFrame; - JSValue* result = jsNumber(ARG_globalData, -src->toNumber(callFrame)); - VM_CHECK_EXCEPTION_AT_END(); - return result; + JSValuePtr result = jsNumber(ARG_globalData, -src.toNumber(callFrame)); + CHECK_FOR_EXCEPTION_AT_END(); + return JSValuePtr::encode(result); } -JSValue* Machine::cti_op_resolve_base(CTI_ARGS) +JSValueEncodedAsPointer* Interpreter::cti_op_resolve_base(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); - return inlineResolveBase(ARG_callFrame, *ARG_id1, ARG_callFrame->scopeChain()); + return JSValuePtr::encode(inlineResolveBase(ARG_callFrame, *ARG_id1, ARG_callFrame->scopeChain())); } -JSValue* Machine::cti_op_resolve_skip(CTI_ARGS) +JSValueEncodedAsPointer* Interpreter::cti_op_resolve_skip(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); CallFrame* callFrame = ARG_callFrame; ScopeChainNode* scopeChain = callFrame->scopeChain(); @@ -5261,225 +5364,225 @@ JSValue* Machine::cti_op_resolve_skip(CTI_ARGS) JSObject* o = *iter; PropertySlot slot(o); if (o->getPropertySlot(callFrame, ident, slot)) { - JSValue* result = slot.getValue(callFrame, ident); - VM_CHECK_EXCEPTION_AT_END(); - return result; + JSValuePtr result = slot.getValue(callFrame, ident); + CHECK_FOR_EXCEPTION_AT_END(); + return JSValuePtr::encode(result); } } while (++iter != end); CodeBlock* codeBlock = callFrame->codeBlock(); - ASSERT(codeBlock->ctiReturnAddressVPCMap.contains(CTI_RETURN_ADDRESS)); - unsigned vPCIndex = codeBlock->ctiReturnAddressVPCMap.get(CTI_RETURN_ADDRESS); - ARG_globalData->exception = createUndefinedVariableError(callFrame, ident, codeBlock->instructions.begin() + vPCIndex, codeBlock); + unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS); + ARG_globalData->exception = createUndefinedVariableError(callFrame, ident, vPCIndex, codeBlock); VM_THROW_EXCEPTION(); } -JSValue* Machine::cti_op_resolve_global(CTI_ARGS) +JSValueEncodedAsPointer* Interpreter::cti_op_resolve_global(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); CallFrame* callFrame = ARG_callFrame; JSGlobalObject* globalObject = asGlobalObject(ARG_src1); Identifier& ident = *ARG_id2; - Instruction* vPC = ARG_instr3; + unsigned globalResolveInfoIndex = ARG_int3; ASSERT(globalObject->isGlobalObject()); PropertySlot slot(globalObject); if (globalObject->getPropertySlot(callFrame, ident, slot)) { - JSValue* result = slot.getValue(callFrame, ident); - if (slot.isCacheable()) { - if (vPC[4].u.structureID) - vPC[4].u.structureID->deref(); - globalObject->structureID()->ref(); - vPC[4] = globalObject->structureID(); - vPC[5] = slot.cachedOffset(); - return result; + JSValuePtr result = slot.getValue(callFrame, ident); + if (slot.isCacheable() && !globalObject->structure()->isDictionary()) { + GlobalResolveInfo& globalResolveInfo = callFrame->codeBlock()->globalResolveInfo(globalResolveInfoIndex); + if (globalResolveInfo.structure) + globalResolveInfo.structure->deref(); + globalObject->structure()->ref(); + globalResolveInfo.structure = globalObject->structure(); + globalResolveInfo.offset = slot.cachedOffset(); + return JSValuePtr::encode(result); } - VM_CHECK_EXCEPTION_AT_END(); - return result; + CHECK_FOR_EXCEPTION_AT_END(); + return JSValuePtr::encode(result); } - - ARG_globalData->exception = createUndefinedVariableError(callFrame, ident, vPC, callFrame->codeBlock()); + + unsigned vPCIndex = callFrame->codeBlock()->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS); + ARG_globalData->exception = createUndefinedVariableError(callFrame, ident, vPCIndex, callFrame->codeBlock()); VM_THROW_EXCEPTION(); } -JSValue* Machine::cti_op_div(CTI_ARGS) +JSValueEncodedAsPointer* Interpreter::cti_op_div(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); - JSValue* src1 = ARG_src1; - JSValue* src2 = ARG_src2; + JSValuePtr src1 = ARG_src1; + JSValuePtr src2 = ARG_src2; double left; double right; - if (fastIsNumber(src1, left) && fastIsNumber(src2, right)) - return jsNumber(ARG_globalData, left / right); + if (src1.getNumber(left) && src2.getNumber(right)) + return JSValuePtr::encode(jsNumber(ARG_globalData, left / right)); CallFrame* callFrame = ARG_callFrame; - JSValue* result = jsNumber(ARG_globalData, src1->toNumber(callFrame) / src2->toNumber(callFrame)); - VM_CHECK_EXCEPTION_AT_END(); - return result; + JSValuePtr result = jsNumber(ARG_globalData, src1.toNumber(callFrame) / src2.toNumber(callFrame)); + CHECK_FOR_EXCEPTION_AT_END(); + return JSValuePtr::encode(result); } -JSValue* Machine::cti_op_pre_dec(CTI_ARGS) +JSValueEncodedAsPointer* Interpreter::cti_op_pre_dec(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); - JSValue* v = ARG_src1; + JSValuePtr v = ARG_src1; CallFrame* callFrame = ARG_callFrame; - JSValue* result = jsNumber(ARG_globalData, v->toNumber(callFrame) - 1); - VM_CHECK_EXCEPTION_AT_END(); - return result; + JSValuePtr result = jsNumber(ARG_globalData, v.toNumber(callFrame) - 1); + CHECK_FOR_EXCEPTION_AT_END(); + return JSValuePtr::encode(result); } -int Machine::cti_op_jless(CTI_ARGS) +int Interpreter::cti_op_jless(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); - JSValue* src1 = ARG_src1; - JSValue* src2 = ARG_src2; + JSValuePtr src1 = ARG_src1; + JSValuePtr src2 = ARG_src2; CallFrame* callFrame = ARG_callFrame; bool result = jsLess(callFrame, src1, src2); - VM_CHECK_EXCEPTION_AT_END(); + CHECK_FOR_EXCEPTION_AT_END(); return result; } -JSValue* Machine::cti_op_not(CTI_ARGS) +JSValueEncodedAsPointer* Interpreter::cti_op_not(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); - JSValue* src = ARG_src1; + JSValuePtr src = ARG_src1; CallFrame* callFrame = ARG_callFrame; - JSValue* result = jsBoolean(!src->toBoolean(callFrame)); - VM_CHECK_EXCEPTION_AT_END(); - return result; + JSValuePtr result = jsBoolean(!src.toBoolean(callFrame)); + CHECK_FOR_EXCEPTION_AT_END(); + return JSValuePtr::encode(result); } -int SFX_CALL Machine::cti_op_jtrue(CTI_ARGS) +int Interpreter::cti_op_jtrue(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); - JSValue* src1 = ARG_src1; + JSValuePtr src1 = ARG_src1; CallFrame* callFrame = ARG_callFrame; - bool result = src1->toBoolean(callFrame); - VM_CHECK_EXCEPTION_AT_END(); + bool result = src1.toBoolean(callFrame); + CHECK_FOR_EXCEPTION_AT_END(); return result; } -VoidPtrPair Machine::cti_op_post_inc(CTI_ARGS) +VoidPtrPair Interpreter::cti_op_post_inc(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); - JSValue* v = ARG_src1; + JSValuePtr v = ARG_src1; CallFrame* callFrame = ARG_callFrame; - JSValue* number = v->toJSNumber(callFrame); - VM_CHECK_EXCEPTION_AT_END(); + JSValuePtr number = v.toJSNumber(callFrame); + CHECK_FOR_EXCEPTION_AT_END(); - VoidPtrPairValue pair = {{ asPointer(number), asPointer(jsNumber(ARG_globalData, number->uncheckedGetNumber() + 1)) }}; - return pair.i; + RETURN_PAIR(JSValuePtr::encode(number), JSValuePtr::encode(jsNumber(ARG_globalData, number.uncheckedGetNumber() + 1))); } -JSValue* Machine::cti_op_eq(CTI_ARGS) +JSValueEncodedAsPointer* Interpreter::cti_op_eq(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); - JSValue* src1 = ARG_src1; - JSValue* src2 = ARG_src2; + JSValuePtr src1 = ARG_src1; + JSValuePtr src2 = ARG_src2; CallFrame* callFrame = ARG_callFrame; - ASSERT(!JSImmediate::areBothImmediateNumbers(src1, src2)); - JSValue* result = jsBoolean(equalSlowCaseInline(callFrame, src1, src2)); - VM_CHECK_EXCEPTION_AT_END(); - return result; + ASSERT(!JSValuePtr::areBothInt32Fast(src1, src2)); + JSValuePtr result = jsBoolean(JSValuePtr::equalSlowCaseInline(callFrame, src1, src2)); + CHECK_FOR_EXCEPTION_AT_END(); + return JSValuePtr::encode(result); } -JSValue* Machine::cti_op_lshift(CTI_ARGS) +JSValueEncodedAsPointer* Interpreter::cti_op_lshift(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); - JSValue* val = ARG_src1; - JSValue* shift = ARG_src2; + JSValuePtr val = ARG_src1; + JSValuePtr shift = ARG_src2; int32_t left; uint32_t right; - if (JSImmediate::areBothImmediateNumbers(val, shift)) - return jsNumber(ARG_globalData, JSImmediate::getTruncatedInt32(val) << (JSImmediate::getTruncatedUInt32(shift) & 0x1f)); - if (fastToInt32(val, left) && fastToUInt32(shift, right)) - return jsNumber(ARG_globalData, left << (right & 0x1f)); + if (JSValuePtr::areBothInt32Fast(val, shift)) + return JSValuePtr::encode(jsNumber(ARG_globalData, val.getInt32Fast() << (shift.getInt32Fast() & 0x1f))); + if (val.numberToInt32(left) && shift.numberToUInt32(right)) + return JSValuePtr::encode(jsNumber(ARG_globalData, left << (right & 0x1f))); CallFrame* callFrame = ARG_callFrame; - JSValue* result = jsNumber(ARG_globalData, (val->toInt32(callFrame)) << (shift->toUInt32(callFrame) & 0x1f)); - VM_CHECK_EXCEPTION_AT_END(); - return result; + JSValuePtr result = jsNumber(ARG_globalData, (val.toInt32(callFrame)) << (shift.toUInt32(callFrame) & 0x1f)); + CHECK_FOR_EXCEPTION_AT_END(); + return JSValuePtr::encode(result); } -JSValue* Machine::cti_op_bitand(CTI_ARGS) +JSValueEncodedAsPointer* Interpreter::cti_op_bitand(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); - JSValue* src1 = ARG_src1; - JSValue* src2 = ARG_src2; + JSValuePtr src1 = ARG_src1; + JSValuePtr src2 = ARG_src2; int32_t left; int32_t right; - if (fastToInt32(src1, left) && fastToInt32(src2, right)) - return jsNumber(ARG_globalData, left & right); + if (src1.numberToInt32(left) && src2.numberToInt32(right)) + return JSValuePtr::encode(jsNumber(ARG_globalData, left & right)); CallFrame* callFrame = ARG_callFrame; - JSValue* result = jsNumber(ARG_globalData, src1->toInt32(callFrame) & src2->toInt32(callFrame)); - VM_CHECK_EXCEPTION_AT_END(); - return result; + JSValuePtr result = jsNumber(ARG_globalData, src1.toInt32(callFrame) & src2.toInt32(callFrame)); + CHECK_FOR_EXCEPTION_AT_END(); + return JSValuePtr::encode(result); } -JSValue* Machine::cti_op_rshift(CTI_ARGS) +JSValueEncodedAsPointer* Interpreter::cti_op_rshift(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); - JSValue* val = ARG_src1; - JSValue* shift = ARG_src2; + JSValuePtr val = ARG_src1; + JSValuePtr shift = ARG_src2; int32_t left; uint32_t right; - if (JSImmediate::areBothImmediateNumbers(val, shift)) - return JSImmediate::rightShiftImmediateNumbers(val, shift); - if (fastToInt32(val, left) && fastToUInt32(shift, right)) - return jsNumber(ARG_globalData, left >> (right & 0x1f)); + if (JSFastMath::canDoFastRshift(val, shift)) + return JSValuePtr::encode(JSFastMath::rightShiftImmediateNumbers(val, shift)); + if (val.numberToInt32(left) && shift.numberToUInt32(right)) + return JSValuePtr::encode(jsNumber(ARG_globalData, left >> (right & 0x1f))); CallFrame* callFrame = ARG_callFrame; - JSValue* result = jsNumber(ARG_globalData, (val->toInt32(callFrame)) >> (shift->toUInt32(callFrame) & 0x1f)); - VM_CHECK_EXCEPTION_AT_END(); - return result; + JSValuePtr result = jsNumber(ARG_globalData, (val.toInt32(callFrame)) >> (shift.toUInt32(callFrame) & 0x1f)); + CHECK_FOR_EXCEPTION_AT_END(); + return JSValuePtr::encode(result); } -JSValue* Machine::cti_op_bitnot(CTI_ARGS) +JSValueEncodedAsPointer* Interpreter::cti_op_bitnot(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); - JSValue* src = ARG_src1; + JSValuePtr src = ARG_src1; int value; - if (fastToInt32(src, value)) - return jsNumber(ARG_globalData, ~value); - + if (src.numberToInt32(value)) + return JSValuePtr::encode(jsNumber(ARG_globalData, ~value)); + CallFrame* callFrame = ARG_callFrame; - JSValue* result = jsNumber(ARG_globalData, ~src->toInt32(callFrame)); - VM_CHECK_EXCEPTION_AT_END(); - return result; + JSValuePtr result = jsNumber(ARG_globalData, ~src.toInt32(callFrame)); + CHECK_FOR_EXCEPTION_AT_END(); + return JSValuePtr::encode(result); } -VoidPtrPair Machine::cti_op_resolve_with_base(CTI_ARGS) +VoidPtrPair Interpreter::cti_op_resolve_with_base(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); CallFrame* callFrame = ARG_callFrame; ScopeChainNode* scopeChain = callFrame->scopeChain(); @@ -5497,348 +5600,337 @@ VoidPtrPair Machine::cti_op_resolve_with_base(CTI_ARGS) base = *iter; PropertySlot slot(base); if (base->getPropertySlot(callFrame, ident, slot)) { - JSValue* result = slot.getValue(callFrame, ident); - VM_CHECK_EXCEPTION_AT_END(); + JSValuePtr result = slot.getValue(callFrame, ident); + CHECK_FOR_EXCEPTION_AT_END(); - VoidPtrPairValue pair = {{ base, asPointer(result) }}; - return pair.i; + RETURN_PAIR(base, JSValuePtr::encode(result)); } ++iter; } while (iter != end); CodeBlock* codeBlock = callFrame->codeBlock(); - ASSERT(codeBlock->ctiReturnAddressVPCMap.contains(CTI_RETURN_ADDRESS)); - unsigned vPCIndex = codeBlock->ctiReturnAddressVPCMap.get(CTI_RETURN_ADDRESS); - ARG_globalData->exception = createUndefinedVariableError(callFrame, ident, codeBlock->instructions.begin() + vPCIndex, codeBlock); + unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS); + ARG_globalData->exception = createUndefinedVariableError(callFrame, ident, vPCIndex, codeBlock); VM_THROW_EXCEPTION_2(); } -JSObject* Machine::cti_op_new_func_exp(CTI_ARGS) +JSObject* Interpreter::cti_op_new_func_exp(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); return ARG_funcexp1->makeFunction(ARG_callFrame, ARG_callFrame->scopeChain()); } -JSValue* Machine::cti_op_mod(CTI_ARGS) +JSValueEncodedAsPointer* Interpreter::cti_op_mod(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); - JSValue* dividendValue = ARG_src1; - JSValue* divisorValue = ARG_src2; + JSValuePtr dividendValue = ARG_src1; + JSValuePtr divisorValue = ARG_src2; CallFrame* callFrame = ARG_callFrame; - double d = dividendValue->toNumber(callFrame); - JSValue* result = jsNumber(ARG_globalData, fmod(d, divisorValue->toNumber(callFrame))); - VM_CHECK_EXCEPTION_AT_END(); - return result; + double d = dividendValue.toNumber(callFrame); + JSValuePtr result = jsNumber(ARG_globalData, fmod(d, divisorValue.toNumber(callFrame))); + CHECK_FOR_EXCEPTION_AT_END(); + return JSValuePtr::encode(result); } -JSValue* Machine::cti_op_less(CTI_ARGS) +JSValueEncodedAsPointer* Interpreter::cti_op_less(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); CallFrame* callFrame = ARG_callFrame; - JSValue* result = jsBoolean(jsLess(callFrame, ARG_src1, ARG_src2)); - VM_CHECK_EXCEPTION_AT_END(); - return result; + JSValuePtr result = jsBoolean(jsLess(callFrame, ARG_src1, ARG_src2)); + CHECK_FOR_EXCEPTION_AT_END(); + return JSValuePtr::encode(result); } -JSValue* Machine::cti_op_neq(CTI_ARGS) +JSValueEncodedAsPointer* Interpreter::cti_op_neq(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); - JSValue* src1 = ARG_src1; - JSValue* src2 = ARG_src2; + JSValuePtr src1 = ARG_src1; + JSValuePtr src2 = ARG_src2; - ASSERT(!JSImmediate::areBothImmediateNumbers(src1, src2)); + ASSERT(!JSValuePtr::areBothInt32Fast(src1, src2)); CallFrame* callFrame = ARG_callFrame; - JSValue* result = jsBoolean(!equalSlowCaseInline(callFrame, src1, src2)); - VM_CHECK_EXCEPTION_AT_END(); - return result; + JSValuePtr result = jsBoolean(!JSValuePtr::equalSlowCaseInline(callFrame, src1, src2)); + CHECK_FOR_EXCEPTION_AT_END(); + return JSValuePtr::encode(result); } -VoidPtrPair Machine::cti_op_post_dec(CTI_ARGS) +VoidPtrPair Interpreter::cti_op_post_dec(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); - JSValue* v = ARG_src1; + JSValuePtr v = ARG_src1; CallFrame* callFrame = ARG_callFrame; - JSValue* number = v->toJSNumber(callFrame); - VM_CHECK_EXCEPTION_AT_END(); + JSValuePtr number = v.toJSNumber(callFrame); + CHECK_FOR_EXCEPTION_AT_END(); - VoidPtrPairValue pair = {{ asPointer(number), asPointer(jsNumber(ARG_globalData, number->uncheckedGetNumber() - 1)) }}; - return pair.i; + RETURN_PAIR(JSValuePtr::encode(number), JSValuePtr::encode(jsNumber(ARG_globalData, number.uncheckedGetNumber() - 1))); } -JSValue* Machine::cti_op_urshift(CTI_ARGS) +JSValueEncodedAsPointer* Interpreter::cti_op_urshift(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); - JSValue* val = ARG_src1; - JSValue* shift = ARG_src2; + JSValuePtr val = ARG_src1; + JSValuePtr shift = ARG_src2; CallFrame* callFrame = ARG_callFrame; - if (JSImmediate::areBothImmediateNumbers(val, shift) && !JSImmediate::isNegative(val)) - return JSImmediate::rightShiftImmediateNumbers(val, shift); + if (JSFastMath::canDoFastUrshift(val, shift)) + return JSValuePtr::encode(JSFastMath::rightShiftImmediateNumbers(val, shift)); else { - JSValue* result = jsNumber(ARG_globalData, (val->toUInt32(callFrame)) >> (shift->toUInt32(callFrame) & 0x1f)); - VM_CHECK_EXCEPTION_AT_END(); - return result; + JSValuePtr result = jsNumber(ARG_globalData, (val.toUInt32(callFrame)) >> (shift.toUInt32(callFrame) & 0x1f)); + CHECK_FOR_EXCEPTION_AT_END(); + return JSValuePtr::encode(result); } } -JSValue* Machine::cti_op_bitxor(CTI_ARGS) +JSValueEncodedAsPointer* Interpreter::cti_op_bitxor(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); - JSValue* src1 = ARG_src1; - JSValue* src2 = ARG_src2; + JSValuePtr src1 = ARG_src1; + JSValuePtr src2 = ARG_src2; CallFrame* callFrame = ARG_callFrame; - JSValue* result = jsNumber(ARG_globalData, src1->toInt32(callFrame) ^ src2->toInt32(callFrame)); - VM_CHECK_EXCEPTION_AT_END(); - return result; + JSValuePtr result = jsNumber(ARG_globalData, src1.toInt32(callFrame) ^ src2.toInt32(callFrame)); + CHECK_FOR_EXCEPTION_AT_END(); + return JSValuePtr::encode(result); } -JSObject* Machine::cti_op_new_regexp(CTI_ARGS) +JSObject* Interpreter::cti_op_new_regexp(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); return new (ARG_globalData) RegExpObject(ARG_callFrame->lexicalGlobalObject()->regExpStructure(), ARG_regexp1); } -JSValue* Machine::cti_op_bitor(CTI_ARGS) +JSValueEncodedAsPointer* Interpreter::cti_op_bitor(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); - JSValue* src1 = ARG_src1; - JSValue* src2 = ARG_src2; + JSValuePtr src1 = ARG_src1; + JSValuePtr src2 = ARG_src2; CallFrame* callFrame = ARG_callFrame; - JSValue* result = jsNumber(ARG_globalData, src1->toInt32(callFrame) | src2->toInt32(callFrame)); - VM_CHECK_EXCEPTION_AT_END(); - return result; + JSValuePtr result = jsNumber(ARG_globalData, src1.toInt32(callFrame) | src2.toInt32(callFrame)); + CHECK_FOR_EXCEPTION_AT_END(); + return JSValuePtr::encode(result); } -JSValue* Machine::cti_op_call_eval(CTI_ARGS) +JSValueEncodedAsPointer* Interpreter::cti_op_call_eval(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); CallFrame* callFrame = ARG_callFrame; RegisterFile* registerFile = ARG_registerFile; - CodeBlock* codeBlock = callFrame->codeBlock(); - ScopeChainNode* scopeChain = callFrame->scopeChain(); - Machine* machine = ARG_globalData->machine; + Interpreter* interpreter = ARG_globalData->interpreter; - JSValue* funcVal = ARG_src1; + JSValuePtr funcVal = ARG_src1; int registerOffset = ARG_int2; int argCount = ARG_int3; - JSValue* baseVal = ARG_src5; - if (baseVal == scopeChain->globalObject() && funcVal == scopeChain->globalObject()->evalFunction()) { - JSObject* thisObject = asObject(callFrame[codeBlock->thisRegister].jsValue(callFrame)); - JSValue* exceptionValue = noValue(); - JSValue* result = machine->callEval(callFrame, thisObject, scopeChain, registerFile, registerOffset - RegisterFile::CallFrameHeaderSize - argCount, argCount, exceptionValue); + Register* newCallFrame = callFrame->registers() + registerOffset; + Register* argv = newCallFrame - RegisterFile::CallFrameHeaderSize - argCount; + JSValuePtr thisValue = argv[0].jsValue(callFrame); + JSGlobalObject* globalObject = callFrame->scopeChain()->globalObject(); + + if (thisValue == globalObject && funcVal == globalObject->evalFunction()) { + JSValuePtr exceptionValue = noValue(); + JSValuePtr result = interpreter->callEval(callFrame, registerFile, argv, argCount, registerOffset, exceptionValue); if (UNLIKELY(exceptionValue != noValue())) { ARG_globalData->exception = exceptionValue; VM_THROW_EXCEPTION_AT_END(); } - return result; + return JSValuePtr::encode(result); } - return JSImmediate::impossibleValue(); + return JSValuePtr::encode(jsImpossibleValue()); } -JSValue* Machine::cti_op_throw(CTI_ARGS) +JSValueEncodedAsPointer* Interpreter::cti_op_throw(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); CallFrame* callFrame = ARG_callFrame; CodeBlock* codeBlock = callFrame->codeBlock(); - ASSERT(codeBlock->ctiReturnAddressVPCMap.contains(CTI_RETURN_ADDRESS)); - unsigned vPCIndex = codeBlock->ctiReturnAddressVPCMap.get(CTI_RETURN_ADDRESS); + unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS); - JSValue* exceptionValue = ARG_src1; + JSValuePtr exceptionValue = ARG_src1; ASSERT(exceptionValue); - Instruction* handlerVPC = ARG_globalData->machine->throwException(callFrame, exceptionValue, codeBlock->instructions.begin() + vPCIndex, true); + HandlerInfo* handler = ARG_globalData->interpreter->throwException(callFrame, exceptionValue, vPCIndex, true); - if (!handlerVPC) { + if (!handler) { *ARG_exception = exceptionValue; - return JSImmediate::nullImmediate(); + return JSValuePtr::encode(jsNull()); } ARG_setCallFrame(callFrame); - void* catchRoutine = callFrame->codeBlock()->nativeExceptionCodeForHandlerVPC(handlerVPC); + void* catchRoutine = handler->nativeCode; ASSERT(catchRoutine); - CTI_SET_RETURN_ADDRESS(catchRoutine); - return exceptionValue; + STUB_SET_RETURN_ADDRESS(catchRoutine); + return JSValuePtr::encode(exceptionValue); } -JSPropertyNameIterator* Machine::cti_op_get_pnames(CTI_ARGS) +JSPropertyNameIterator* Interpreter::cti_op_get_pnames(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); return JSPropertyNameIterator::create(ARG_callFrame, ARG_src1); } -JSValue* Machine::cti_op_next_pname(CTI_ARGS) +JSValueEncodedAsPointer* Interpreter::cti_op_next_pname(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); JSPropertyNameIterator* it = ARG_pni1; - JSValue* temp = it->next(ARG_callFrame); + JSValuePtr temp = it->next(ARG_callFrame); if (!temp) it->invalidate(); - return temp; + return JSValuePtr::encode(temp); } -void Machine::cti_op_push_scope(CTI_ARGS) +JSObject* Interpreter::cti_op_push_scope(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); - JSObject* o = ARG_src1->toObject(ARG_callFrame); - VM_CHECK_EXCEPTION_VOID(); + JSObject* o = ARG_src1.toObject(ARG_callFrame); + CHECK_FOR_EXCEPTION(); ARG_callFrame->setScopeChain(ARG_callFrame->scopeChain()->push(o)); + return o; } -void Machine::cti_op_pop_scope(CTI_ARGS) +void Interpreter::cti_op_pop_scope(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); ARG_callFrame->setScopeChain(ARG_callFrame->scopeChain()->pop()); } -JSValue* Machine::cti_op_typeof(CTI_ARGS) +JSValueEncodedAsPointer* Interpreter::cti_op_typeof(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); - return jsTypeStringForValue(ARG_callFrame, ARG_src1); + return JSValuePtr::encode(jsTypeStringForValue(ARG_callFrame, ARG_src1)); } -JSValue* Machine::cti_op_is_undefined(CTI_ARGS) +JSValueEncodedAsPointer* Interpreter::cti_op_is_undefined(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); - JSValue* v = ARG_src1; - return jsBoolean(JSImmediate::isImmediate(v) ? v->isUndefined() : v->asCell()->structureID()->typeInfo().masqueradesAsUndefined()); + JSValuePtr v = ARG_src1; + return JSValuePtr::encode(jsBoolean(v.isCell() ? v.asCell()->structure()->typeInfo().masqueradesAsUndefined() : v.isUndefined())); } -JSValue* Machine::cti_op_is_boolean(CTI_ARGS) +JSValueEncodedAsPointer* Interpreter::cti_op_is_boolean(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); - return jsBoolean(ARG_src1->isBoolean()); + return JSValuePtr::encode(jsBoolean(ARG_src1.isBoolean())); } -JSValue* Machine::cti_op_is_number(CTI_ARGS) +JSValueEncodedAsPointer* Interpreter::cti_op_is_number(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); - return jsBoolean(ARG_src1->isNumber()); + return JSValuePtr::encode(jsBoolean(ARG_src1.isNumber())); } -JSValue* Machine::cti_op_is_string(CTI_ARGS) +JSValueEncodedAsPointer* Interpreter::cti_op_is_string(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); - return jsBoolean(ARG_globalData->machine->isJSString(ARG_src1)); + return JSValuePtr::encode(jsBoolean(ARG_globalData->interpreter->isJSString(ARG_src1))); } -JSValue* Machine::cti_op_is_object(CTI_ARGS) +JSValueEncodedAsPointer* Interpreter::cti_op_is_object(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); - return jsBoolean(jsIsObjectType(ARG_src1)); + return JSValuePtr::encode(jsBoolean(jsIsObjectType(ARG_src1))); } -JSValue* Machine::cti_op_is_function(CTI_ARGS) +JSValueEncodedAsPointer* Interpreter::cti_op_is_function(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); - return jsBoolean(jsIsFunctionType(ARG_src1)); + return JSValuePtr::encode(jsBoolean(jsIsFunctionType(ARG_src1))); } -JSValue* Machine::cti_op_stricteq(CTI_ARGS) +JSValueEncodedAsPointer* Interpreter::cti_op_stricteq(STUB_ARGS) { - CTI_STACK_HACK(); - - JSValue* src1 = ARG_src1; - JSValue* src2 = ARG_src2; + BEGIN_STUB_FUNCTION(); - // handled inline as fast cases - ASSERT(!JSImmediate::areBothImmediate(src1, src2)); - ASSERT(!(JSImmediate::isEitherImmediate(src1, src2) & (src1 != JSImmediate::zeroImmediate()) & (src2 != JSImmediate::zeroImmediate()))); + JSValuePtr src1 = ARG_src1; + JSValuePtr src2 = ARG_src2; - return jsBoolean(strictEqualSlowCaseInline(src1, src2)); + return JSValuePtr::encode(jsBoolean(JSValuePtr::strictEqual(src1, src2))); } -JSValue* Machine::cti_op_nstricteq(CTI_ARGS) +JSValueEncodedAsPointer* Interpreter::cti_op_nstricteq(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); - JSValue* src1 = ARG_src1; - JSValue* src2 = ARG_src2; + JSValuePtr src1 = ARG_src1; + JSValuePtr src2 = ARG_src2; - // handled inline as fast cases - ASSERT(!JSImmediate::areBothImmediate(src1, src2)); - ASSERT(!(JSImmediate::isEitherImmediate(src1, src2) & (src1 != JSImmediate::zeroImmediate()) & (src2 != JSImmediate::zeroImmediate()))); - - return jsBoolean(!strictEqualSlowCaseInline(src1, src2)); + return JSValuePtr::encode(jsBoolean(!JSValuePtr::strictEqual(src1, src2))); } -JSValue* Machine::cti_op_to_jsnumber(CTI_ARGS) +JSValueEncodedAsPointer* Interpreter::cti_op_to_jsnumber(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); - JSValue* src = ARG_src1; + JSValuePtr src = ARG_src1; CallFrame* callFrame = ARG_callFrame; - JSValue* result = src->toJSNumber(callFrame); - VM_CHECK_EXCEPTION_AT_END(); - return result; + JSValuePtr result = src.toJSNumber(callFrame); + CHECK_FOR_EXCEPTION_AT_END(); + return JSValuePtr::encode(result); } -JSValue* Machine::cti_op_in(CTI_ARGS) +JSValueEncodedAsPointer* Interpreter::cti_op_in(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); CallFrame* callFrame = ARG_callFrame; - JSValue* baseVal = ARG_src2; + JSValuePtr baseVal = ARG_src2; - if (!baseVal->isObject()) { + if (!baseVal.isObject()) { CallFrame* callFrame = ARG_callFrame; CodeBlock* codeBlock = callFrame->codeBlock(); - ASSERT(codeBlock->ctiReturnAddressVPCMap.contains(CTI_RETURN_ADDRESS)); - unsigned vPCIndex = codeBlock->ctiReturnAddressVPCMap.get(CTI_RETURN_ADDRESS); - ARG_globalData->exception = createInvalidParamError(callFrame, "in", baseVal, codeBlock->instructions.begin() + vPCIndex, codeBlock); + unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS); + ARG_globalData->exception = createInvalidParamError(callFrame, "in", baseVal, vPCIndex, codeBlock); VM_THROW_EXCEPTION(); } - JSValue* propName = ARG_src1; + JSValuePtr propName = ARG_src1; JSObject* baseObj = asObject(baseVal); uint32_t i; - if (propName->getUInt32(i)) - return jsBoolean(baseObj->hasProperty(callFrame, i)); + if (propName.getUInt32(i)) + return JSValuePtr::encode(jsBoolean(baseObj->hasProperty(callFrame, i))); - Identifier property(callFrame, propName->toString(callFrame)); - VM_CHECK_EXCEPTION(); - return jsBoolean(baseObj->hasProperty(callFrame, property)); + Identifier property(callFrame, propName.toString(callFrame)); + CHECK_FOR_EXCEPTION(); + return JSValuePtr::encode(jsBoolean(baseObj->hasProperty(callFrame, property))); } -JSObject* Machine::cti_op_push_new_scope(CTI_ARGS) +JSObject* Interpreter::cti_op_push_new_scope(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); JSObject* scope = new (ARG_globalData) JSStaticScopeObject(ARG_callFrame, *ARG_id1, ARG_src2, DontDelete); @@ -5847,9 +5939,9 @@ JSObject* Machine::cti_op_push_new_scope(CTI_ARGS) return scope; } -void Machine::cti_op_jmp_scopes(CTI_ARGS) +void Interpreter::cti_op_jmp_scopes(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); unsigned count = ARG_int1; CallFrame* callFrame = ARG_callFrame; @@ -5860,139 +5952,141 @@ void Machine::cti_op_jmp_scopes(CTI_ARGS) callFrame->setScopeChain(tmp); } -void Machine::cti_op_put_by_index(CTI_ARGS) +void Interpreter::cti_op_put_by_index(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); CallFrame* callFrame = ARG_callFrame; unsigned property = ARG_int2; - ARG_src1->put(callFrame, property, ARG_src3); + ARG_src1.put(callFrame, property, ARG_src3); } -void* Machine::cti_op_switch_imm(CTI_ARGS) +void* Interpreter::cti_op_switch_imm(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); - JSValue* scrutinee = ARG_src1; + JSValuePtr scrutinee = ARG_src1; unsigned tableIndex = ARG_int2; CallFrame* callFrame = ARG_callFrame; CodeBlock* codeBlock = callFrame->codeBlock(); - if (JSImmediate::isNumber(scrutinee)) { - int32_t value = JSImmediate::getTruncatedInt32(scrutinee); - return codeBlock->immediateSwitchJumpTables[tableIndex].ctiForValue(value); + if (scrutinee.isInt32Fast()) + return codeBlock->immediateSwitchJumpTable(tableIndex).ctiForValue(scrutinee.getInt32Fast()); + else { + int32_t value; + if (scrutinee.numberToInt32(value)) + return codeBlock->immediateSwitchJumpTable(tableIndex).ctiForValue(value); + else + return codeBlock->immediateSwitchJumpTable(tableIndex).ctiDefault; } - - return codeBlock->immediateSwitchJumpTables[tableIndex].ctiDefault; } -void* Machine::cti_op_switch_char(CTI_ARGS) +void* Interpreter::cti_op_switch_char(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); - JSValue* scrutinee = ARG_src1; + JSValuePtr scrutinee = ARG_src1; unsigned tableIndex = ARG_int2; CallFrame* callFrame = ARG_callFrame; CodeBlock* codeBlock = callFrame->codeBlock(); - void* result = codeBlock->characterSwitchJumpTables[tableIndex].ctiDefault; + void* result = codeBlock->characterSwitchJumpTable(tableIndex).ctiDefault; - if (scrutinee->isString()) { + if (scrutinee.isString()) { UString::Rep* value = asString(scrutinee)->value().rep(); if (value->size() == 1) - result = codeBlock->characterSwitchJumpTables[tableIndex].ctiForValue(value->data()[0]); + result = codeBlock->characterSwitchJumpTable(tableIndex).ctiForValue(value->data()[0]); } return result; } -void* Machine::cti_op_switch_string(CTI_ARGS) +void* Interpreter::cti_op_switch_string(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); - JSValue* scrutinee = ARG_src1; + JSValuePtr scrutinee = ARG_src1; unsigned tableIndex = ARG_int2; CallFrame* callFrame = ARG_callFrame; CodeBlock* codeBlock = callFrame->codeBlock(); - void* result = codeBlock->stringSwitchJumpTables[tableIndex].ctiDefault; + void* result = codeBlock->stringSwitchJumpTable(tableIndex).ctiDefault; - if (scrutinee->isString()) { + if (scrutinee.isString()) { UString::Rep* value = asString(scrutinee)->value().rep(); - result = codeBlock->stringSwitchJumpTables[tableIndex].ctiForValue(value); + result = codeBlock->stringSwitchJumpTable(tableIndex).ctiForValue(value); } return result; } -JSValue* Machine::cti_op_del_by_val(CTI_ARGS) +JSValueEncodedAsPointer* Interpreter::cti_op_del_by_val(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); CallFrame* callFrame = ARG_callFrame; - JSValue* baseValue = ARG_src1; - JSObject* baseObj = baseValue->toObject(callFrame); // may throw + JSValuePtr baseValue = ARG_src1; + JSObject* baseObj = baseValue.toObject(callFrame); // may throw - JSValue* subscript = ARG_src2; - JSValue* result; + JSValuePtr subscript = ARG_src2; + JSValuePtr result; uint32_t i; - if (subscript->getUInt32(i)) + if (subscript.getUInt32(i)) result = jsBoolean(baseObj->deleteProperty(callFrame, i)); else { - VM_CHECK_EXCEPTION(); - Identifier property(callFrame, subscript->toString(callFrame)); - VM_CHECK_EXCEPTION(); + CHECK_FOR_EXCEPTION(); + Identifier property(callFrame, subscript.toString(callFrame)); + CHECK_FOR_EXCEPTION(); result = jsBoolean(baseObj->deleteProperty(callFrame, property)); } - VM_CHECK_EXCEPTION_AT_END(); - return result; + CHECK_FOR_EXCEPTION_AT_END(); + return JSValuePtr::encode(result); } -void Machine::cti_op_put_getter(CTI_ARGS) +void Interpreter::cti_op_put_getter(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); CallFrame* callFrame = ARG_callFrame; - ASSERT(ARG_src1->isObject()); + ASSERT(ARG_src1.isObject()); JSObject* baseObj = asObject(ARG_src1); - Identifier& ident = *ARG_id2; - ASSERT(ARG_src3->isObject()); - baseObj->defineGetter(callFrame, ident, asObject(ARG_src3)); + ASSERT(ARG_src3.isObject()); + baseObj->defineGetter(callFrame, *ARG_id2, asObject(ARG_src3)); } -void Machine::cti_op_put_setter(CTI_ARGS) +void Interpreter::cti_op_put_setter(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); CallFrame* callFrame = ARG_callFrame; - ASSERT(ARG_src1->isObject()); + ASSERT(ARG_src1.isObject()); JSObject* baseObj = asObject(ARG_src1); - Identifier& ident = *ARG_id2; - ASSERT(ARG_src3->isObject()); - baseObj->defineSetter(callFrame, ident, asObject(ARG_src3)); + ASSERT(ARG_src3.isObject()); + baseObj->defineSetter(callFrame, *ARG_id2, asObject(ARG_src3)); } -JSObject* Machine::cti_op_new_error(CTI_ARGS) +JSObject* Interpreter::cti_op_new_error(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); CallFrame* callFrame = ARG_callFrame; CodeBlock* codeBlock = callFrame->codeBlock(); unsigned type = ARG_int1; - JSValue* message = ARG_src2; - unsigned lineNumber = ARG_int3; + JSValuePtr message = ARG_src2; + unsigned bytecodeOffset = ARG_int3; - return Error::create(callFrame, static_cast<ErrorType>(type), message->toString(callFrame), lineNumber, codeBlock->ownerNode->sourceID(), codeBlock->ownerNode->sourceURL()); + unsigned lineNumber = codeBlock->lineNumberForBytecodeOffset(callFrame, bytecodeOffset); + return Error::create(callFrame, static_cast<ErrorType>(type), message.toString(callFrame), lineNumber, codeBlock->ownerNode()->sourceID(), codeBlock->ownerNode()->sourceURL()); } -void Machine::cti_op_debug(CTI_ARGS) +void Interpreter::cti_op_debug(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); CallFrame* callFrame = ARG_callFrame; @@ -6000,47 +6094,47 @@ void Machine::cti_op_debug(CTI_ARGS) int firstLine = ARG_int2; int lastLine = ARG_int3; - ARG_globalData->machine->debug(callFrame, static_cast<DebugHookID>(debugHookID), firstLine, lastLine); + ARG_globalData->interpreter->debug(callFrame, static_cast<DebugHookID>(debugHookID), firstLine, lastLine); } -JSValue* Machine::cti_vm_throw(CTI_ARGS) +JSValueEncodedAsPointer* Interpreter::cti_vm_throw(STUB_ARGS) { - CTI_STACK_HACK(); + BEGIN_STUB_FUNCTION(); CallFrame* callFrame = ARG_callFrame; CodeBlock* codeBlock = callFrame->codeBlock(); + JSGlobalData* globalData = ARG_globalData; - ASSERT(codeBlock->ctiReturnAddressVPCMap.contains(ARG_globalData->throwReturnAddress)); - unsigned vPCIndex = codeBlock->ctiReturnAddressVPCMap.get(ARG_globalData->throwReturnAddress); + unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, globalData->exceptionLocation); - JSValue* exceptionValue = ARG_globalData->exception; + JSValuePtr exceptionValue = globalData->exception; ASSERT(exceptionValue); - ARG_globalData->exception = noValue(); + globalData->exception = noValue(); - Instruction* handlerVPC = ARG_globalData->machine->throwException(callFrame, exceptionValue, codeBlock->instructions.begin() + vPCIndex, false); + HandlerInfo* handler = globalData->interpreter->throwException(callFrame, exceptionValue, vPCIndex, false); - if (!handlerVPC) { + if (!handler) { *ARG_exception = exceptionValue; - return JSImmediate::nullImmediate(); + return JSValuePtr::encode(jsNull()); } ARG_setCallFrame(callFrame); - void* catchRoutine = callFrame->codeBlock()->nativeExceptionCodeForHandlerVPC(handlerVPC); + void* catchRoutine = handler->nativeCode; ASSERT(catchRoutine); - CTI_SET_RETURN_ADDRESS(catchRoutine); - return exceptionValue; + STUB_SET_RETURN_ADDRESS(catchRoutine); + return JSValuePtr::encode(exceptionValue); } -#undef CTI_RETURN_ADDRESS -#undef CTI_SET_RETURN_ADDRESS -#undef CTI_STACK_HACK -#undef VM_CHECK_EXCEPTION -#undef VM_CHECK_EXCEPTION_AT_END -#undef VM_CHECK_EXCEPTION_VOID +#undef STUB_RETURN_ADDRESS +#undef STUB_SET_RETURN_ADDRESS +#undef BEGIN_STUB_FUNCTION +#undef CHECK_FOR_EXCEPTION +#undef CHECK_FOR_EXCEPTION_AT_END +#undef CHECK_FOR_EXCEPTION_VOID #undef VM_THROW_EXCEPTION #undef VM_THROW_EXCEPTION_2 #undef VM_THROW_EXCEPTION_AT_END -#endif // ENABLE(CTI) +#endif // ENABLE(JIT) } // namespace JSC diff --git a/JavaScriptCore/interpreter/Interpreter.h b/JavaScriptCore/interpreter/Interpreter.h new file mode 100644 index 0000000..18c2185 --- /dev/null +++ b/JavaScriptCore/interpreter/Interpreter.h @@ -0,0 +1,389 @@ +/* + * 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 Interpreter_h +#define Interpreter_h + +#include "ArgList.h" +#include "JSCell.h" +#include "JSValue.h" +#include "Opcode.h" +#include "RegisterFile.h" +#include <wtf/HashMap.h> + +#ifdef ANDROID_INSTRUMENT +#include "TimeCounter.h" +#endif + +namespace JSC { + + class CodeBlock; + class EvalNode; + class FunctionBodyNode; + class Instruction; + class InternalFunction; + class AssemblerBuffer; + class JSFunction; + class JSGlobalObject; + class ProgramNode; + class Register; + class ScopeChainNode; + class SamplingTool; + struct HandlerInfo; + +#if ENABLE(JIT) + +#if USE(JIT_STUB_ARGUMENT_VA_LIST) + #define STUB_ARGS void* args, ... + #define ARGS (reinterpret_cast<void**>(vl_args) - 1) +#else // JIT_STUB_ARGUMENT_REGISTER or JIT_STUB_ARGUMENT_STACK + #define STUB_ARGS void** args + #define ARGS (args) +#endif + +#if USE(JIT_STUB_ARGUMENT_REGISTER) + #if PLATFORM(X86_64) + #define JIT_STUB + #elif COMPILER(MSVC) + #define JIT_STUB __fastcall + #elif COMPILER(GCC) + #define JIT_STUB __attribute__ ((fastcall)) + #else + #error Need to support register calling convention in this compiler + #endif +#else // JIT_STUB_ARGUMENT_VA_LIST or JIT_STUB_ARGUMENT_STACK + #if COMPILER(MSVC) + #define JIT_STUB __cdecl + #else + #define JIT_STUB + #endif +#endif + +// The Mac compilers are fine with this, +#if PLATFORM(MAC) + struct VoidPtrPair { + void* first; + void* second; + }; +#define RETURN_PAIR(a,b) VoidPtrPair pair = { a, b }; return pair +#else + typedef uint64_t VoidPtrPair; + union VoidPtrPairValue { + struct { void* first; void* second; } s; + VoidPtrPair i; + }; +#define RETURN_PAIR(a,b) VoidPtrPairValue pair = {{ a, b }}; return pair.i +#endif + +#endif // ENABLE(JIT) + + enum DebugHookID { + WillExecuteProgram, + DidExecuteProgram, + DidEnterCallFrame, + DidReachBreakpoint, + WillLeaveCallFrame, + WillExecuteStatement + }; + + enum { MaxReentryDepth = 128 }; + + class Interpreter { + friend class JIT; + public: + Interpreter(); + ~Interpreter(); + + void initialize(JSGlobalData*); + + RegisterFile& registerFile() { return m_registerFile; } + + Opcode getOpcode(OpcodeID id) + { + #if HAVE(COMPUTED_GOTO) + return m_opcodeTable[id]; + #else + return id; + #endif + } + + OpcodeID getOpcodeID(Opcode opcode) + { + #if HAVE(COMPUTED_GOTO) + ASSERT(isOpcode(opcode)); + return m_opcodeIDTable.get(opcode); + #else + return opcode; + #endif + } + + bool isOpcode(Opcode); + + JSValuePtr execute(ProgramNode*, CallFrame*, ScopeChainNode*, JSObject* thisObj, JSValuePtr* exception); + JSValuePtr execute(FunctionBodyNode*, CallFrame*, JSFunction*, JSObject* thisObj, const ArgList& args, ScopeChainNode*, JSValuePtr* exception); + JSValuePtr execute(EvalNode* evalNode, CallFrame* exec, JSObject* thisObj, ScopeChainNode* scopeChain, JSValuePtr* exception); + + JSValuePtr retrieveArguments(CallFrame*, JSFunction*) const; + JSValuePtr retrieveCaller(CallFrame*, InternalFunction*) const; + void retrieveLastCaller(CallFrame*, int& lineNumber, intptr_t& sourceID, UString& sourceURL, JSValuePtr& function) const; + + void getArgumentsData(CallFrame*, JSFunction*&, ptrdiff_t& firstParameterIndex, Register*& argv, int& argc); + void setTimeoutTime(unsigned timeoutTime) { m_timeoutTime = timeoutTime; } + + void startTimeoutCheck() + { + if (!m_timeoutCheckCount) + resetTimeoutCheck(); +#ifdef ANDROID_INSTRUMENT + if (!m_timeoutCheckCount) + android::TimeCounter::start(android::TimeCounter::JavaScriptTimeCounter); +#endif + + ++m_timeoutCheckCount; + } + + void stopTimeoutCheck() + { + ASSERT(m_timeoutCheckCount); + --m_timeoutCheckCount; +#ifdef ANDROID_INSTRUMENT + if (!m_timeoutCheckCount) + android::TimeCounter::record(android::TimeCounter::JavaScriptTimeCounter, __FUNCTION__); +#endif + } + + inline void initTimeout() + { + ASSERT(!m_timeoutCheckCount); + resetTimeoutCheck(); + m_timeoutTime = 0; + m_timeoutCheckCount = 0; + } + + void setSampler(SamplingTool* sampler) { m_sampler = sampler; } + SamplingTool* sampler() { return m_sampler; } + +#if ENABLE(JIT) + + static int JIT_STUB cti_timeout_check(STUB_ARGS); + static void JIT_STUB cti_register_file_check(STUB_ARGS); + + static JSObject* JIT_STUB cti_op_convert_this(STUB_ARGS); + static void JIT_STUB cti_op_end(STUB_ARGS); + static JSValueEncodedAsPointer* JIT_STUB cti_op_add(STUB_ARGS); + static JSValueEncodedAsPointer* JIT_STUB cti_op_pre_inc(STUB_ARGS); + static int JIT_STUB cti_op_loop_if_less(STUB_ARGS); + static int JIT_STUB cti_op_loop_if_lesseq(STUB_ARGS); + static JSObject* JIT_STUB cti_op_new_object(STUB_ARGS); + static void JIT_STUB cti_op_put_by_id(STUB_ARGS); + static void JIT_STUB cti_op_put_by_id_second(STUB_ARGS); + static void JIT_STUB cti_op_put_by_id_generic(STUB_ARGS); + static void JIT_STUB cti_op_put_by_id_fail(STUB_ARGS); + static JSValueEncodedAsPointer* JIT_STUB cti_op_get_by_id(STUB_ARGS); + static JSValueEncodedAsPointer* JIT_STUB cti_op_get_by_id_second(STUB_ARGS); + static JSValueEncodedAsPointer* JIT_STUB cti_op_get_by_id_generic(STUB_ARGS); + static JSValueEncodedAsPointer* JIT_STUB cti_op_get_by_id_self_fail(STUB_ARGS); + static JSValueEncodedAsPointer* JIT_STUB cti_op_get_by_id_proto_list(STUB_ARGS); + static JSValueEncodedAsPointer* JIT_STUB cti_op_get_by_id_proto_list_full(STUB_ARGS); + static JSValueEncodedAsPointer* JIT_STUB cti_op_get_by_id_proto_fail(STUB_ARGS); + static JSValueEncodedAsPointer* JIT_STUB cti_op_get_by_id_array_fail(STUB_ARGS); + static JSValueEncodedAsPointer* JIT_STUB cti_op_get_by_id_string_fail(STUB_ARGS); + static JSValueEncodedAsPointer* JIT_STUB cti_op_del_by_id(STUB_ARGS); + static JSValueEncodedAsPointer* JIT_STUB cti_op_instanceof(STUB_ARGS); + static JSValueEncodedAsPointer* JIT_STUB cti_op_mul(STUB_ARGS); + static JSObject* JIT_STUB cti_op_new_func(STUB_ARGS); + static void* JIT_STUB cti_op_call_JSFunction(STUB_ARGS); + static VoidPtrPair JIT_STUB cti_op_call_arityCheck(STUB_ARGS); + static JSValueEncodedAsPointer* JIT_STUB cti_op_call_NotJSFunction(STUB_ARGS); + static void JIT_STUB cti_op_create_arguments(STUB_ARGS); + static void JIT_STUB cti_op_create_arguments_no_params(STUB_ARGS); + static void JIT_STUB cti_op_tear_off_activation(STUB_ARGS); + static void JIT_STUB cti_op_tear_off_arguments(STUB_ARGS); + static void JIT_STUB cti_op_profile_will_call(STUB_ARGS); + static void JIT_STUB cti_op_profile_did_call(STUB_ARGS); + static void JIT_STUB cti_op_ret_scopeChain(STUB_ARGS); + static JSObject* JIT_STUB cti_op_new_array(STUB_ARGS); + static JSValueEncodedAsPointer* JIT_STUB cti_op_resolve(STUB_ARGS); + static JSValueEncodedAsPointer* JIT_STUB cti_op_resolve_global(STUB_ARGS); + static JSObject* JIT_STUB cti_op_construct_JSConstruct(STUB_ARGS); + static JSValueEncodedAsPointer* JIT_STUB cti_op_construct_NotJSConstruct(STUB_ARGS); + static JSValueEncodedAsPointer* JIT_STUB cti_op_get_by_val(STUB_ARGS); + static JSValueEncodedAsPointer* JIT_STUB cti_op_get_by_val_byte_array(STUB_ARGS); + static VoidPtrPair JIT_STUB cti_op_resolve_func(STUB_ARGS); + static JSValueEncodedAsPointer* JIT_STUB cti_op_sub(STUB_ARGS); + static void JIT_STUB cti_op_put_by_val(STUB_ARGS); + static void JIT_STUB cti_op_put_by_val_array(STUB_ARGS); + static void JIT_STUB cti_op_put_by_val_byte_array(STUB_ARGS); + static JSValueEncodedAsPointer* JIT_STUB cti_op_lesseq(STUB_ARGS); + static int JIT_STUB cti_op_loop_if_true(STUB_ARGS); + static JSValueEncodedAsPointer* JIT_STUB cti_op_resolve_base(STUB_ARGS); + static JSValueEncodedAsPointer* JIT_STUB cti_op_negate(STUB_ARGS); + static JSValueEncodedAsPointer* JIT_STUB cti_op_resolve_skip(STUB_ARGS); + static JSValueEncodedAsPointer* JIT_STUB cti_op_div(STUB_ARGS); + static JSValueEncodedAsPointer* JIT_STUB cti_op_pre_dec(STUB_ARGS); + static int JIT_STUB cti_op_jless(STUB_ARGS); + static JSValueEncodedAsPointer* JIT_STUB cti_op_not(STUB_ARGS); + static int JIT_STUB cti_op_jtrue(STUB_ARGS); + static VoidPtrPair JIT_STUB cti_op_post_inc(STUB_ARGS); + static JSValueEncodedAsPointer* JIT_STUB cti_op_eq(STUB_ARGS); + static JSValueEncodedAsPointer* JIT_STUB cti_op_lshift(STUB_ARGS); + static JSValueEncodedAsPointer* JIT_STUB cti_op_bitand(STUB_ARGS); + static JSValueEncodedAsPointer* JIT_STUB cti_op_rshift(STUB_ARGS); + static JSValueEncodedAsPointer* JIT_STUB cti_op_bitnot(STUB_ARGS); + static VoidPtrPair JIT_STUB cti_op_resolve_with_base(STUB_ARGS); + static JSObject* JIT_STUB cti_op_new_func_exp(STUB_ARGS); + static JSValueEncodedAsPointer* JIT_STUB cti_op_mod(STUB_ARGS); + static JSValueEncodedAsPointer* JIT_STUB cti_op_less(STUB_ARGS); + static JSValueEncodedAsPointer* JIT_STUB cti_op_neq(STUB_ARGS); + static VoidPtrPair JIT_STUB cti_op_post_dec(STUB_ARGS); + static JSValueEncodedAsPointer* JIT_STUB cti_op_urshift(STUB_ARGS); + static JSValueEncodedAsPointer* JIT_STUB cti_op_bitxor(STUB_ARGS); + static JSObject* JIT_STUB cti_op_new_regexp(STUB_ARGS); + static JSValueEncodedAsPointer* JIT_STUB cti_op_bitor(STUB_ARGS); + static JSValueEncodedAsPointer* JIT_STUB cti_op_call_eval(STUB_ARGS); + static JSValueEncodedAsPointer* JIT_STUB cti_op_throw(STUB_ARGS); + static JSPropertyNameIterator* JIT_STUB cti_op_get_pnames(STUB_ARGS); + static JSValueEncodedAsPointer* JIT_STUB cti_op_next_pname(STUB_ARGS); + static JSObject* JIT_STUB cti_op_push_scope(STUB_ARGS); + static void JIT_STUB cti_op_pop_scope(STUB_ARGS); + static JSValueEncodedAsPointer* JIT_STUB cti_op_typeof(STUB_ARGS); + static JSValueEncodedAsPointer* JIT_STUB cti_op_is_undefined(STUB_ARGS); + static JSValueEncodedAsPointer* JIT_STUB cti_op_is_boolean(STUB_ARGS); + static JSValueEncodedAsPointer* JIT_STUB cti_op_is_number(STUB_ARGS); + static JSValueEncodedAsPointer* JIT_STUB cti_op_is_string(STUB_ARGS); + static JSValueEncodedAsPointer* JIT_STUB cti_op_is_object(STUB_ARGS); + static JSValueEncodedAsPointer* JIT_STUB cti_op_is_function(STUB_ARGS); + static JSValueEncodedAsPointer* JIT_STUB cti_op_stricteq(STUB_ARGS); + static JSValueEncodedAsPointer* JIT_STUB cti_op_nstricteq(STUB_ARGS); + static JSValueEncodedAsPointer* JIT_STUB cti_op_to_jsnumber(STUB_ARGS); + static JSValueEncodedAsPointer* JIT_STUB cti_op_in(STUB_ARGS); + static JSObject* JIT_STUB cti_op_push_new_scope(STUB_ARGS); + static void JIT_STUB cti_op_jmp_scopes(STUB_ARGS); + static void JIT_STUB cti_op_put_by_index(STUB_ARGS); + static void* JIT_STUB cti_op_switch_imm(STUB_ARGS); + static void* JIT_STUB cti_op_switch_char(STUB_ARGS); + static void* JIT_STUB cti_op_switch_string(STUB_ARGS); + static JSValueEncodedAsPointer* JIT_STUB cti_op_del_by_val(STUB_ARGS); + static void JIT_STUB cti_op_put_getter(STUB_ARGS); + static void JIT_STUB cti_op_put_setter(STUB_ARGS); + static JSObject* JIT_STUB cti_op_new_error(STUB_ARGS); + static void JIT_STUB cti_op_debug(STUB_ARGS); + + static JSValueEncodedAsPointer* JIT_STUB cti_vm_throw(STUB_ARGS); + static void* JIT_STUB cti_vm_dontLazyLinkCall(STUB_ARGS); + static void* JIT_STUB cti_vm_lazyLinkCall(STUB_ARGS); + static JSObject* JIT_STUB cti_op_push_activation(STUB_ARGS); + +#endif // ENABLE(JIT) + + // Default number of ticks before a timeout check should be done. + static const int initialTickCountThreshold = 1024; + + bool isJSArray(JSValuePtr v) { return v.isCell() && v.asCell()->vptr() == m_jsArrayVptr; } + bool isJSString(JSValuePtr v) { return v.isCell() && v.asCell()->vptr() == m_jsStringVptr; } + bool isJSByteArray(JSValuePtr v) { return v.isCell() && v.asCell()->vptr() == m_jsByteArrayVptr; } + + private: + enum ExecutionFlag { Normal, InitializeAndReturn }; + + NEVER_INLINE JSValuePtr callEval(CallFrame*, RegisterFile*, Register* argv, int argc, int registerOffset, JSValuePtr& exceptionValue); + JSValuePtr execute(EvalNode*, CallFrame*, JSObject* thisObject, int globalRegisterOffset, ScopeChainNode*, JSValuePtr* exception); + + NEVER_INLINE void debug(CallFrame*, DebugHookID, int firstLine, int lastLine); + + NEVER_INLINE bool resolve(CallFrame*, Instruction*, JSValuePtr& exceptionValue); + NEVER_INLINE bool resolveSkip(CallFrame*, Instruction*, JSValuePtr& exceptionValue); + NEVER_INLINE bool resolveGlobal(CallFrame*, Instruction*, JSValuePtr& exceptionValue); + NEVER_INLINE void resolveBase(CallFrame*, Instruction* vPC); + NEVER_INLINE bool resolveBaseAndProperty(CallFrame*, Instruction*, JSValuePtr& exceptionValue); + NEVER_INLINE ScopeChainNode* createExceptionScope(CallFrame*, const Instruction* vPC); + + NEVER_INLINE bool unwindCallFrame(CallFrame*&, JSValuePtr, unsigned& bytecodeOffset, CodeBlock*&); + NEVER_INLINE HandlerInfo* throwException(CallFrame*&, JSValuePtr&, unsigned bytecodeOffset, bool); + NEVER_INLINE bool resolveBaseAndFunc(CallFrame*, Instruction*, JSValuePtr& exceptionValue); + + static ALWAYS_INLINE CallFrame* slideRegisterWindowForCall(CodeBlock*, RegisterFile*, CallFrame*, size_t registerOffset, int argc); + + static CallFrame* findFunctionCallFrame(CallFrame*, InternalFunction*); + + JSValuePtr privateExecute(ExecutionFlag, RegisterFile*, CallFrame*, JSValuePtr* exception); + + void dumpCallFrame(CallFrame*); + void dumpRegisters(CallFrame*); + + bool checkTimeout(JSGlobalObject*); + void resetTimeoutCheck(); + + void tryCacheGetByID(CallFrame*, CodeBlock*, Instruction*, JSValuePtr baseValue, const Identifier& propertyName, const PropertySlot&); + void uncacheGetByID(CodeBlock*, Instruction* vPC); + void tryCachePutByID(CallFrame*, CodeBlock*, Instruction*, JSValuePtr baseValue, const PutPropertySlot&); + void uncachePutByID(CodeBlock*, Instruction* vPC); + + bool isCallBytecode(Opcode opcode) { return opcode == getOpcode(op_call) || opcode == getOpcode(op_construct) || opcode == getOpcode(op_call_eval); } + +#if ENABLE(JIT) + static void throwStackOverflowPreviousFrame(CallFrame**, JSGlobalData*, void*& returnAddress); + + void tryCTICacheGetByID(CallFrame*, CodeBlock*, void* returnAddress, JSValuePtr baseValue, const Identifier& propertyName, const PropertySlot&); + void tryCTICachePutByID(CallFrame*, CodeBlock*, void* returnAddress, JSValuePtr baseValue, const PutPropertySlot&); +#endif + + SamplingTool* m_sampler; + +#if ENABLE(JIT) + RefPtr<ExecutablePool> m_executablePool; + void* m_ctiArrayLengthTrampoline; + void* m_ctiStringLengthTrampoline; + void* m_ctiVirtualCallPreLink; + void* m_ctiVirtualCallLink; + void* m_ctiVirtualCall; +#endif + + int m_reentryDepth; + unsigned m_timeoutTime; + unsigned m_timeAtLastCheckTimeout; + unsigned m_timeExecuting; + unsigned m_timeoutCheckCount; + unsigned m_ticksUntilNextTimeoutCheck; + + RegisterFile m_registerFile; + + void* m_jsArrayVptr; + void* m_jsByteArrayVptr; + void* m_jsStringVptr; + void* m_jsFunctionVptr; + +#if HAVE(COMPUTED_GOTO) + Opcode m_opcodeTable[numOpcodeIDs]; // Maps OpcodeID => Opcode for compiling + HashMap<Opcode, OpcodeID> m_opcodeIDTable; // Maps Opcode => OpcodeID for decompiling +#endif + }; + +} // namespace JSC + +#endif // Interpreter_h diff --git a/JavaScriptCore/VM/Register.h b/JavaScriptCore/interpreter/Register.h index c1fee3a..ff36bbc 100644 --- a/JavaScriptCore/VM/Register.h +++ b/JavaScriptCore/interpreter/Register.h @@ -49,19 +49,19 @@ namespace JSC { class Register { public: Register(); - Register(JSValue*); + Register(JSValuePtr); - JSValue* jsValue(CallFrame*) const; - JSValue* getJSValue() const; + JSValuePtr jsValue(CallFrame*) const; + JSValuePtr getJSValue() const; bool marked() const; void mark(); private: friend class ExecState; - friend class Machine; + friend class Interpreter; - // Only CallFrame and Machine should use these functions. + // Only CallFrame and Interpreter should use these functions. Register(intptr_t); @@ -89,7 +89,7 @@ namespace JSC { union { intptr_t i; void* v; - JSValue* value; + JSValueEncodedAsPointer* value; JSActivation* activation; Arguments* arguments; @@ -135,42 +135,42 @@ namespace JSC { { #ifndef NDEBUG SET_TYPE(EmptyType); - *this = noValue(); + u.value = JSValuePtr::encode(noValue()); #endif } - ALWAYS_INLINE Register::Register(JSValue* v) + ALWAYS_INLINE Register::Register(JSValuePtr v) { SET_TYPE(ValueType); - u.value = v; + u.value = JSValuePtr::encode(v); } // This function is scaffolding for legacy clients. It will eventually go away. - ALWAYS_INLINE JSValue* Register::jsValue(CallFrame*) const + ALWAYS_INLINE JSValuePtr Register::jsValue(CallFrame*) const { // Once registers hold doubles, this function will allocate a JSValue* // if the register doesn't hold one already. ASSERT_TYPE(ValueType); - return u.value; + return JSValuePtr::decode(u.value); } - ALWAYS_INLINE JSValue* Register::getJSValue() const + ALWAYS_INLINE JSValuePtr Register::getJSValue() const { ASSERT_TYPE(JSValueType); - return u.value; + return JSValuePtr::decode(u.value); } ALWAYS_INLINE bool Register::marked() const { - return getJSValue()->marked(); + return getJSValue().marked(); } ALWAYS_INLINE void Register::mark() { - getJSValue()->mark(); + getJSValue().mark(); } - // Machine functions + // Interpreter functions ALWAYS_INLINE Register::Register(Arguments* arguments) { diff --git a/JavaScriptCore/VM/RegisterFile.cpp b/JavaScriptCore/interpreter/RegisterFile.cpp index 05d717f..50698f5 100644 --- a/JavaScriptCore/VM/RegisterFile.cpp +++ b/JavaScriptCore/interpreter/RegisterFile.cpp @@ -36,8 +36,7 @@ RegisterFile::~RegisterFile() #if HAVE(MMAP) munmap(m_buffer, ((m_max - m_start) + m_maxGlobals) * sizeof(Register)); #elif HAVE(VIRTUALALLOC) - // FIXME: Use VirtualFree. - fastFree(m_buffer); + VirtualFree(m_buffer, 0, MEM_RELEASE); #else #error "Don't know how to release virtual memory on this platform." #endif diff --git a/JavaScriptCore/VM/RegisterFile.h b/JavaScriptCore/interpreter/RegisterFile.h index 0955ccb..ec190d6 100644 --- a/JavaScriptCore/VM/RegisterFile.h +++ b/JavaScriptCore/interpreter/RegisterFile.h @@ -30,11 +30,14 @@ #define RegisterFile_h #include "Register.h" -#include "collector.h" +#include "Collector.h" +#include <wtf/Noncopyable.h> + #if HAVE(MMAP) +#include <errno.h> +#include <stdio.h> #include <sys/mman.h> #endif -#include <wtf/Noncopyable.h> namespace JSC { @@ -88,7 +91,7 @@ namespace JSC { class JSGlobalObject; class RegisterFile : Noncopyable { - friend class CTI; + friend class JIT; public: enum CallFrameHeaderEntry { CallFrameHeaderSize = 8, @@ -96,7 +99,7 @@ namespace JSC { CodeBlock = -8, ScopeChain = -7, CallerFrame = -6, - ReturnPC = -5, + ReturnPC = -5, // This is either an Instruction* or a pointer into JIT generated code stored as an Instruction*. ReturnValueRegister = -4, ArgumentCount = -3, Callee = -2, @@ -108,6 +111,8 @@ namespace JSC { static const size_t defaultCapacity = 524288; static const size_t defaultMaxGlobals = 8192; + static const size_t allocationSize = 1 << 14; + static const size_t allocationSizeMask = allocationSize - 1; RegisterFile(size_t capacity = defaultCapacity, size_t maxGlobals = defaultMaxGlobals) : m_numGlobals(0) @@ -121,10 +126,25 @@ namespace JSC { size_t bufferLength = (capacity + maxGlobals) * sizeof(Register); #if HAVE(MMAP) m_buffer = static_cast<Register*>(mmap(0, bufferLength, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0)); - ASSERT(reinterpret_cast<intptr_t>(m_buffer) != -1); + if (m_buffer == MAP_FAILED) { + fprintf(stderr, "Could not allocate register file: %d\n", errno); + CRASH(); + } #elif HAVE(VIRTUALALLOC) - // FIXME: Use VirtualAlloc, and commit pages as we go. - m_buffer = static_cast<Register*>(fastMalloc(bufferLength)); + // Ensure bufferLength is a multiple of allocation size + bufferLength = (bufferLength + allocationSizeMask) & ~allocationSizeMask; + m_buffer = static_cast<Register*>(VirtualAlloc(0, bufferLength, MEM_RESERVE, PAGE_READWRITE)); + if (!m_buffer) { + fprintf(stderr, "Could not allocate register file: %d\n", errno); + CRASH(); + } + int initialAllocation = (maxGlobals * sizeof(Register) + allocationSizeMask) & ~allocationSizeMask; + void* commitCheck = VirtualAlloc(m_buffer, initialAllocation, MEM_COMMIT, PAGE_READWRITE); + if (commitCheck != m_buffer) { + fprintf(stderr, "Could not allocate register file: %d\n", errno); + CRASH(); + } + m_maxCommitted = reinterpret_cast<Register*>(reinterpret_cast<char*>(m_buffer) + initialAllocation); #else #error "Don't know how to reserve virtual memory on this platform." #endif @@ -154,7 +174,14 @@ namespace JSC { if (newEnd > m_max) return false; #if !HAVE(MMAP) && HAVE(VIRTUALALLOC) - // FIXME: Use VirtualAlloc, and commit pages as we go. + if (newEnd > m_maxCommitted) { + ptrdiff_t additionalAllocation = ((reinterpret_cast<char*>(newEnd) - reinterpret_cast<char*>(m_maxCommitted)) + allocationSizeMask) & ~allocationSizeMask; + if (!VirtualAlloc(m_maxCommitted, additionalAllocation, MEM_COMMIT, PAGE_READWRITE)) { + fprintf(stderr, "Could not allocate register file: %d\n", errno); + CRASH(); + } + m_maxCommitted = reinterpret_cast<Register*>(reinterpret_cast<char*>(m_maxCommitted) + additionalAllocation); + } #endif m_end = newEnd; } @@ -177,6 +204,10 @@ namespace JSC { Register* m_end; Register* m_max; Register* m_buffer; +#if HAVE(VIRTUALALLOC) + Register* m_maxCommitted; +#endif + JSGlobalObject* m_globalObject; // The global object whose vars are currently stored in the register file. }; diff --git a/JavaScriptCore/jit/ExecutableAllocator.cpp b/JavaScriptCore/jit/ExecutableAllocator.cpp new file mode 100644 index 0000000..f6b27ec --- /dev/null +++ b/JavaScriptCore/jit/ExecutableAllocator.cpp @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2008 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#include "ExecutableAllocator.h" + +#if ENABLE(ASSEMBLER) + +namespace JSC { + +size_t ExecutableAllocator::pageSize = 0; + +} + +#endif // HAVE(ASSEMBLER) diff --git a/JavaScriptCore/jit/ExecutableAllocator.h b/JavaScriptCore/jit/ExecutableAllocator.h new file mode 100644 index 0000000..1541256 --- /dev/null +++ b/JavaScriptCore/jit/ExecutableAllocator.h @@ -0,0 +1,179 @@ +/* + * 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 ExecutableAllocator_h +#define ExecutableAllocator_h + +#if ENABLE(ASSEMBLER) + +#include <wtf/Assertions.h> +#include <wtf/PassRefPtr.h> +#include <wtf/RefCounted.h> +#include <wtf/Vector.h> + +#include <limits> + +#define JIT_ALLOCATOR_PAGE_SIZE (ExecutableAllocator::pageSize) +#define JIT_ALLOCATOR_LARGE_ALLOC_SIZE (ExecutableAllocator::pageSize * 4) + +namespace JSC { + +class ExecutablePool : public RefCounted<ExecutablePool> { +private: + struct Allocation { + char* pages; + size_t size; + }; + typedef Vector<Allocation, 2> AllocationList; + +public: + static PassRefPtr<ExecutablePool> create(size_t n) + { + return adoptRef(new ExecutablePool(n)); + } + + void* alloc(size_t n) + { + ASSERT(m_freePtr <= m_end); + + // Round 'n' up to a multiple of word size; if all allocations are of + // word sized quantities, then all subsequent allocations will be aligned. + n = roundUpAllocationSize(n, sizeof(void*)); + + if (static_cast<ptrdiff_t>(n) < (m_end - m_freePtr)) { + void* result = m_freePtr; + m_freePtr += n; + return result; + } + + // Insufficient space to allocate in the existing pool + // so we need allocate into a new pool + return poolAllocate(n); + } + + ~ExecutablePool() + { + AllocationList::const_iterator end = m_pools.end(); + for (AllocationList::const_iterator ptr = m_pools.begin(); ptr != end; ++ptr) + ExecutablePool::systemRelease(*ptr); + } + + size_t available() const { return (m_pools.size() > 1) ? 0 : m_end - m_freePtr; } + +private: + static Allocation systemAlloc(size_t n); + static void systemRelease(const Allocation& alloc); + + inline size_t roundUpAllocationSize(size_t request, size_t granularity) + { + if ((std::numeric_limits<size_t>::max() - granularity) <= request) + CRASH(); // Allocation is too large + + // Round up to next page boundary + size_t size = request + (granularity - 1); + size = size & ~(granularity - 1); + ASSERT(size >= request); + return size; + } + + ExecutablePool(size_t n); + + void* poolAllocate(size_t n); + + char* m_freePtr; + char* m_end; + AllocationList m_pools; +}; + +class ExecutableAllocator { +public: + static size_t pageSize; + ExecutableAllocator() + { + if (!pageSize) + intializePageSize(); + m_smallAllocationPool = ExecutablePool::create(JIT_ALLOCATOR_LARGE_ALLOC_SIZE); + } + + PassRefPtr<ExecutablePool> poolForSize(size_t n) + { + // Try to fit in the existing small allocator + if (n < m_smallAllocationPool->available()) + return m_smallAllocationPool; + + // If the request is large, we just provide a unshared allocator + if (n > JIT_ALLOCATOR_LARGE_ALLOC_SIZE) + return ExecutablePool::create(n); + + // Create a new allocator + RefPtr<ExecutablePool> pool = ExecutablePool::create(JIT_ALLOCATOR_LARGE_ALLOC_SIZE); + + // If the new allocator will result in more free space than in + // the current small allocator, then we will use it instead + if ((pool->available() - n) > m_smallAllocationPool->available()) + m_smallAllocationPool = pool; + return pool.release(); + } + +private: + RefPtr<ExecutablePool> m_smallAllocationPool; + static void intializePageSize(); +}; + +inline ExecutablePool::ExecutablePool(size_t n) +{ + size_t allocSize = roundUpAllocationSize(n, JIT_ALLOCATOR_PAGE_SIZE); + Allocation mem = systemAlloc(allocSize); + m_pools.append(mem); + m_freePtr = mem.pages; + if (!m_freePtr) + CRASH(); // Failed to allocate + m_end = m_freePtr + allocSize; +} + +inline void* ExecutablePool::poolAllocate(size_t n) +{ + size_t allocSize = roundUpAllocationSize(n, JIT_ALLOCATOR_PAGE_SIZE); + + Allocation result = systemAlloc(allocSize); + if (!result.pages) + CRASH(); // Failed to allocate + + ASSERT(m_end >= m_freePtr); + if ((allocSize - n) > static_cast<size_t>(m_end - m_freePtr)) { + // Replace allocation pool + m_freePtr = result.pages + n; + m_end = result.pages + allocSize; + } + + m_pools.append(result); + return result.pages; +} + +} + +#endif // ENABLE(ASSEMBLER) + +#endif // !defined(ExecutableAllocator) diff --git a/JavaScriptCore/jit/ExecutableAllocatorPosix.cpp b/JavaScriptCore/jit/ExecutableAllocatorPosix.cpp new file mode 100644 index 0000000..21955d7 --- /dev/null +++ b/JavaScriptCore/jit/ExecutableAllocatorPosix.cpp @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2008 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#include "ExecutableAllocator.h" + +#if ENABLE(ASSEMBLER) + +#include <sys/mman.h> +#include <unistd.h> + +namespace JSC { + +void ExecutableAllocator::intializePageSize() +{ + ExecutableAllocator::pageSize = getpagesize(); +} + +ExecutablePool::Allocation ExecutablePool::systemAlloc(size_t n) +{ + ExecutablePool::Allocation alloc = {reinterpret_cast<char*>(mmap(NULL, n, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANON, -1, 0)), n}; + return alloc; +} + +void ExecutablePool::systemRelease(const ExecutablePool::Allocation& alloc) +{ + int result = munmap(alloc.pages, alloc.size); + ASSERT_UNUSED(result, !result); +} + +} + +#endif // HAVE(ASSEMBLER) diff --git a/JavaScriptCore/jit/ExecutableAllocatorWin.cpp b/JavaScriptCore/jit/ExecutableAllocatorWin.cpp new file mode 100644 index 0000000..7467f81 --- /dev/null +++ b/JavaScriptCore/jit/ExecutableAllocatorWin.cpp @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2008 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#include "ExecutableAllocator.h" + +#if ENABLE(ASSEMBLER) + +#include "windows.h" + +namespace JSC { + +void ExecutableAllocator::intializePageSize() +{ + SYSTEM_INFO system_info; + GetSystemInfo(&system_info); + ExecutableAllocator::pageSize = system_info.dwPageSize; +} + +ExecutablePool::Allocation ExecutablePool::systemAlloc(size_t n) +{ + ExecutablePool::Allocation alloc = {reinterpret_cast<char*>(VirtualAlloc(0, n, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE)), n}; + return alloc; +} + +void ExecutablePool::systemRelease(const ExecutablePool::Allocation& alloc) +{ + VirtualFree(alloc.pages, 0, MEM_RELEASE); +} + +} + +#endif // HAVE(ASSEMBLER) diff --git a/JavaScriptCore/jit/JIT.cpp b/JavaScriptCore/jit/JIT.cpp new file mode 100644 index 0000000..5640c8a --- /dev/null +++ b/JavaScriptCore/jit/JIT.cpp @@ -0,0 +1,1944 @@ +/* + * Copyright (C) 2008, 2009 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "JIT.h" + +#if ENABLE(JIT) + +#include "CodeBlock.h" +#include "JITInlineMethods.h" +#include "JSArray.h" +#include "JSFunction.h" +#include "Interpreter.h" +#include "ResultType.h" +#include "SamplingTool.h" + +#ifndef NDEBUG +#include <stdio.h> +#endif + +using namespace std; + +namespace JSC { + +#if COMPILER(GCC) && PLATFORM(X86) + +COMPILE_ASSERT(STUB_ARGS_code == 0x0C, STUB_ARGS_code_is_0x0C); +COMPILE_ASSERT(STUB_ARGS_callFrame == 0x0E, STUB_ARGS_callFrame_is_0x0E); + +#if PLATFORM(DARWIN) +#define SYMBOL_STRING(name) "_" #name +#else +#define SYMBOL_STRING(name) #name +#endif + +asm( +".globl " SYMBOL_STRING(ctiTrampoline) "\n" +SYMBOL_STRING(ctiTrampoline) ":" "\n" + "pushl %ebp" "\n" + "movl %esp, %ebp" "\n" + "pushl %esi" "\n" + "pushl %edi" "\n" + "pushl %ebx" "\n" + "subl $0x1c, %esp" "\n" + "movl $512, %esi" "\n" + "movl 0x38(%esp), %edi" "\n" // Ox38 = 0x0E * 4, 0x0E = STUB_ARGS_callFrame (see assertion above) + "call *0x30(%esp)" "\n" // Ox30 = 0x0C * 4, 0x0C = STUB_ARGS_code (see assertion above) + "addl $0x1c, %esp" "\n" + "popl %ebx" "\n" + "popl %edi" "\n" + "popl %esi" "\n" + "popl %ebp" "\n" + "ret" "\n" +); + +asm( +".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n" +SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n" +#if USE(JIT_STUB_ARGUMENT_VA_LIST) + "call " SYMBOL_STRING(_ZN3JSC11Interpreter12cti_vm_throwEPvz) "\n" +#else +#if USE(JIT_STUB_ARGUMENT_REGISTER) + "movl %esp, %ecx" "\n" +#else // JIT_STUB_ARGUMENT_STACK + "movl %esp, 0(%esp)" "\n" +#endif + "call " SYMBOL_STRING(_ZN3JSC11Interpreter12cti_vm_throwEPPv) "\n" +#endif + "addl $0x1c, %esp" "\n" + "popl %ebx" "\n" + "popl %edi" "\n" + "popl %esi" "\n" + "popl %ebp" "\n" + "ret" "\n" +); + +#elif COMPILER(GCC) && PLATFORM(X86_64) + +COMPILE_ASSERT(STUB_ARGS_code == 0x10, STUB_ARGS_code_is_0x10); +COMPILE_ASSERT(STUB_ARGS_callFrame == 0x12, STUB_ARGS_callFrame_is_0x12); + +#if PLATFORM(DARWIN) +#define SYMBOL_STRING(name) "_" #name +#else +#define SYMBOL_STRING(name) #name +#endif + +asm( +".globl " SYMBOL_STRING(ctiTrampoline) "\n" +SYMBOL_STRING(ctiTrampoline) ":" "\n" + "pushq %rbp" "\n" + "movq %rsp, %rbp" "\n" + "pushq %r12" "\n" + "pushq %r13" "\n" + "pushq %r14" "\n" + "pushq %r15" "\n" + "pushq %rbx" "\n" + "subq $0x48, %rsp" "\n" + "movq $512, %r12" "\n" + "movq $0xFFFF000000000000, %r14" "\n" + "movq $0xFFFF000000000002, %r15" "\n" + "movq 0x90(%rsp), %r13" "\n" // Ox90 = 0x12 * 8, 0x12 = STUB_ARGS_callFrame (see assertion above) + "call *0x80(%rsp)" "\n" // Ox80 = 0x10 * 8, 0x10 = STUB_ARGS_code (see assertion above) + "addq $0x48, %rsp" "\n" + "popq %rbx" "\n" + "popq %r15" "\n" + "popq %r14" "\n" + "popq %r13" "\n" + "popq %r12" "\n" + "popq %rbp" "\n" + "ret" "\n" +); + +asm( +".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n" +SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n" +#if USE(JIT_STUB_ARGUMENT_REGISTER) + "movq %rsp, %rdi" "\n" + "call " SYMBOL_STRING(_ZN3JSC11Interpreter12cti_vm_throwEPPv) "\n" +#else // JIT_STUB_ARGUMENT_VA_LIST or JIT_STUB_ARGUMENT_STACK +#error "JIT_STUB_ARGUMENT configuration not supported." +#endif + "addq $0x48, %rsp" "\n" + "popq %rbx" "\n" + "popq %r15" "\n" + "popq %r14" "\n" + "popq %r13" "\n" + "popq %r12" "\n" + "popq %rbp" "\n" + "ret" "\n" +); + +#elif COMPILER(MSVC) + +extern "C" { + + __declspec(naked) JSValueEncodedAsPointer* ctiTrampoline(void* code, RegisterFile*, CallFrame*, JSValuePtr* exception, Profiler**, JSGlobalData*) + { + __asm { + push ebp; + mov ebp, esp; + push esi; + push edi; + push ebx; + sub esp, 0x1c; + mov esi, 512; + mov ecx, esp; + mov edi, [esp + 0x38]; + call [esp + 0x30]; // Ox30 = 0x0C * 4, 0x0C = STUB_ARGS_code (see assertion above) + add esp, 0x1c; + pop ebx; + pop edi; + pop esi; + pop ebp; + ret; + } + } + + __declspec(naked) void ctiVMThrowTrampoline() + { + __asm { +#if USE(JIT_STUB_ARGUMENT_REGISTER) + mov ecx, esp; +#else // JIT_STUB_ARGUMENT_VA_LIST or JIT_STUB_ARGUMENT_STACK +#error "JIT_STUB_ARGUMENT configuration not supported." +#endif + call JSC::Interpreter::cti_vm_throw; + add esp, 0x1c; + pop ebx; + pop edi; + pop esi; + pop ebp; + ret; + } + } + +} + +#endif + +void ctiSetReturnAddress(void** where, void* what) +{ + *where = what; +} + +void ctiPatchCallByReturnAddress(void* where, void* what) +{ + MacroAssembler::Jump::patch(where, what); +} + +JIT::JIT(JSGlobalData* globalData, CodeBlock* codeBlock) + : m_interpreter(globalData->interpreter) + , m_globalData(globalData) + , m_codeBlock(codeBlock) + , m_labels(codeBlock ? codeBlock->instructions().size() : 0) + , m_propertyAccessCompilationInfo(codeBlock ? codeBlock->numberOfStructureStubInfos() : 0) + , m_callStructureStubCompilationInfo(codeBlock ? codeBlock->numberOfCallLinkInfos() : 0) + , m_lastResultBytecodeRegister(std::numeric_limits<int>::max()) + , m_jumpTargetsPosition(0) +{ +} + +void JIT::compileOpStrictEq(Instruction* currentInstruction, CompileOpStrictEqType type) +{ + unsigned dst = currentInstruction[1].u.operand; + unsigned src1 = currentInstruction[2].u.operand; + unsigned src2 = currentInstruction[3].u.operand; + + emitGetVirtualRegisters(src1, X86::eax, src2, X86::edx); + +#if USE(ALTERNATE_JSIMMEDIATE) + // Jump to a slow case if either operand is a number, or if both are JSCell*s. + move(X86::eax, X86::ecx); + orPtr(X86::edx, X86::ecx); + addSlowCase(emitJumpIfJSCell(X86::ecx)); + addSlowCase(emitJumpIfImmediateNumber(X86::ecx)); + + if (type == OpStrictEq) + sete32(X86::edx, X86::eax); + else + setne32(X86::edx, X86::eax); + emitTagAsBoolImmediate(X86::eax); +#else + bool negated = (type == OpNStrictEq); + + // Check that both are immediates, if so check if they're equal + Jump firstNotImmediate = emitJumpIfJSCell(X86::eax); + Jump secondNotImmediate = emitJumpIfJSCell(X86::edx); + Jump bothWereImmediatesButNotEqual = jnePtr(X86::edx, X86::eax); + + // They are equal - set the result to true. (Or false, if negated). + move(ImmPtr(JSValuePtr::encode(jsBoolean(!negated))), X86::eax); + Jump bothWereImmediatesAndEqual = jump(); + + // eax was not an immediate, we haven't yet checked edx. + // If edx is also a JSCell, or is 0, then jump to a slow case, + // otherwise these values are not equal. + firstNotImmediate.link(this); + emitJumpSlowCaseIfJSCell(X86::edx); + addSlowCase(jePtr(X86::edx, ImmPtr(JSValuePtr::encode(js0())))); + Jump firstWasNotImmediate = jump(); + + // eax was an immediate, but edx wasn't. + // If eax is 0 jump to a slow case, otherwise these values are not equal. + secondNotImmediate.link(this); + addSlowCase(jePtr(X86::eax, ImmPtr(JSValuePtr::encode(js0())))); + + // We get here if the two values are different immediates, or one is 0 and the other is a JSCell. + // Vaelues are not equal, set the result to false. + bothWereImmediatesButNotEqual.link(this); + firstWasNotImmediate.link(this); + move(ImmPtr(JSValuePtr::encode(jsBoolean(negated))), X86::eax); + + bothWereImmediatesAndEqual.link(this); +#endif + + emitPutVirtualRegister(dst); +} + +void JIT::emitSlowScriptCheck() +{ + Jump skipTimeout = jnzSub32(Imm32(1), timeoutCheckRegister); + emitCTICall(Interpreter::cti_timeout_check); + move(X86::eax, timeoutCheckRegister); + skipTimeout.link(this); + + killLastResultRegister(); +} + + +#define NEXT_OPCODE(name) \ + m_bytecodeIndex += OPCODE_LENGTH(name); \ + break; + +#define CTI_COMPILE_BINARY_OP(name) \ + case name: { \ + emitPutJITStubArgFromVirtualRegister(currentInstruction[2].u.operand, 1, X86::ecx); \ + emitPutJITStubArgFromVirtualRegister(currentInstruction[3].u.operand, 2, X86::ecx); \ + emitCTICall(Interpreter::cti_##name); \ + emitPutVirtualRegister(currentInstruction[1].u.operand); \ + NEXT_OPCODE(name); \ + } + +#define CTI_COMPILE_UNARY_OP(name) \ + case name: { \ + emitPutJITStubArgFromVirtualRegister(currentInstruction[2].u.operand, 1, X86::ecx); \ + emitCTICall(Interpreter::cti_##name); \ + emitPutVirtualRegister(currentInstruction[1].u.operand); \ + NEXT_OPCODE(name); \ + } + +void JIT::privateCompileMainPass() +{ + Instruction* instructionsBegin = m_codeBlock->instructions().begin(); + unsigned instructionCount = m_codeBlock->instructions().size(); + unsigned propertyAccessInstructionIndex = 0; + unsigned globalResolveInfoIndex = 0; + unsigned callLinkInfoIndex = 0; + + for (m_bytecodeIndex = 0; m_bytecodeIndex < instructionCount; ) { + Instruction* currentInstruction = instructionsBegin + m_bytecodeIndex; + ASSERT_WITH_MESSAGE(m_interpreter->isOpcode(currentInstruction->u.opcode), "privateCompileMainPass gone bad @ %d", m_bytecodeIndex); + +#if ENABLE(OPCODE_SAMPLING) + if (m_bytecodeIndex > 0) // Avoid the overhead of sampling op_enter twice. + sampleInstruction(currentInstruction); +#endif + + m_labels[m_bytecodeIndex] = label(); + OpcodeID opcodeID = m_interpreter->getOpcodeID(currentInstruction->u.opcode); + + switch (opcodeID) { + case op_mov: { + emitGetVirtualRegister(currentInstruction[2].u.operand, X86::eax); + emitPutVirtualRegister(currentInstruction[1].u.operand); + NEXT_OPCODE(op_mov); + } + case op_add: { + compileFastArith_op_add(currentInstruction); + NEXT_OPCODE(op_add); + } + case op_end: { + if (m_codeBlock->needsFullScopeChain()) + emitCTICall(Interpreter::cti_op_end); + emitGetVirtualRegister(currentInstruction[1].u.operand, X86::eax); + push(Address(callFrameRegister, RegisterFile::ReturnPC * static_cast<int>(sizeof(Register)))); + ret(); + NEXT_OPCODE(op_end); + } + case op_jmp: { + unsigned target = currentInstruction[1].u.operand; + addJump(jump(), target + 1); + NEXT_OPCODE(op_jmp); + } + case op_pre_inc: { + compileFastArith_op_pre_inc(currentInstruction[1].u.operand); + NEXT_OPCODE(op_pre_inc); + } + case op_loop: { + emitSlowScriptCheck(); + + unsigned target = currentInstruction[1].u.operand; + addJump(jump(), target + 1); + NEXT_OPCODE(op_end); + } + case op_loop_if_less: { + emitSlowScriptCheck(); + + unsigned op1 = currentInstruction[1].u.operand; + unsigned op2 = currentInstruction[2].u.operand; + unsigned target = currentInstruction[3].u.operand; + if (isOperandConstantImmediateInt(op2)) { + emitGetVirtualRegister(op1, X86::eax); + emitJumpSlowCaseIfNotImmediateInteger(X86::eax); +#if USE(ALTERNATE_JSIMMEDIATE) + int32_t op2imm = getConstantOperandImmediateInt(op2); +#else + int32_t op2imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2))); +#endif + addJump(jl32(X86::eax, Imm32(op2imm)), target + 3); + } else { + emitGetVirtualRegisters(op1, X86::eax, op2, X86::edx); + emitJumpSlowCaseIfNotImmediateInteger(X86::eax); + emitJumpSlowCaseIfNotImmediateInteger(X86::edx); + addJump(jl32(X86::eax, X86::edx), target + 3); + } + NEXT_OPCODE(op_loop_if_less); + } + case op_loop_if_lesseq: { + emitSlowScriptCheck(); + + unsigned op1 = currentInstruction[1].u.operand; + unsigned op2 = currentInstruction[2].u.operand; + unsigned target = currentInstruction[3].u.operand; + if (isOperandConstantImmediateInt(op2)) { + emitGetVirtualRegister(op1, X86::eax); + emitJumpSlowCaseIfNotImmediateInteger(X86::eax); +#if USE(ALTERNATE_JSIMMEDIATE) + int32_t op2imm = getConstantOperandImmediateInt(op2); +#else + int32_t op2imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2))); +#endif + addJump(jle32(X86::eax, Imm32(op2imm)), target + 3); + } else { + emitGetVirtualRegisters(op1, X86::eax, op2, X86::edx); + emitJumpSlowCaseIfNotImmediateInteger(X86::eax); + emitJumpSlowCaseIfNotImmediateInteger(X86::edx); + addJump(jle32(X86::eax, X86::edx), target + 3); + } + NEXT_OPCODE(op_loop_if_less); + } + case op_new_object: { + emitCTICall(Interpreter::cti_op_new_object); + emitPutVirtualRegister(currentInstruction[1].u.operand); + NEXT_OPCODE(op_new_object); + } + case op_put_by_id: { + compilePutByIdHotPath(currentInstruction[1].u.operand, &(m_codeBlock->identifier(currentInstruction[2].u.operand)), currentInstruction[3].u.operand, propertyAccessInstructionIndex++); + NEXT_OPCODE(op_put_by_id); + } + case op_get_by_id: { + compileGetByIdHotPath(currentInstruction[1].u.operand, currentInstruction[2].u.operand, &(m_codeBlock->identifier(currentInstruction[3].u.operand)), propertyAccessInstructionIndex++); + NEXT_OPCODE(op_get_by_id); + } + case op_instanceof: { + emitGetVirtualRegister(currentInstruction[2].u.operand, X86::eax); // value + emitGetVirtualRegister(currentInstruction[3].u.operand, X86::ecx); // baseVal + emitGetVirtualRegister(currentInstruction[4].u.operand, X86::edx); // proto + + // check if any are immediates + move(X86::eax, X86::ebx); + orPtr(X86::ecx, X86::ebx); + orPtr(X86::edx, X86::ebx); + emitJumpSlowCaseIfNotJSCell(X86::ebx); + + // check that all are object type - this is a bit of a bithack to avoid excess branching; + // we check that the sum of the three type codes from Structures is exactly 3 * ObjectType, + // this works because NumberType and StringType are smaller + move(Imm32(3 * ObjectType), X86::ebx); + loadPtr(Address(X86::eax, FIELD_OFFSET(JSCell, m_structure)), X86::eax); + loadPtr(Address(X86::ecx, FIELD_OFFSET(JSCell, m_structure)), X86::ecx); + loadPtr(Address(X86::edx, FIELD_OFFSET(JSCell, m_structure)), X86::edx); + sub32(Address(X86::eax, FIELD_OFFSET(Structure, m_typeInfo.m_type)), X86::ebx); + sub32(Address(X86::ecx, FIELD_OFFSET(Structure, m_typeInfo.m_type)), X86::ebx); + addSlowCase(jne32(Address(X86::edx, FIELD_OFFSET(Structure, m_typeInfo.m_type)), X86::ebx)); + + // check that baseVal's flags include ImplementsHasInstance but not OverridesHasInstance + load32(Address(X86::ecx, FIELD_OFFSET(Structure, m_typeInfo.m_flags)), X86::ecx); + and32(Imm32(ImplementsHasInstance | OverridesHasInstance), X86::ecx); + addSlowCase(jne32(X86::ecx, Imm32(ImplementsHasInstance))); + + emitGetVirtualRegister(currentInstruction[2].u.operand, X86::ecx); // reload value + emitGetVirtualRegister(currentInstruction[4].u.operand, X86::edx); // reload proto + + // optimistically load true result + move(ImmPtr(JSValuePtr::encode(jsBoolean(true))), X86::eax); + + Label loop(this); + + // load value's prototype + loadPtr(Address(X86::ecx, FIELD_OFFSET(JSCell, m_structure)), X86::ecx); + loadPtr(Address(X86::ecx, FIELD_OFFSET(Structure, m_prototype)), X86::ecx); + + Jump exit = jePtr(X86::ecx, X86::edx); + + jnePtr(X86::ecx, ImmPtr(JSValuePtr::encode(jsNull())), loop); + + move(ImmPtr(JSValuePtr::encode(jsBoolean(false))), X86::eax); + + exit.link(this); + + emitPutVirtualRegister(currentInstruction[1].u.operand); + + NEXT_OPCODE(op_instanceof); + } + case op_del_by_id: { + emitPutJITStubArgFromVirtualRegister(currentInstruction[2].u.operand, 1, X86::ecx); + Identifier* ident = &(m_codeBlock->identifier(currentInstruction[3].u.operand)); + emitPutJITStubArgConstant(ident, 2); + emitCTICall(Interpreter::cti_op_del_by_id); + emitPutVirtualRegister(currentInstruction[1].u.operand); + NEXT_OPCODE(op_del_by_id); + } + case op_mul: { + compileFastArith_op_mul(currentInstruction); + NEXT_OPCODE(op_mul); + } + case op_new_func: { + FuncDeclNode* func = m_codeBlock->function(currentInstruction[2].u.operand); + emitPutJITStubArgConstant(func, 1); + emitCTICall(Interpreter::cti_op_new_func); + emitPutVirtualRegister(currentInstruction[1].u.operand); + NEXT_OPCODE(op_new_func); + } + case op_call: { + compileOpCall(opcodeID, currentInstruction, callLinkInfoIndex++); + NEXT_OPCODE(op_call); + } + case op_call_eval: { + compileOpCall(opcodeID, currentInstruction, callLinkInfoIndex++); + NEXT_OPCODE(op_call_eval); + } + case op_construct: { + compileOpCall(opcodeID, currentInstruction, callLinkInfoIndex++); + NEXT_OPCODE(op_construct); + } + case op_get_global_var: { + JSVariableObject* globalObject = static_cast<JSVariableObject*>(currentInstruction[2].u.jsCell); + move(ImmPtr(globalObject), X86::eax); + emitGetVariableObjectRegister(X86::eax, currentInstruction[3].u.operand, X86::eax); + emitPutVirtualRegister(currentInstruction[1].u.operand); + NEXT_OPCODE(op_get_global_var); + } + case op_put_global_var: { + emitGetVirtualRegister(currentInstruction[3].u.operand, X86::edx); + JSVariableObject* globalObject = static_cast<JSVariableObject*>(currentInstruction[1].u.jsCell); + move(ImmPtr(globalObject), X86::eax); + emitPutVariableObjectRegister(X86::edx, X86::eax, currentInstruction[2].u.operand); + NEXT_OPCODE(op_put_global_var); + } + case op_get_scoped_var: { + int skip = currentInstruction[3].u.operand + m_codeBlock->needsFullScopeChain(); + + emitGetFromCallFrameHeader(RegisterFile::ScopeChain, X86::eax); + while (skip--) + loadPtr(Address(X86::eax, FIELD_OFFSET(ScopeChainNode, next)), X86::eax); + + loadPtr(Address(X86::eax, FIELD_OFFSET(ScopeChainNode, object)), X86::eax); + emitGetVariableObjectRegister(X86::eax, currentInstruction[2].u.operand, X86::eax); + emitPutVirtualRegister(currentInstruction[1].u.operand); + NEXT_OPCODE(op_get_scoped_var); + } + case op_put_scoped_var: { + int skip = currentInstruction[2].u.operand + m_codeBlock->needsFullScopeChain(); + + emitGetFromCallFrameHeader(RegisterFile::ScopeChain, X86::edx); + emitGetVirtualRegister(currentInstruction[3].u.operand, X86::eax); + while (skip--) + loadPtr(Address(X86::edx, FIELD_OFFSET(ScopeChainNode, next)), X86::edx); + + loadPtr(Address(X86::edx, FIELD_OFFSET(ScopeChainNode, object)), X86::edx); + emitPutVariableObjectRegister(X86::eax, X86::edx, currentInstruction[1].u.operand); + NEXT_OPCODE(op_put_scoped_var); + } + case op_tear_off_activation: { + emitPutJITStubArgFromVirtualRegister(currentInstruction[1].u.operand, 1, X86::ecx); + emitCTICall(Interpreter::cti_op_tear_off_activation); + NEXT_OPCODE(op_tear_off_activation); + } + case op_tear_off_arguments: { + emitCTICall(Interpreter::cti_op_tear_off_arguments); + NEXT_OPCODE(op_tear_off_arguments); + } + case op_ret: { + // We could JIT generate the deref, only calling out to C when the refcount hits zero. + if (m_codeBlock->needsFullScopeChain()) + emitCTICall(Interpreter::cti_op_ret_scopeChain); + + // Return the result in %eax. + emitGetVirtualRegister(currentInstruction[1].u.operand, X86::eax); + + // Grab the return address. + emitGetFromCallFrameHeader(RegisterFile::ReturnPC, X86::edx); + + // Restore our caller's "r". + emitGetFromCallFrameHeader(RegisterFile::CallerFrame, callFrameRegister); + + // Return. + push(X86::edx); + ret(); + + NEXT_OPCODE(op_ret); + } + case op_new_array: { + emitPutJITStubArgConstant(currentInstruction[2].u.operand, 1); + emitPutJITStubArgConstant(currentInstruction[3].u.operand, 2); + emitCTICall(Interpreter::cti_op_new_array); + emitPutVirtualRegister(currentInstruction[1].u.operand); + NEXT_OPCODE(op_new_array); + } + case op_resolve: { + Identifier* ident = &(m_codeBlock->identifier(currentInstruction[2].u.operand)); + emitPutJITStubArgConstant(ident, 1); + emitCTICall(Interpreter::cti_op_resolve); + emitPutVirtualRegister(currentInstruction[1].u.operand); + NEXT_OPCODE(op_resolve); + } + case op_construct_verify: { + emitGetVirtualRegister(currentInstruction[1].u.operand, X86::eax); + + emitJumpSlowCaseIfNotJSCell(X86::eax); + loadPtr(Address(X86::eax, FIELD_OFFSET(JSCell, m_structure)), X86::ecx); + addSlowCase(jne32(Address(X86::ecx, FIELD_OFFSET(Structure, m_typeInfo) + FIELD_OFFSET(TypeInfo, m_type)), Imm32(ObjectType))); + + NEXT_OPCODE(op_construct_verify); + } + case op_get_by_val: { + emitGetVirtualRegisters(currentInstruction[2].u.operand, X86::eax, currentInstruction[3].u.operand, X86::edx); + emitJumpSlowCaseIfNotImmediateInteger(X86::edx); +#if USE(ALTERNATE_JSIMMEDIATE) + // This is technically incorrect - we're zero-extending an int32. On the hot path this doesn't matter. + // We check the value as if it was a uint32 against the m_fastAccessCutoff - which will always fail if + // number was signed since m_fastAccessCutoff is always less than intmax (since the total allocation + // size is always less than 4Gb). As such zero extending wil have been correct (and extending the value + // to 64-bits is necessary since it's used in the address calculation. We zero extend rather than sign + // extending since it makes it easier to re-tag the value in the slow case. + zeroExtend32ToPtr(X86::edx, X86::edx); +#else + emitFastArithImmToInt(X86::edx); +#endif + emitJumpSlowCaseIfNotJSCell(X86::eax); + addSlowCase(jnePtr(Address(X86::eax), ImmPtr(m_interpreter->m_jsArrayVptr))); + + // This is an array; get the m_storage pointer into ecx, then check if the index is below the fast cutoff + loadPtr(Address(X86::eax, FIELD_OFFSET(JSArray, m_storage)), X86::ecx); + addSlowCase(jae32(X86::edx, Address(X86::eax, FIELD_OFFSET(JSArray, m_fastAccessCutoff)))); + + // Get the value from the vector + loadPtr(BaseIndex(X86::ecx, X86::edx, ScalePtr, FIELD_OFFSET(ArrayStorage, m_vector[0])), X86::eax); + emitPutVirtualRegister(currentInstruction[1].u.operand); + NEXT_OPCODE(op_get_by_val); + } + case op_resolve_func: { + Identifier* ident = &(m_codeBlock->identifier(currentInstruction[3].u.operand)); + emitPutJITStubArgConstant(ident, 1); + emitCTICall(Interpreter::cti_op_resolve_func); + emitPutVirtualRegister(currentInstruction[2].u.operand, X86::edx); + emitPutVirtualRegister(currentInstruction[1].u.operand); + NEXT_OPCODE(op_resolve_func); + } + case op_sub: { + compileFastArith_op_sub(currentInstruction); + NEXT_OPCODE(op_sub); + } + case op_put_by_val: { + emitGetVirtualRegisters(currentInstruction[1].u.operand, X86::eax, currentInstruction[2].u.operand, X86::edx); + emitJumpSlowCaseIfNotImmediateInteger(X86::edx); +#if USE(ALTERNATE_JSIMMEDIATE) + // See comment in op_get_by_val. + zeroExtend32ToPtr(X86::edx, X86::edx); +#else + emitFastArithImmToInt(X86::edx); +#endif + emitJumpSlowCaseIfNotJSCell(X86::eax); + addSlowCase(jnePtr(Address(X86::eax), ImmPtr(m_interpreter->m_jsArrayVptr))); + + // This is an array; get the m_storage pointer into ecx, then check if the index is below the fast cutoff + loadPtr(Address(X86::eax, FIELD_OFFSET(JSArray, m_storage)), X86::ecx); + Jump inFastVector = jb32(X86::edx, Address(X86::eax, FIELD_OFFSET(JSArray, m_fastAccessCutoff))); + // No; oh well, check if the access if within the vector - if so, we may still be okay. + addSlowCase(jae32(X86::edx, Address(X86::ecx, FIELD_OFFSET(ArrayStorage, m_vectorLength)))); + + // This is a write to the slow part of the vector; first, we have to check if this would be the first write to this location. + // FIXME: should be able to handle initial write to array; increment the the number of items in the array, and potentially update fast access cutoff. + addSlowCase(jzPtr(BaseIndex(X86::ecx, X86::edx, ScalePtr, FIELD_OFFSET(ArrayStorage, m_vector[0])))); + + // All good - put the value into the array. + inFastVector.link(this); + emitGetVirtualRegister(currentInstruction[3].u.operand, X86::eax); + storePtr(X86::eax, BaseIndex(X86::ecx, X86::edx, ScalePtr, FIELD_OFFSET(ArrayStorage, m_vector[0]))); + NEXT_OPCODE(op_put_by_val); + } + CTI_COMPILE_BINARY_OP(op_lesseq) + case op_loop_if_true: { + emitSlowScriptCheck(); + + unsigned target = currentInstruction[2].u.operand; + emitGetVirtualRegister(currentInstruction[1].u.operand, X86::eax); + + Jump isZero = jePtr(X86::eax, ImmPtr(JSValuePtr::encode(js0()))); + addJump(emitJumpIfImmediateInteger(X86::eax), target + 2); + + addJump(jePtr(X86::eax, ImmPtr(JSValuePtr::encode(jsBoolean(true)))), target + 2); + addSlowCase(jnePtr(X86::eax, ImmPtr(JSValuePtr::encode(jsBoolean(false))))); + + isZero.link(this); + NEXT_OPCODE(op_loop_if_true); + }; + case op_resolve_base: { + Identifier* ident = &(m_codeBlock->identifier(currentInstruction[2].u.operand)); + emitPutJITStubArgConstant(ident, 1); + emitCTICall(Interpreter::cti_op_resolve_base); + emitPutVirtualRegister(currentInstruction[1].u.operand); + NEXT_OPCODE(op_resolve_base); + } + case op_negate: { + emitPutJITStubArgFromVirtualRegister(currentInstruction[2].u.operand, 1, X86::ecx); + emitCTICall(Interpreter::cti_op_negate); + emitPutVirtualRegister(currentInstruction[1].u.operand); + NEXT_OPCODE(op_negate); + } + case op_resolve_skip: { + Identifier* ident = &(m_codeBlock->identifier(currentInstruction[2].u.operand)); + emitPutJITStubArgConstant(ident, 1); + emitPutJITStubArgConstant(currentInstruction[3].u.operand + m_codeBlock->needsFullScopeChain(), 2); + emitCTICall(Interpreter::cti_op_resolve_skip); + emitPutVirtualRegister(currentInstruction[1].u.operand); + NEXT_OPCODE(op_resolve_skip); + } + case op_resolve_global: { + // Fast case + void* globalObject = currentInstruction[2].u.jsCell; + Identifier* ident = &(m_codeBlock->identifier(currentInstruction[3].u.operand)); + + unsigned currentIndex = globalResolveInfoIndex++; + void* structureAddress = &(m_codeBlock->globalResolveInfo(currentIndex).structure); + void* offsetAddr = &(m_codeBlock->globalResolveInfo(currentIndex).offset); + + // Check Structure of global object + move(ImmPtr(globalObject), X86::eax); + loadPtr(structureAddress, X86::edx); + Jump noMatch = jnePtr(X86::edx, Address(X86::eax, FIELD_OFFSET(JSCell, m_structure))); // Structures don't match + + // Load cached property + loadPtr(Address(X86::eax, FIELD_OFFSET(JSGlobalObject, m_propertyStorage)), X86::eax); + load32(offsetAddr, X86::edx); + loadPtr(BaseIndex(X86::eax, X86::edx, ScalePtr), X86::eax); + emitPutVirtualRegister(currentInstruction[1].u.operand); + Jump end = jump(); + + // Slow case + noMatch.link(this); + emitPutJITStubArgConstant(globalObject, 1); + emitPutJITStubArgConstant(ident, 2); + emitPutJITStubArgConstant(currentIndex, 3); + emitCTICall(Interpreter::cti_op_resolve_global); + emitPutVirtualRegister(currentInstruction[1].u.operand); + end.link(this); + NEXT_OPCODE(op_resolve_global); + } + CTI_COMPILE_BINARY_OP(op_div) + case op_pre_dec: { + compileFastArith_op_pre_dec(currentInstruction[1].u.operand); + NEXT_OPCODE(op_pre_dec); + } + case op_jnless: { + unsigned op1 = currentInstruction[1].u.operand; + unsigned op2 = currentInstruction[2].u.operand; + unsigned target = currentInstruction[3].u.operand; + if (isOperandConstantImmediateInt(op2)) { + emitGetVirtualRegister(op1, X86::eax); + emitJumpSlowCaseIfNotImmediateInteger(X86::eax); +#if USE(ALTERNATE_JSIMMEDIATE) + int32_t op2imm = getConstantOperandImmediateInt(op2); +#else + int32_t op2imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2))); +#endif + addJump(jge32(X86::eax, Imm32(op2imm)), target + 3); + } else { + emitGetVirtualRegisters(op1, X86::eax, op2, X86::edx); + emitJumpSlowCaseIfNotImmediateInteger(X86::eax); + emitJumpSlowCaseIfNotImmediateInteger(X86::edx); + addJump(jge32(X86::eax, X86::edx), target + 3); + } + NEXT_OPCODE(op_jnless); + } + case op_not: { + emitGetVirtualRegister(currentInstruction[2].u.operand, X86::eax); + xorPtr(Imm32(static_cast<int32_t>(JSImmediate::FullTagTypeBool)), X86::eax); + addSlowCase(jnzPtr(X86::eax, Imm32(static_cast<int32_t>(~JSImmediate::ExtendedPayloadBitBoolValue)))); + xorPtr(Imm32(static_cast<int32_t>(JSImmediate::FullTagTypeBool | JSImmediate::ExtendedPayloadBitBoolValue)), X86::eax); + emitPutVirtualRegister(currentInstruction[1].u.operand); + NEXT_OPCODE(op_not); + } + case op_jfalse: { + unsigned target = currentInstruction[2].u.operand; + emitGetVirtualRegister(currentInstruction[1].u.operand, X86::eax); + + addJump(jePtr(X86::eax, ImmPtr(JSValuePtr::encode(js0()))), target + 2); + Jump isNonZero = emitJumpIfImmediateInteger(X86::eax); + + addJump(jePtr(X86::eax, ImmPtr(JSValuePtr::encode(jsBoolean(false)))), target + 2); + addSlowCase(jnePtr(X86::eax, ImmPtr(JSValuePtr::encode(jsBoolean(true))))); + + isNonZero.link(this); + NEXT_OPCODE(op_jfalse); + }; + case op_jeq_null: { + unsigned src = currentInstruction[1].u.operand; + unsigned target = currentInstruction[2].u.operand; + + emitGetVirtualRegister(src, X86::eax); + Jump isImmediate = emitJumpIfNotJSCell(X86::eax); + + // First, handle JSCell cases - check MasqueradesAsUndefined bit on the structure. + loadPtr(Address(X86::eax, FIELD_OFFSET(JSCell, m_structure)), X86::ecx); + addJump(jnz32(Address(X86::ecx, FIELD_OFFSET(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined)), target + 2); + Jump wasNotImmediate = jump(); + + // Now handle the immediate cases - undefined & null + isImmediate.link(this); + andPtr(Imm32(~JSImmediate::ExtendedTagBitUndefined), X86::eax); + addJump(jePtr(X86::eax, ImmPtr(JSValuePtr::encode(jsNull()))), target + 2); + + wasNotImmediate.link(this); + NEXT_OPCODE(op_jeq_null); + }; + case op_jneq_null: { + unsigned src = currentInstruction[1].u.operand; + unsigned target = currentInstruction[2].u.operand; + + emitGetVirtualRegister(src, X86::eax); + Jump isImmediate = emitJumpIfNotJSCell(X86::eax); + + // First, handle JSCell cases - check MasqueradesAsUndefined bit on the structure. + loadPtr(Address(X86::eax, FIELD_OFFSET(JSCell, m_structure)), X86::ecx); + addJump(jz32(Address(X86::ecx, FIELD_OFFSET(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined)), target + 2); + Jump wasNotImmediate = jump(); + + // Now handle the immediate cases - undefined & null + isImmediate.link(this); + andPtr(Imm32(~JSImmediate::ExtendedTagBitUndefined), X86::eax); + addJump(jnePtr(X86::eax, ImmPtr(JSValuePtr::encode(jsNull()))), target + 2); + + wasNotImmediate.link(this); + NEXT_OPCODE(op_jneq_null); + } + case op_post_inc: { + compileFastArith_op_post_inc(currentInstruction[1].u.operand, currentInstruction[2].u.operand); + NEXT_OPCODE(op_post_inc); + } + case op_unexpected_load: { + JSValuePtr v = m_codeBlock->unexpectedConstant(currentInstruction[2].u.operand); + move(ImmPtr(JSValuePtr::encode(v)), X86::eax); + emitPutVirtualRegister(currentInstruction[1].u.operand); + NEXT_OPCODE(op_unexpected_load); + } + case op_jsr: { + int retAddrDst = currentInstruction[1].u.operand; + int target = currentInstruction[2].u.operand; + DataLabelPtr storeLocation = storePtrWithPatch(Address(callFrameRegister, sizeof(Register) * retAddrDst)); + addJump(jump(), target + 2); + m_jsrSites.append(JSRInfo(storeLocation, label())); + NEXT_OPCODE(op_jsr); + } + case op_sret: { + jump(Address(callFrameRegister, sizeof(Register) * currentInstruction[1].u.operand)); + NEXT_OPCODE(op_sret); + } + case op_eq: { + emitGetVirtualRegisters(currentInstruction[2].u.operand, X86::eax, currentInstruction[3].u.operand, X86::edx); + emitJumpSlowCaseIfNotImmediateIntegers(X86::eax, X86::edx, X86::ecx); + sete32(X86::edx, X86::eax); + emitTagAsBoolImmediate(X86::eax); + emitPutVirtualRegister(currentInstruction[1].u.operand); + NEXT_OPCODE(op_eq); + } + case op_lshift: { + compileFastArith_op_lshift(currentInstruction[1].u.operand, currentInstruction[2].u.operand, currentInstruction[3].u.operand); + NEXT_OPCODE(op_lshift); + } + case op_bitand: { + compileFastArith_op_bitand(currentInstruction[1].u.operand, currentInstruction[2].u.operand, currentInstruction[3].u.operand); + NEXT_OPCODE(op_bitand); + } + case op_rshift: { + compileFastArith_op_rshift(currentInstruction[1].u.operand, currentInstruction[2].u.operand, currentInstruction[3].u.operand); + NEXT_OPCODE(op_rshift); + } + case op_bitnot: { + emitGetVirtualRegister(currentInstruction[2].u.operand, X86::eax); + emitJumpSlowCaseIfNotImmediateInteger(X86::eax); +#if USE(ALTERNATE_JSIMMEDIATE) + not32(X86::eax); + emitFastArithIntToImmNoCheck(X86::eax, X86::eax); +#else + xorPtr(Imm32(~JSImmediate::TagTypeNumber), X86::eax); +#endif + emitPutVirtualRegister(currentInstruction[1].u.operand); + NEXT_OPCODE(op_bitnot); + } + case op_resolve_with_base: { + Identifier* ident = &(m_codeBlock->identifier(currentInstruction[3].u.operand)); + emitPutJITStubArgConstant(ident, 1); + emitCTICall(Interpreter::cti_op_resolve_with_base); + emitPutVirtualRegister(currentInstruction[2].u.operand, X86::edx); + emitPutVirtualRegister(currentInstruction[1].u.operand); + NEXT_OPCODE(op_resolve_with_base); + } + case op_new_func_exp: { + FuncExprNode* func = m_codeBlock->functionExpression(currentInstruction[2].u.operand); + emitPutJITStubArgConstant(func, 1); + emitCTICall(Interpreter::cti_op_new_func_exp); + emitPutVirtualRegister(currentInstruction[1].u.operand); + NEXT_OPCODE(op_new_func_exp); + } + case op_mod: { + compileFastArith_op_mod(currentInstruction[1].u.operand, currentInstruction[2].u.operand, currentInstruction[3].u.operand); + NEXT_OPCODE(op_mod); + } + case op_jtrue: { + unsigned target = currentInstruction[2].u.operand; + emitGetVirtualRegister(currentInstruction[1].u.operand, X86::eax); + + Jump isZero = jePtr(X86::eax, ImmPtr(JSValuePtr::encode(js0()))); + addJump(emitJumpIfImmediateInteger(X86::eax), target + 2); + + addJump(jePtr(X86::eax, ImmPtr(JSValuePtr::encode(jsBoolean(true)))), target + 2); + addSlowCase(jnePtr(X86::eax, ImmPtr(JSValuePtr::encode(jsBoolean(false))))); + + isZero.link(this); + NEXT_OPCODE(op_jtrue); + } + CTI_COMPILE_BINARY_OP(op_less) + case op_neq: { + emitGetVirtualRegisters(currentInstruction[2].u.operand, X86::eax, currentInstruction[3].u.operand, X86::edx); + emitJumpSlowCaseIfNotImmediateIntegers(X86::eax, X86::edx, X86::ecx); + setne32(X86::edx, X86::eax); + emitTagAsBoolImmediate(X86::eax); + + emitPutVirtualRegister(currentInstruction[1].u.operand); + + NEXT_OPCODE(op_neq); + } + case op_post_dec: { + compileFastArith_op_post_dec(currentInstruction[1].u.operand, currentInstruction[2].u.operand); + NEXT_OPCODE(op_post_dec); + } + CTI_COMPILE_BINARY_OP(op_urshift) + case op_bitxor: { + emitGetVirtualRegisters(currentInstruction[2].u.operand, X86::eax, currentInstruction[3].u.operand, X86::edx); + emitJumpSlowCaseIfNotImmediateIntegers(X86::eax, X86::edx, X86::ecx); + xorPtr(X86::edx, X86::eax); + emitFastArithReTagImmediate(X86::eax, X86::eax); + emitPutVirtualRegister(currentInstruction[1].u.operand); + NEXT_OPCODE(op_bitxor); + } + case op_new_regexp: { + RegExp* regExp = m_codeBlock->regexp(currentInstruction[2].u.operand); + emitPutJITStubArgConstant(regExp, 1); + emitCTICall(Interpreter::cti_op_new_regexp); + emitPutVirtualRegister(currentInstruction[1].u.operand); + NEXT_OPCODE(op_new_regexp); + } + case op_bitor: { + emitGetVirtualRegisters(currentInstruction[2].u.operand, X86::eax, currentInstruction[3].u.operand, X86::edx); + emitJumpSlowCaseIfNotImmediateIntegers(X86::eax, X86::edx, X86::ecx); + orPtr(X86::edx, X86::eax); + emitPutVirtualRegister(currentInstruction[1].u.operand); + NEXT_OPCODE(op_bitor); + } + case op_throw: { + emitPutJITStubArgFromVirtualRegister(currentInstruction[1].u.operand, 1, X86::ecx); + emitCTICall(Interpreter::cti_op_throw); +#if PLATFORM(X86_64) + addPtr(Imm32(0x48), X86::esp); + pop(X86::ebx); + pop(X86::r15); + pop(X86::r14); + pop(X86::r13); + pop(X86::r12); + pop(X86::ebp); + ret(); +#else + addPtr(Imm32(0x1c), X86::esp); + pop(X86::ebx); + pop(X86::edi); + pop(X86::esi); + pop(X86::ebp); + ret(); +#endif + NEXT_OPCODE(op_throw); + } + case op_get_pnames: { + emitPutJITStubArgFromVirtualRegister(currentInstruction[2].u.operand, 1, X86::ecx); + emitCTICall(Interpreter::cti_op_get_pnames); + emitPutVirtualRegister(currentInstruction[1].u.operand); + NEXT_OPCODE(op_get_pnames); + } + case op_next_pname: { + emitPutJITStubArgFromVirtualRegister(currentInstruction[2].u.operand, 1, X86::ecx); + unsigned target = currentInstruction[3].u.operand; + emitCTICall(Interpreter::cti_op_next_pname); + Jump endOfIter = jzPtr(X86::eax); + emitPutVirtualRegister(currentInstruction[1].u.operand); + addJump(jump(), target + 3); + endOfIter.link(this); + NEXT_OPCODE(op_next_pname); + } + case op_push_scope: { + emitPutJITStubArgFromVirtualRegister(currentInstruction[1].u.operand, 1, X86::ecx); + emitCTICall(Interpreter::cti_op_push_scope); + emitPutVirtualRegister(currentInstruction[1].u.operand); + NEXT_OPCODE(op_push_scope); + } + case op_pop_scope: { + emitCTICall(Interpreter::cti_op_pop_scope); + NEXT_OPCODE(op_pop_scope); + } + CTI_COMPILE_UNARY_OP(op_typeof) + CTI_COMPILE_UNARY_OP(op_is_undefined) + CTI_COMPILE_UNARY_OP(op_is_boolean) + CTI_COMPILE_UNARY_OP(op_is_number) + CTI_COMPILE_UNARY_OP(op_is_string) + CTI_COMPILE_UNARY_OP(op_is_object) + CTI_COMPILE_UNARY_OP(op_is_function) + case op_stricteq: { + compileOpStrictEq(currentInstruction, OpStrictEq); + NEXT_OPCODE(op_stricteq); + } + case op_nstricteq: { + compileOpStrictEq(currentInstruction, OpNStrictEq); + NEXT_OPCODE(op_nstricteq); + } + case op_to_jsnumber: { + int srcVReg = currentInstruction[2].u.operand; + emitGetVirtualRegister(srcVReg, X86::eax); + + Jump wasImmediate = emitJumpIfImmediateInteger(X86::eax); + + emitJumpSlowCaseIfNotJSCell(X86::eax, srcVReg); + loadPtr(Address(X86::eax, FIELD_OFFSET(JSCell, m_structure)), X86::ecx); + addSlowCase(jne32(Address(X86::ecx, FIELD_OFFSET(Structure, m_typeInfo.m_type)), Imm32(NumberType))); + + wasImmediate.link(this); + + emitPutVirtualRegister(currentInstruction[1].u.operand); + NEXT_OPCODE(op_to_jsnumber); + } + CTI_COMPILE_BINARY_OP(op_in) + case op_push_new_scope: { + Identifier* ident = &(m_codeBlock->identifier(currentInstruction[2].u.operand)); + emitPutJITStubArgConstant(ident, 1); + emitPutJITStubArgFromVirtualRegister(currentInstruction[3].u.operand, 2, X86::ecx); + emitCTICall(Interpreter::cti_op_push_new_scope); + emitPutVirtualRegister(currentInstruction[1].u.operand); + NEXT_OPCODE(op_push_new_scope); + } + case op_catch: { + emitGetCTIParam(STUB_ARGS_callFrame, callFrameRegister); + emitPutVirtualRegister(currentInstruction[1].u.operand); + NEXT_OPCODE(op_catch); + } + case op_jmp_scopes: { + unsigned count = currentInstruction[1].u.operand; + emitPutJITStubArgConstant(count, 1); + emitCTICall(Interpreter::cti_op_jmp_scopes); + unsigned target = currentInstruction[2].u.operand; + addJump(jump(), target + 2); + NEXT_OPCODE(op_jmp_scopes); + } + case op_put_by_index: { + emitPutJITStubArgFromVirtualRegister(currentInstruction[1].u.operand, 1, X86::ecx); + emitPutJITStubArgConstant(currentInstruction[2].u.operand, 2); + emitPutJITStubArgFromVirtualRegister(currentInstruction[3].u.operand, 3, X86::ecx); + emitCTICall(Interpreter::cti_op_put_by_index); + NEXT_OPCODE(op_put_by_index); + } + case op_switch_imm: { + unsigned tableIndex = currentInstruction[1].u.operand; + unsigned defaultOffset = currentInstruction[2].u.operand; + unsigned scrutinee = currentInstruction[3].u.operand; + + // create jump table for switch destinations, track this switch statement. + SimpleJumpTable* jumpTable = &m_codeBlock->immediateSwitchJumpTable(tableIndex); + m_switches.append(SwitchRecord(jumpTable, m_bytecodeIndex, defaultOffset, SwitchRecord::Immediate)); + jumpTable->ctiOffsets.grow(jumpTable->branchOffsets.size()); + + emitPutJITStubArgFromVirtualRegister(scrutinee, 1, X86::ecx); + emitPutJITStubArgConstant(tableIndex, 2); + emitCTICall(Interpreter::cti_op_switch_imm); + jump(X86::eax); + NEXT_OPCODE(op_switch_imm); + } + case op_switch_char: { + unsigned tableIndex = currentInstruction[1].u.operand; + unsigned defaultOffset = currentInstruction[2].u.operand; + unsigned scrutinee = currentInstruction[3].u.operand; + + // create jump table for switch destinations, track this switch statement. + SimpleJumpTable* jumpTable = &m_codeBlock->characterSwitchJumpTable(tableIndex); + m_switches.append(SwitchRecord(jumpTable, m_bytecodeIndex, defaultOffset, SwitchRecord::Character)); + jumpTable->ctiOffsets.grow(jumpTable->branchOffsets.size()); + + emitPutJITStubArgFromVirtualRegister(scrutinee, 1, X86::ecx); + emitPutJITStubArgConstant(tableIndex, 2); + emitCTICall(Interpreter::cti_op_switch_char); + jump(X86::eax); + NEXT_OPCODE(op_switch_char); + } + case op_switch_string: { + unsigned tableIndex = currentInstruction[1].u.operand; + unsigned defaultOffset = currentInstruction[2].u.operand; + unsigned scrutinee = currentInstruction[3].u.operand; + + // create jump table for switch destinations, track this switch statement. + StringJumpTable* jumpTable = &m_codeBlock->stringSwitchJumpTable(tableIndex); + m_switches.append(SwitchRecord(jumpTable, m_bytecodeIndex, defaultOffset)); + + emitPutJITStubArgFromVirtualRegister(scrutinee, 1, X86::ecx); + emitPutJITStubArgConstant(tableIndex, 2); + emitCTICall(Interpreter::cti_op_switch_string); + jump(X86::eax); + NEXT_OPCODE(op_switch_string); + } + case op_del_by_val: { + emitPutJITStubArgFromVirtualRegister(currentInstruction[2].u.operand, 1, X86::ecx); + emitPutJITStubArgFromVirtualRegister(currentInstruction[3].u.operand, 2, X86::ecx); + emitCTICall(Interpreter::cti_op_del_by_val); + emitPutVirtualRegister(currentInstruction[1].u.operand); + NEXT_OPCODE(op_del_by_val); + } + case op_put_getter: { + emitPutJITStubArgFromVirtualRegister(currentInstruction[1].u.operand, 1, X86::ecx); + Identifier* ident = &(m_codeBlock->identifier(currentInstruction[2].u.operand)); + emitPutJITStubArgConstant(ident, 2); + emitPutJITStubArgFromVirtualRegister(currentInstruction[3].u.operand, 3, X86::ecx); + emitCTICall(Interpreter::cti_op_put_getter); + NEXT_OPCODE(op_put_getter); + } + case op_put_setter: { + emitPutJITStubArgFromVirtualRegister(currentInstruction[1].u.operand, 1, X86::ecx); + Identifier* ident = &(m_codeBlock->identifier(currentInstruction[2].u.operand)); + emitPutJITStubArgConstant(ident, 2); + emitPutJITStubArgFromVirtualRegister(currentInstruction[3].u.operand, 3, X86::ecx); + emitCTICall(Interpreter::cti_op_put_setter); + NEXT_OPCODE(op_put_setter); + } + case op_new_error: { + JSValuePtr message = m_codeBlock->unexpectedConstant(currentInstruction[3].u.operand); + emitPutJITStubArgConstant(currentInstruction[2].u.operand, 1); + emitPutJITStubArgConstant(JSValuePtr::encode(message), 2); + emitPutJITStubArgConstant(m_bytecodeIndex, 3); + emitCTICall(Interpreter::cti_op_new_error); + emitPutVirtualRegister(currentInstruction[1].u.operand); + NEXT_OPCODE(op_new_error); + } + case op_debug: { + emitPutJITStubArgConstant(currentInstruction[1].u.operand, 1); + emitPutJITStubArgConstant(currentInstruction[2].u.operand, 2); + emitPutJITStubArgConstant(currentInstruction[3].u.operand, 3); + emitCTICall(Interpreter::cti_op_debug); + NEXT_OPCODE(op_debug); + } + case op_eq_null: { + unsigned dst = currentInstruction[1].u.operand; + unsigned src1 = currentInstruction[2].u.operand; + + emitGetVirtualRegister(src1, X86::eax); + Jump isImmediate = emitJumpIfNotJSCell(X86::eax); + + loadPtr(Address(X86::eax, FIELD_OFFSET(JSCell, m_structure)), X86::ecx); + setnz32(Address(X86::ecx, FIELD_OFFSET(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined), X86::eax); + + Jump wasNotImmediate = jump(); + + isImmediate.link(this); + + andPtr(Imm32(~JSImmediate::ExtendedTagBitUndefined), X86::eax); + sete32(Imm32(JSImmediate::FullTagTypeNull), X86::eax); + + wasNotImmediate.link(this); + + emitTagAsBoolImmediate(X86::eax); + emitPutVirtualRegister(dst); + + NEXT_OPCODE(op_eq_null); + } + case op_neq_null: { + unsigned dst = currentInstruction[1].u.operand; + unsigned src1 = currentInstruction[2].u.operand; + + emitGetVirtualRegister(src1, X86::eax); + Jump isImmediate = emitJumpIfNotJSCell(X86::eax); + + loadPtr(Address(X86::eax, FIELD_OFFSET(JSCell, m_structure)), X86::ecx); + setz32(Address(X86::ecx, FIELD_OFFSET(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined), X86::eax); + + Jump wasNotImmediate = jump(); + + isImmediate.link(this); + + andPtr(Imm32(~JSImmediate::ExtendedTagBitUndefined), X86::eax); + setne32(Imm32(JSImmediate::FullTagTypeNull), X86::eax); + + wasNotImmediate.link(this); + + emitTagAsBoolImmediate(X86::eax); + emitPutVirtualRegister(dst); + + NEXT_OPCODE(op_neq_null); + } + case op_enter: { + // Even though CTI doesn't use them, we initialize our constant + // registers to zap stale pointers, to avoid unnecessarily prolonging + // object lifetime and increasing GC pressure. + size_t count = m_codeBlock->m_numVars + m_codeBlock->numberOfConstantRegisters(); + for (size_t j = 0; j < count; ++j) + emitInitRegister(j); + + NEXT_OPCODE(op_enter); + } + case op_enter_with_activation: { + // Even though CTI doesn't use them, we initialize our constant + // registers to zap stale pointers, to avoid unnecessarily prolonging + // object lifetime and increasing GC pressure. + size_t count = m_codeBlock->m_numVars + m_codeBlock->numberOfConstantRegisters(); + for (size_t j = 0; j < count; ++j) + emitInitRegister(j); + + emitCTICall(Interpreter::cti_op_push_activation); + emitPutVirtualRegister(currentInstruction[1].u.operand); + + NEXT_OPCODE(op_enter_with_activation); + } + case op_create_arguments: { + if (m_codeBlock->m_numParameters == 1) + emitCTICall(Interpreter::cti_op_create_arguments_no_params); + else + emitCTICall(Interpreter::cti_op_create_arguments); + NEXT_OPCODE(op_create_arguments); + } + case op_convert_this: { + emitGetVirtualRegister(currentInstruction[1].u.operand, X86::eax); + + emitJumpSlowCaseIfNotJSCell(X86::eax); + loadPtr(Address(X86::eax, FIELD_OFFSET(JSCell, m_structure)), X86::edx); + addSlowCase(jnz32(Address(X86::edx, FIELD_OFFSET(Structure, m_typeInfo.m_flags)), Imm32(NeedsThisConversion))); + + NEXT_OPCODE(op_convert_this); + } + case op_profile_will_call: { + emitGetCTIParam(STUB_ARGS_profilerReference, X86::eax); + Jump noProfiler = jzPtr(Address(X86::eax)); + emitPutJITStubArgFromVirtualRegister(currentInstruction[1].u.operand, 1, X86::eax); + emitCTICall(Interpreter::cti_op_profile_will_call); + noProfiler.link(this); + + NEXT_OPCODE(op_profile_will_call); + } + case op_profile_did_call: { + emitGetCTIParam(STUB_ARGS_profilerReference, X86::eax); + Jump noProfiler = jzPtr(Address(X86::eax)); + emitPutJITStubArgFromVirtualRegister(currentInstruction[1].u.operand, 1, X86::eax); + emitCTICall(Interpreter::cti_op_profile_did_call); + noProfiler.link(this); + + NEXT_OPCODE(op_profile_did_call); + } + case op_get_array_length: + case op_get_by_id_chain: + case op_get_by_id_generic: + case op_get_by_id_proto: + case op_get_by_id_proto_list: + case op_get_by_id_self: + case op_get_by_id_self_list: + case op_get_string_length: + case op_put_by_id_generic: + case op_put_by_id_replace: + case op_put_by_id_transition: + ASSERT_NOT_REACHED(); + } + } + + ASSERT(propertyAccessInstructionIndex == m_codeBlock->numberOfStructureStubInfos()); + ASSERT(callLinkInfoIndex == m_codeBlock->numberOfCallLinkInfos()); + +#ifndef NDEBUG + // reset this, in order to guard it's use with asserts + m_bytecodeIndex = (unsigned)-1; +#endif +} + + +void JIT::privateCompileLinkPass() +{ + unsigned jmpTableCount = m_jmpTable.size(); + for (unsigned i = 0; i < jmpTableCount; ++i) + m_jmpTable[i].from.linkTo(m_labels[m_jmpTable[i].toBytecodeIndex], this); + m_jmpTable.clear(); +} + +void JIT::privateCompileSlowCases() +{ + Instruction* instructionsBegin = m_codeBlock->instructions().begin(); + unsigned propertyAccessInstructionIndex = 0; + unsigned callLinkInfoIndex = 0; + + for (Vector<SlowCaseEntry>::iterator iter = m_slowCases.begin(); iter != m_slowCases.end();) { + // FIXME: enable peephole optimizations for slow cases when applicable + killLastResultRegister(); + + m_bytecodeIndex = iter->to; +#ifndef NDEBUG + unsigned firstTo = m_bytecodeIndex; +#endif + Instruction* currentInstruction = instructionsBegin + m_bytecodeIndex; + + switch (OpcodeID opcodeID = m_interpreter->getOpcodeID(currentInstruction->u.opcode)) { + case op_convert_this: { + linkSlowCase(iter); + linkSlowCase(iter); + emitPutJITStubArg(X86::eax, 1); + emitCTICall(Interpreter::cti_op_convert_this); + emitPutVirtualRegister(currentInstruction[1].u.operand); + NEXT_OPCODE(op_convert_this); + } + case op_add: { + compileFastArithSlow_op_add(currentInstruction, iter); + NEXT_OPCODE(op_add); + } + case op_construct_verify: { + linkSlowCase(iter); + linkSlowCase(iter); + emitGetVirtualRegister(currentInstruction[2].u.operand, X86::eax); + emitPutVirtualRegister(currentInstruction[1].u.operand); + + NEXT_OPCODE(op_construct_verify); + } + case op_get_by_val: { + // The slow case that handles accesses to arrays (below) may jump back up to here. + Label beginGetByValSlow(this); + + Jump notImm = getSlowCase(iter); + linkSlowCase(iter); + linkSlowCase(iter); + emitFastArithIntToImmNoCheck(X86::edx, X86::edx); + notImm.link(this); + emitPutJITStubArg(X86::eax, 1); + emitPutJITStubArg(X86::edx, 2); + emitCTICall(Interpreter::cti_op_get_by_val); + emitPutVirtualRegister(currentInstruction[1].u.operand); + emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_get_by_val)); + + // This is slow case that handles accesses to arrays above the fast cut-off. + // First, check if this is an access to the vector + linkSlowCase(iter); + jae32(X86::edx, Address(X86::ecx, FIELD_OFFSET(ArrayStorage, m_vectorLength)), beginGetByValSlow); + + // okay, missed the fast region, but it is still in the vector. Get the value. + loadPtr(BaseIndex(X86::ecx, X86::edx, ScalePtr, FIELD_OFFSET(ArrayStorage, m_vector[0])), X86::ecx); + // Check whether the value loaded is zero; if so we need to return undefined. + jzPtr(X86::ecx, beginGetByValSlow); + move(X86::ecx, X86::eax); + emitPutVirtualRegister(currentInstruction[1].u.operand, X86::eax); + + NEXT_OPCODE(op_get_by_val); + } + case op_sub: { + compileFastArithSlow_op_sub(currentInstruction, iter); + NEXT_OPCODE(op_sub); + } + case op_rshift: { + compileFastArithSlow_op_rshift(currentInstruction[1].u.operand, currentInstruction[2].u.operand, currentInstruction[3].u.operand, iter); + NEXT_OPCODE(op_rshift); + } + case op_lshift: { + compileFastArithSlow_op_lshift(currentInstruction[1].u.operand, currentInstruction[2].u.operand, currentInstruction[3].u.operand, iter); + NEXT_OPCODE(op_lshift); + } + case op_loop_if_less: { + unsigned op2 = currentInstruction[2].u.operand; + unsigned target = currentInstruction[3].u.operand; + if (isOperandConstantImmediateInt(op2)) { + linkSlowCase(iter); + emitPutJITStubArg(X86::eax, 1); + emitPutJITStubArgFromVirtualRegister(op2, 2, X86::ecx); + emitCTICall(Interpreter::cti_op_loop_if_less); + emitJumpSlowToHot(jnz32(X86::eax), target + 3); + } else { + linkSlowCase(iter); + linkSlowCase(iter); + emitPutJITStubArg(X86::eax, 1); + emitPutJITStubArg(X86::edx, 2); + emitCTICall(Interpreter::cti_op_loop_if_less); + emitJumpSlowToHot(jnz32(X86::eax), target + 3); + } + NEXT_OPCODE(op_loop_if_less); + } + case op_put_by_id: { + compilePutByIdSlowCase(currentInstruction[1].u.operand, &(m_codeBlock->identifier(currentInstruction[2].u.operand)), currentInstruction[3].u.operand, iter, propertyAccessInstructionIndex++); + NEXT_OPCODE(op_put_by_id); + } + case op_get_by_id: { + compileGetByIdSlowCase(currentInstruction[1].u.operand, currentInstruction[2].u.operand, &(m_codeBlock->identifier(currentInstruction[3].u.operand)), iter, propertyAccessInstructionIndex++); + NEXT_OPCODE(op_get_by_id); + } + case op_loop_if_lesseq: { + unsigned op2 = currentInstruction[2].u.operand; + unsigned target = currentInstruction[3].u.operand; + if (isOperandConstantImmediateInt(op2)) { + linkSlowCase(iter); + emitPutJITStubArg(X86::eax, 1); + emitPutJITStubArgFromVirtualRegister(currentInstruction[2].u.operand, 2, X86::ecx); + emitCTICall(Interpreter::cti_op_loop_if_lesseq); + emitJumpSlowToHot(jnz32(X86::eax), target + 3); + } else { + linkSlowCase(iter); + linkSlowCase(iter); + emitPutJITStubArg(X86::eax, 1); + emitPutJITStubArg(X86::edx, 2); + emitCTICall(Interpreter::cti_op_loop_if_lesseq); + emitJumpSlowToHot(jnz32(X86::eax), target + 3); + } + NEXT_OPCODE(op_loop_if_lesseq); + } + case op_pre_inc: { + compileFastArithSlow_op_pre_inc(currentInstruction[1].u.operand, iter); + NEXT_OPCODE(op_pre_inc); + } + case op_put_by_val: { + // Normal slow cases - either is not an immediate imm, or is an array. + Jump notImm = getSlowCase(iter); + linkSlowCase(iter); + linkSlowCase(iter); + emitFastArithIntToImmNoCheck(X86::edx, X86::edx); + notImm.link(this); + emitGetVirtualRegister(currentInstruction[3].u.operand, X86::ecx); + emitPutJITStubArg(X86::eax, 1); + emitPutJITStubArg(X86::edx, 2); + emitPutJITStubArg(X86::ecx, 3); + emitCTICall(Interpreter::cti_op_put_by_val); + emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_put_by_val)); + + // slow cases for immediate int accesses to arrays + linkSlowCase(iter); + linkSlowCase(iter); + emitGetVirtualRegister(currentInstruction[3].u.operand, X86::ecx); + emitPutJITStubArg(X86::eax, 1); + emitPutJITStubArg(X86::edx, 2); + emitPutJITStubArg(X86::ecx, 3); + emitCTICall(Interpreter::cti_op_put_by_val_array); + + NEXT_OPCODE(op_put_by_val); + } + case op_loop_if_true: { + linkSlowCase(iter); + emitPutJITStubArg(X86::eax, 1); + emitCTICall(Interpreter::cti_op_jtrue); + unsigned target = currentInstruction[2].u.operand; + emitJumpSlowToHot(jnz32(X86::eax), target + 2); + NEXT_OPCODE(op_loop_if_true); + } + case op_pre_dec: { + compileFastArithSlow_op_pre_dec(currentInstruction[1].u.operand, iter); + NEXT_OPCODE(op_pre_dec); + } + case op_jnless: { + unsigned op2 = currentInstruction[2].u.operand; + unsigned target = currentInstruction[3].u.operand; + if (isOperandConstantImmediateInt(op2)) { + linkSlowCase(iter); + emitPutJITStubArg(X86::eax, 1); + emitPutJITStubArgFromVirtualRegister(currentInstruction[2].u.operand, 2, X86::ecx); + emitCTICall(Interpreter::cti_op_jless); + emitJumpSlowToHot(jz32(X86::eax), target + 3); + } else { + linkSlowCase(iter); + linkSlowCase(iter); + emitPutJITStubArg(X86::eax, 1); + emitPutJITStubArg(X86::edx, 2); + emitCTICall(Interpreter::cti_op_jless); + emitJumpSlowToHot(jz32(X86::eax), target + 3); + } + NEXT_OPCODE(op_jnless); + } + case op_not: { + linkSlowCase(iter); + xorPtr(Imm32(static_cast<int32_t>(JSImmediate::FullTagTypeBool)), X86::eax); + emitPutJITStubArg(X86::eax, 1); + emitCTICall(Interpreter::cti_op_not); + emitPutVirtualRegister(currentInstruction[1].u.operand); + NEXT_OPCODE(op_not); + } + case op_jfalse: { + linkSlowCase(iter); + emitPutJITStubArg(X86::eax, 1); + emitCTICall(Interpreter::cti_op_jtrue); + unsigned target = currentInstruction[2].u.operand; + emitJumpSlowToHot(jz32(X86::eax), target + 2); // inverted! + NEXT_OPCODE(op_jfalse); + } + case op_post_inc: { + compileFastArithSlow_op_post_inc(currentInstruction[1].u.operand, currentInstruction[2].u.operand, iter); + NEXT_OPCODE(op_post_inc); + } + case op_bitnot: { + linkSlowCase(iter); + emitPutJITStubArg(X86::eax, 1); + emitCTICall(Interpreter::cti_op_bitnot); + emitPutVirtualRegister(currentInstruction[1].u.operand); + NEXT_OPCODE(op_bitnot); + } + case op_bitand: { + compileFastArithSlow_op_bitand(currentInstruction[1].u.operand, currentInstruction[2].u.operand, currentInstruction[3].u.operand, iter); + NEXT_OPCODE(op_bitand); + } + case op_jtrue: { + linkSlowCase(iter); + emitPutJITStubArg(X86::eax, 1); + emitCTICall(Interpreter::cti_op_jtrue); + unsigned target = currentInstruction[2].u.operand; + emitJumpSlowToHot(jnz32(X86::eax), target + 2); + NEXT_OPCODE(op_jtrue); + } + case op_post_dec: { + compileFastArithSlow_op_post_dec(currentInstruction[1].u.operand, currentInstruction[2].u.operand, iter); + NEXT_OPCODE(op_post_dec); + } + case op_bitxor: { + linkSlowCase(iter); + emitPutJITStubArg(X86::eax, 1); + emitPutJITStubArg(X86::edx, 2); + emitCTICall(Interpreter::cti_op_bitxor); + emitPutVirtualRegister(currentInstruction[1].u.operand); + NEXT_OPCODE(op_bitxor); + } + case op_bitor: { + linkSlowCase(iter); + emitPutJITStubArg(X86::eax, 1); + emitPutJITStubArg(X86::edx, 2); + emitCTICall(Interpreter::cti_op_bitor); + emitPutVirtualRegister(currentInstruction[1].u.operand); + NEXT_OPCODE(op_bitor); + } + case op_eq: { + linkSlowCase(iter); + emitPutJITStubArg(X86::eax, 1); + emitPutJITStubArg(X86::edx, 2); + emitCTICall(Interpreter::cti_op_eq); + emitPutVirtualRegister(currentInstruction[1].u.operand); + NEXT_OPCODE(op_eq); + } + case op_neq: { + linkSlowCase(iter); + emitPutJITStubArg(X86::eax, 1); + emitPutJITStubArg(X86::edx, 2); + emitCTICall(Interpreter::cti_op_neq); + emitPutVirtualRegister(currentInstruction[1].u.operand); + NEXT_OPCODE(op_neq); + } + case op_stricteq: { + linkSlowCase(iter); + linkSlowCase(iter); +#if !USE(ALTERNATE_JSIMMEDIATE) + linkSlowCase(iter); +#endif + emitPutJITStubArg(X86::eax, 1); + emitPutJITStubArg(X86::edx, 2); + emitCTICall(Interpreter::cti_op_stricteq); + emitPutVirtualRegister(currentInstruction[1].u.operand); + NEXT_OPCODE(op_stricteq); + } + case op_nstricteq: { + linkSlowCase(iter); + linkSlowCase(iter); +#if !USE(ALTERNATE_JSIMMEDIATE) + linkSlowCase(iter); +#endif + emitPutJITStubArg(X86::eax, 1); + emitPutJITStubArg(X86::edx, 2); + emitCTICall(Interpreter::cti_op_nstricteq); + emitPutVirtualRegister(currentInstruction[1].u.operand); + NEXT_OPCODE(op_nstricteq); + } + case op_instanceof: { + linkSlowCase(iter); + linkSlowCase(iter); + linkSlowCase(iter); + emitPutJITStubArgFromVirtualRegister(currentInstruction[2].u.operand, 1, X86::ecx); + emitPutJITStubArgFromVirtualRegister(currentInstruction[3].u.operand, 2, X86::ecx); + emitPutJITStubArgFromVirtualRegister(currentInstruction[4].u.operand, 3, X86::ecx); + emitCTICall(Interpreter::cti_op_instanceof); + emitPutVirtualRegister(currentInstruction[1].u.operand); + NEXT_OPCODE(op_instanceof); + } + case op_mod: { + compileFastArithSlow_op_mod(currentInstruction[1].u.operand, currentInstruction[2].u.operand, currentInstruction[3].u.operand, iter); + NEXT_OPCODE(op_mod); + } + case op_mul: { + compileFastArithSlow_op_mul(currentInstruction, iter); + NEXT_OPCODE(op_mul); + } + + case op_call: { + compileOpCallSlowCase(currentInstruction, iter, callLinkInfoIndex++, opcodeID); + NEXT_OPCODE(op_call); + } + case op_call_eval: { + compileOpCallSlowCase(currentInstruction, iter, callLinkInfoIndex++, opcodeID); + NEXT_OPCODE(op_call_eval); + } + case op_construct: { + compileOpCallSlowCase(currentInstruction, iter, callLinkInfoIndex++, opcodeID); + NEXT_OPCODE(op_construct); + } + case op_to_jsnumber: { + linkSlowCaseIfNotJSCell(iter, currentInstruction[2].u.operand); + linkSlowCase(iter); + + emitPutJITStubArg(X86::eax, 1); + emitCTICall(Interpreter::cti_op_to_jsnumber); + + emitPutVirtualRegister(currentInstruction[1].u.operand); + NEXT_OPCODE(op_to_jsnumber); + } + + default: + ASSERT_NOT_REACHED(); + } + + ASSERT_WITH_MESSAGE(iter == m_slowCases.end() || firstTo != iter->to,"Not enough jumps linked in slow case codegen."); + ASSERT_WITH_MESSAGE(firstTo == (iter - 1)->to, "Too many jumps linked in slow case codegen."); + + emitJumpSlowToHot(jump(), 0); + } + +#if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS) + ASSERT(propertyAccessInstructionIndex == m_codeBlock->numberOfStructureStubInfos()); +#endif + ASSERT(callLinkInfoIndex == m_codeBlock->numberOfCallLinkInfos()); + +#ifndef NDEBUG + // reset this, in order to guard it's use with asserts + m_bytecodeIndex = (unsigned)-1; +#endif +} + +void JIT::privateCompile() +{ + sampleCodeBlock(m_codeBlock); +#if ENABLE(OPCODE_SAMPLING) + sampleInstruction(m_codeBlock->instructions().begin()); +#endif + + // Could use a pop_m, but would need to offset the following instruction if so. + pop(X86::ecx); + emitPutToCallFrameHeader(X86::ecx, RegisterFile::ReturnPC); + + Jump slowRegisterFileCheck; + Label afterRegisterFileCheck; + if (m_codeBlock->codeType() == FunctionCode) { + // In the case of a fast linked call, we do not set this up in the caller. + emitPutImmediateToCallFrameHeader(m_codeBlock, RegisterFile::CodeBlock); + + emitGetCTIParam(STUB_ARGS_registerFile, X86::eax); + addPtr(Imm32(m_codeBlock->m_numCalleeRegisters * sizeof(Register)), callFrameRegister, X86::edx); + + slowRegisterFileCheck = jg32(X86::edx, Address(X86::eax, FIELD_OFFSET(RegisterFile, m_end))); + afterRegisterFileCheck = label(); + } + + privateCompileMainPass(); + privateCompileLinkPass(); + privateCompileSlowCases(); + + if (m_codeBlock->codeType() == FunctionCode) { + slowRegisterFileCheck.link(this); + m_bytecodeIndex = 0; // emitCTICall will add to the map, but doesn't actually need this... + emitCTICall(Interpreter::cti_register_file_check); +#ifndef NDEBUG + // reset this, in order to guard it's use with asserts + m_bytecodeIndex = (unsigned)-1; +#endif + jump(afterRegisterFileCheck); + } + + ASSERT(m_jmpTable.isEmpty()); + + RefPtr<ExecutablePool> allocator = m_globalData->poolForSize(m_assembler.size()); + void* code = m_assembler.executableCopy(allocator.get()); + JITCodeRef codeRef(code, allocator); +#ifndef NDEBUG + codeRef.codeSize = m_assembler.size(); +#endif + + PatchBuffer patchBuffer(code); + + // Translate vPC offsets into addresses in JIT generated code, for switch tables. + for (unsigned i = 0; i < m_switches.size(); ++i) { + SwitchRecord record = m_switches[i]; + unsigned bytecodeIndex = record.bytecodeIndex; + + if (record.type != SwitchRecord::String) { + ASSERT(record.type == SwitchRecord::Immediate || record.type == SwitchRecord::Character); + ASSERT(record.jumpTable.simpleJumpTable->branchOffsets.size() == record.jumpTable.simpleJumpTable->ctiOffsets.size()); + + record.jumpTable.simpleJumpTable->ctiDefault = patchBuffer.addressOf(m_labels[bytecodeIndex + 3 + record.defaultOffset]); + + for (unsigned j = 0; j < record.jumpTable.simpleJumpTable->branchOffsets.size(); ++j) { + unsigned offset = record.jumpTable.simpleJumpTable->branchOffsets[j]; + record.jumpTable.simpleJumpTable->ctiOffsets[j] = offset ? patchBuffer.addressOf(m_labels[bytecodeIndex + 3 + offset]) : record.jumpTable.simpleJumpTable->ctiDefault; + } + } else { + ASSERT(record.type == SwitchRecord::String); + + record.jumpTable.stringJumpTable->ctiDefault = patchBuffer.addressOf(m_labels[bytecodeIndex + 3 + record.defaultOffset]); + + StringJumpTable::StringOffsetTable::iterator end = record.jumpTable.stringJumpTable->offsetTable.end(); + for (StringJumpTable::StringOffsetTable::iterator it = record.jumpTable.stringJumpTable->offsetTable.begin(); it != end; ++it) { + unsigned offset = it->second.branchOffset; + it->second.ctiOffset = offset ? patchBuffer.addressOf(m_labels[bytecodeIndex + 3 + offset]) : record.jumpTable.stringJumpTable->ctiDefault; + } + } + } + + for (size_t i = 0; i < m_codeBlock->numberOfExceptionHandlers(); ++i) { + HandlerInfo& handler = m_codeBlock->exceptionHandler(i); + handler.nativeCode = patchBuffer.addressOf(m_labels[handler.target]); + } + + for (Vector<CallRecord>::iterator iter = m_calls.begin(); iter != m_calls.end(); ++iter) { + if (iter->to) + patchBuffer.link(iter->from, iter->to); + } + + if (m_codeBlock->hasExceptionInfo()) { + m_codeBlock->pcVector().reserveCapacity(m_calls.size()); + for (Vector<CallRecord>::iterator iter = m_calls.begin(); iter != m_calls.end(); ++iter) + m_codeBlock->pcVector().append(PC(reinterpret_cast<void**>(patchBuffer.addressOf(iter->from)) - reinterpret_cast<void**>(code), iter->bytecodeIndex)); + } + + // Link absolute addresses for jsr + for (Vector<JSRInfo>::iterator iter = m_jsrSites.begin(); iter != m_jsrSites.end(); ++iter) + patchBuffer.setPtr(iter->storeLocation, patchBuffer.addressOf(iter->target)); + + for (unsigned i = 0; i < m_codeBlock->numberOfStructureStubInfos(); ++i) { + StructureStubInfo& info = m_codeBlock->structureStubInfo(i); +#if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS) + info.callReturnLocation = patchBuffer.addressOf(m_propertyAccessCompilationInfo[i].callReturnLocation); + info.hotPathBegin = patchBuffer.addressOf(m_propertyAccessCompilationInfo[i].hotPathBegin); +#else + info.callReturnLocation = 0; + info.hotPathBegin = 0; +#endif + } + for (unsigned i = 0; i < m_codeBlock->numberOfCallLinkInfos(); ++i) { + CallLinkInfo& info = m_codeBlock->callLinkInfo(i); +#if ENABLE(JIT_OPTIMIZE_CALL) + info.callReturnLocation = patchBuffer.addressOf(m_callStructureStubCompilationInfo[i].callReturnLocation); + info.hotPathBegin = patchBuffer.addressOf(m_callStructureStubCompilationInfo[i].hotPathBegin); + info.hotPathOther = patchBuffer.addressOf(m_callStructureStubCompilationInfo[i].hotPathOther); + info.coldPathOther = patchBuffer.addressOf(m_callStructureStubCompilationInfo[i].coldPathOther); +#else + info.callReturnLocation = 0; + info.hotPathBegin = 0; + info.hotPathOther = 0; + info.coldPathOther = 0; +#endif + } + + m_codeBlock->setJITCode(codeRef); +} + +void JIT::privateCompileCTIMachineTrampolines() +{ +#if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS) + // (1) The first function provides fast property access for array length + Label arrayLengthBegin = align(); + + // Check eax is an array + Jump array_failureCases1 = emitJumpIfNotJSCell(X86::eax); + Jump array_failureCases2 = jnePtr(Address(X86::eax), ImmPtr(m_interpreter->m_jsArrayVptr)); + + // Checks out okay! - get the length from the storage + loadPtr(Address(X86::eax, FIELD_OFFSET(JSArray, m_storage)), X86::eax); + load32(Address(X86::eax, FIELD_OFFSET(ArrayStorage, m_length)), X86::eax); + + Jump array_failureCases3 = ja32(X86::eax, Imm32(JSImmediate::maxImmediateInt)); + + // X86::eax contains a 64 bit value (is positive, is zero extended) so we don't need sign extend here. + emitFastArithIntToImmNoCheck(X86::eax, X86::eax); + + ret(); + + // (2) The second function provides fast property access for string length + Label stringLengthBegin = align(); + + // Check eax is a string + Jump string_failureCases1 = emitJumpIfNotJSCell(X86::eax); + Jump string_failureCases2 = jnePtr(Address(X86::eax), ImmPtr(m_interpreter->m_jsStringVptr)); + + // Checks out okay! - get the length from the Ustring. + loadPtr(Address(X86::eax, FIELD_OFFSET(JSString, m_value) + FIELD_OFFSET(UString, m_rep)), X86::eax); + load32(Address(X86::eax, FIELD_OFFSET(UString::Rep, len)), X86::eax); + + Jump string_failureCases3 = ja32(X86::eax, Imm32(JSImmediate::maxImmediateInt)); + + // X86::eax contains a 64 bit value (is positive, is zero extended) so we don't need sign extend here. + emitFastArithIntToImmNoCheck(X86::eax, X86::eax); + + ret(); +#endif + + // (3) Trampolines for the slow cases of op_call / op_call_eval / op_construct. + + Label virtualCallPreLinkBegin = align(); + + // Load the callee CodeBlock* into eax + loadPtr(Address(X86::ecx, FIELD_OFFSET(JSFunction, m_body)), X86::eax); + loadPtr(Address(X86::eax, FIELD_OFFSET(FunctionBodyNode, m_code)), X86::eax); + Jump hasCodeBlock1 = jnzPtr(X86::eax); + pop(X86::ebx); + restoreArgumentReference(); + Jump callJSFunction1 = call(); + emitGetJITStubArg(1, X86::ecx); + emitGetJITStubArg(3, X86::edx); + push(X86::ebx); + hasCodeBlock1.link(this); + + // Check argCount matches callee arity. + Jump arityCheckOkay1 = je32(Address(X86::eax, FIELD_OFFSET(CodeBlock, m_numParameters)), X86::edx); + pop(X86::ebx); + emitPutJITStubArg(X86::ebx, 2); + emitPutJITStubArg(X86::eax, 4); + restoreArgumentReference(); + Jump callArityCheck1 = call(); + move(X86::edx, callFrameRegister); + emitGetJITStubArg(1, X86::ecx); + emitGetJITStubArg(3, X86::edx); + push(X86::ebx); + arityCheckOkay1.link(this); + + compileOpCallInitializeCallFrame(); + + pop(X86::ebx); + emitPutJITStubArg(X86::ebx, 2); + restoreArgumentReference(); + Jump callDontLazyLinkCall = call(); + push(X86::ebx); + + jump(X86::eax); + + Label virtualCallLinkBegin = align(); + + // Load the callee CodeBlock* into eax + loadPtr(Address(X86::ecx, FIELD_OFFSET(JSFunction, m_body)), X86::eax); + loadPtr(Address(X86::eax, FIELD_OFFSET(FunctionBodyNode, m_code)), X86::eax); + Jump hasCodeBlock2 = jnzPtr(X86::eax); + pop(X86::ebx); + restoreArgumentReference(); + Jump callJSFunction2 = call(); + emitGetJITStubArg(1, X86::ecx); + emitGetJITStubArg(3, X86::edx); + push(X86::ebx); + hasCodeBlock2.link(this); + + // Check argCount matches callee arity. + Jump arityCheckOkay2 = je32(Address(X86::eax, FIELD_OFFSET(CodeBlock, m_numParameters)), X86::edx); + pop(X86::ebx); + emitPutJITStubArg(X86::ebx, 2); + emitPutJITStubArg(X86::eax, 4); + restoreArgumentReference(); + Jump callArityCheck2 = call(); + move(X86::edx, callFrameRegister); + emitGetJITStubArg(1, X86::ecx); + emitGetJITStubArg(3, X86::edx); + push(X86::ebx); + arityCheckOkay2.link(this); + + compileOpCallInitializeCallFrame(); + + pop(X86::ebx); + emitPutJITStubArg(X86::ebx, 2); + restoreArgumentReference(); + Jump callLazyLinkCall = call(); + push(X86::ebx); + + jump(X86::eax); + + Label virtualCallBegin = align(); + + // Load the callee CodeBlock* into eax + loadPtr(Address(X86::ecx, FIELD_OFFSET(JSFunction, m_body)), X86::eax); + loadPtr(Address(X86::eax, FIELD_OFFSET(FunctionBodyNode, m_code)), X86::eax); + Jump hasCodeBlock3 = jnzPtr(X86::eax); + pop(X86::ebx); + restoreArgumentReference(); + Jump callJSFunction3 = call(); + emitGetJITStubArg(1, X86::ecx); + emitGetJITStubArg(3, X86::edx); + push(X86::ebx); + hasCodeBlock3.link(this); + + // Check argCount matches callee arity. + Jump arityCheckOkay3 = je32(Address(X86::eax, FIELD_OFFSET(CodeBlock, m_numParameters)), X86::edx); + pop(X86::ebx); + emitPutJITStubArg(X86::ebx, 2); + emitPutJITStubArg(X86::eax, 4); + restoreArgumentReference(); + Jump callArityCheck3 = call(); + move(X86::edx, callFrameRegister); + emitGetJITStubArg(1, X86::ecx); + emitGetJITStubArg(3, X86::edx); + push(X86::ebx); + arityCheckOkay3.link(this); + + compileOpCallInitializeCallFrame(); + + // load ctiCode from the new codeBlock. + loadPtr(Address(X86::eax, FIELD_OFFSET(CodeBlock, m_jitCode)), X86::eax); + + jump(X86::eax); + + // All trampolines constructed! copy the code, link up calls, and set the pointers on the Machine object. + m_interpreter->m_executablePool = m_globalData->poolForSize(m_assembler.size()); + void* code = m_assembler.executableCopy(m_interpreter->m_executablePool.get()); + PatchBuffer patchBuffer(code); + +#if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS) + patchBuffer.link(array_failureCases1, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_array_fail)); + patchBuffer.link(array_failureCases2, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_array_fail)); + patchBuffer.link(array_failureCases3, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_array_fail)); + patchBuffer.link(string_failureCases1, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_string_fail)); + patchBuffer.link(string_failureCases2, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_string_fail)); + patchBuffer.link(string_failureCases3, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_string_fail)); + + m_interpreter->m_ctiArrayLengthTrampoline = patchBuffer.addressOf(arrayLengthBegin); + m_interpreter->m_ctiStringLengthTrampoline = patchBuffer.addressOf(stringLengthBegin); +#endif + patchBuffer.link(callArityCheck1, reinterpret_cast<void*>(Interpreter::cti_op_call_arityCheck)); + patchBuffer.link(callArityCheck2, reinterpret_cast<void*>(Interpreter::cti_op_call_arityCheck)); + patchBuffer.link(callArityCheck3, reinterpret_cast<void*>(Interpreter::cti_op_call_arityCheck)); + patchBuffer.link(callJSFunction1, reinterpret_cast<void*>(Interpreter::cti_op_call_JSFunction)); + patchBuffer.link(callJSFunction2, reinterpret_cast<void*>(Interpreter::cti_op_call_JSFunction)); + patchBuffer.link(callJSFunction3, reinterpret_cast<void*>(Interpreter::cti_op_call_JSFunction)); + patchBuffer.link(callDontLazyLinkCall, reinterpret_cast<void*>(Interpreter::cti_vm_dontLazyLinkCall)); + patchBuffer.link(callLazyLinkCall, reinterpret_cast<void*>(Interpreter::cti_vm_lazyLinkCall)); + + m_interpreter->m_ctiVirtualCallPreLink = patchBuffer.addressOf(virtualCallPreLinkBegin); + m_interpreter->m_ctiVirtualCallLink = patchBuffer.addressOf(virtualCallLinkBegin); + m_interpreter->m_ctiVirtualCall = patchBuffer.addressOf(virtualCallBegin); +} + +void JIT::emitGetVariableObjectRegister(RegisterID variableObject, int index, RegisterID dst) +{ + loadPtr(Address(variableObject, FIELD_OFFSET(JSVariableObject, d)), dst); + loadPtr(Address(dst, FIELD_OFFSET(JSVariableObject::JSVariableObjectData, registers)), dst); + loadPtr(Address(dst, index * sizeof(Register)), dst); +} + +void JIT::emitPutVariableObjectRegister(RegisterID src, RegisterID variableObject, int index) +{ + loadPtr(Address(variableObject, FIELD_OFFSET(JSVariableObject, d)), variableObject); + loadPtr(Address(variableObject, FIELD_OFFSET(JSVariableObject::JSVariableObjectData, registers)), variableObject); + storePtr(src, Address(variableObject, index * sizeof(Register))); +} + +} // namespace JSC + +#endif // ENABLE(JIT) diff --git a/JavaScriptCore/jit/JIT.h b/JavaScriptCore/jit/JIT.h new file mode 100644 index 0000000..d13fbb5 --- /dev/null +++ b/JavaScriptCore/jit/JIT.h @@ -0,0 +1,577 @@ +/* + * 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 JIT_h +#define JIT_h + +#include <wtf/Platform.h> +#include <bytecode/SamplingTool.h> + +#if ENABLE(JIT) + +#define WTF_USE_CTI_REPATCH_PIC 1 + +#include "Interpreter.h" +#include "Opcode.h" +#include "RegisterFile.h" +#include "MacroAssembler.h" +#include "Profiler.h" +#include <wtf/AlwaysInline.h> +#include <wtf/Vector.h> + +#if PLATFORM(X86_64) +#define STUB_ARGS_offset 0x10 +#else +#define STUB_ARGS_offset 0x0C +#endif + +#define STUB_ARGS_code (STUB_ARGS_offset) +#define STUB_ARGS_registerFile (STUB_ARGS_offset + 1) +#define STUB_ARGS_callFrame (STUB_ARGS_offset + 2) +#define STUB_ARGS_exception (STUB_ARGS_offset + 3) +#define STUB_ARGS_profilerReference (STUB_ARGS_offset + 4) +#define STUB_ARGS_globalData (STUB_ARGS_offset + 5) + +#define ARG_callFrame static_cast<CallFrame*>(ARGS[STUB_ARGS_callFrame]) +#define ARG_registerFile static_cast<RegisterFile*>(ARGS[STUB_ARGS_registerFile]) +#define ARG_exception static_cast<JSValuePtr*>(ARGS[STUB_ARGS_exception]) +#define ARG_profilerReference static_cast<Profiler**>(ARGS[STUB_ARGS_profilerReference]) +#define ARG_globalData static_cast<JSGlobalData*>(ARGS[STUB_ARGS_globalData]) + +#define ARG_setCallFrame(newCallFrame) (ARGS[STUB_ARGS_callFrame] = (newCallFrame)) + +#define ARG_src1 JSValuePtr::decode(static_cast<JSValueEncodedAsPointer*>(ARGS[1])) +#define ARG_src2 JSValuePtr::decode(static_cast<JSValueEncodedAsPointer*>(ARGS[2])) +#define ARG_src3 JSValuePtr::decode(static_cast<JSValueEncodedAsPointer*>(ARGS[3])) +#define ARG_src4 JSValuePtr::decode(static_cast<JSValueEncodedAsPointer*>(ARGS[4])) +#define ARG_src5 JSValuePtr::decode(static_cast<JSValueEncodedAsPointer*>(ARGS[5])) +#define ARG_id1 static_cast<Identifier*>(ARGS[1]) +#define ARG_id2 static_cast<Identifier*>(ARGS[2]) +#define ARG_id3 static_cast<Identifier*>(ARGS[3]) +#define ARG_id4 static_cast<Identifier*>(ARGS[4]) +#define ARG_int1 static_cast<int32_t>(reinterpret_cast<intptr_t>(ARGS[1])) +#define ARG_int2 static_cast<int32_t>(reinterpret_cast<intptr_t>(ARGS[2])) +#define ARG_int3 static_cast<int32_t>(reinterpret_cast<intptr_t>(ARGS[3])) +#define ARG_int4 static_cast<int32_t>(reinterpret_cast<intptr_t>(ARGS[4])) +#define ARG_int5 static_cast<int32_t>(reinterpret_cast<intptr_t>(ARGS[5])) +#define ARG_int6 static_cast<int32_t>(reinterpret_cast<intptr_t>(ARGS[6])) +#define ARG_func1 static_cast<FuncDeclNode*>(ARGS[1]) +#define ARG_funcexp1 static_cast<FuncExprNode*>(ARGS[1]) +#define ARG_regexp1 static_cast<RegExp*>(ARGS[1]) +#define ARG_pni1 static_cast<JSPropertyNameIterator*>(ARGS[1]) +#define ARG_returnAddress2 static_cast<void*>(ARGS[2]) +#define ARG_codeBlock4 static_cast<CodeBlock*>(ARGS[4]) + +#define STUB_RETURN_ADDRESS_SLOT (ARGS[-1]) + +namespace JSC { + + class CodeBlock; + class JSPropertyNameIterator; + class Interpreter; + class Register; + class RegisterFile; + class ScopeChainNode; + class SimpleJumpTable; + class StringJumpTable; + class StructureChain; + + struct CallLinkInfo; + struct Instruction; + struct OperandTypes; + struct PolymorphicAccessStructureList; + struct StructureStubInfo; + + typedef JSValueEncodedAsPointer* (JIT_STUB *CTIHelper_j)(STUB_ARGS); + typedef JSObject* (JIT_STUB *CTIHelper_o)(STUB_ARGS); + typedef JSPropertyNameIterator* (JIT_STUB *CTIHelper_p)(STUB_ARGS); + typedef void (JIT_STUB *CTIHelper_v)(STUB_ARGS); + typedef void* (JIT_STUB *CTIHelper_s)(STUB_ARGS); + typedef int (JIT_STUB *CTIHelper_b)(STUB_ARGS); + typedef VoidPtrPair (JIT_STUB *CTIHelper_2)(STUB_ARGS); + + struct CallRecord { + MacroAssembler::Jump from; + unsigned bytecodeIndex; + void* to; + + CallRecord() + { + } + + CallRecord(MacroAssembler::Jump from, unsigned bytecodeIndex, void* to = 0) + : from(from) + , bytecodeIndex(bytecodeIndex) + , to(to) + { + } + }; + + struct JumpTable { + MacroAssembler::Jump from; + unsigned toBytecodeIndex; + + JumpTable(MacroAssembler::Jump f, unsigned t) + : from(f) + , toBytecodeIndex(t) + { + } + }; + + struct SlowCaseEntry { + MacroAssembler::Jump from; + unsigned to; + unsigned hint; + + SlowCaseEntry(MacroAssembler::Jump f, unsigned t, unsigned h = 0) + : from(f) + , to(t) + , hint(h) + { + } + }; + + struct SwitchRecord { + enum Type { + Immediate, + Character, + String + }; + + Type type; + + union { + SimpleJumpTable* simpleJumpTable; + StringJumpTable* stringJumpTable; + } jumpTable; + + unsigned bytecodeIndex; + unsigned defaultOffset; + + SwitchRecord(SimpleJumpTable* jumpTable, unsigned bytecodeIndex, unsigned defaultOffset, Type type) + : type(type) + , bytecodeIndex(bytecodeIndex) + , defaultOffset(defaultOffset) + { + this->jumpTable.simpleJumpTable = jumpTable; + } + + SwitchRecord(StringJumpTable* jumpTable, unsigned bytecodeIndex, unsigned defaultOffset) + : type(String) + , bytecodeIndex(bytecodeIndex) + , defaultOffset(defaultOffset) + { + this->jumpTable.stringJumpTable = jumpTable; + } + }; + + struct PropertyStubCompilationInfo { + MacroAssembler::Jump callReturnLocation; + MacroAssembler::Label hotPathBegin; + }; + + struct StructureStubCompilationInfo { + MacroAssembler::DataLabelPtr hotPathBegin; + MacroAssembler::Jump hotPathOther; + MacroAssembler::Jump callReturnLocation; + MacroAssembler::Label coldPathOther; + }; + + extern "C" { + JSValueEncodedAsPointer* ctiTrampoline( +#if PLATFORM(X86_64) + // FIXME: (bug #22910) this will force all arguments onto the stack (regparm(0) does not appear to have any effect). + // We can allow register passing here, and move the writes of these values into the trampoline. + void*, void*, void*, void*, void*, void*, +#endif + void* code, RegisterFile*, CallFrame*, JSValuePtr* exception, Profiler**, JSGlobalData*); + void ctiVMThrowTrampoline(); + }; + + void ctiSetReturnAddress(void** where, void* what); + void ctiPatchCallByReturnAddress(void* where, void* what); + + class JIT : private MacroAssembler { + using MacroAssembler::Jump; + using MacroAssembler::JumpList; + using MacroAssembler::Label; + +#if PLATFORM(X86_64) + static const RegisterID timeoutCheckRegister = X86::r12; + static const RegisterID callFrameRegister = X86::r13; + static const RegisterID tagTypeNumberRegister = X86::r14; + static const RegisterID tagMaskRegister = X86::r15; +#else + static const RegisterID timeoutCheckRegister = X86::esi; + static const RegisterID callFrameRegister = X86::edi; +#endif + + static const int patchGetByIdDefaultStructure = -1; + // Magic number - initial offset cannot be representable as a signed 8bit value, or the X86Assembler + // will compress the displacement, and we may not be able to fit a patched offset. + static const int patchGetByIdDefaultOffset = 256; + +#if USE(JIT_STUB_ARGUMENT_REGISTER) +#if PLATFORM(X86_64) + static const int ctiArgumentInitSize = 6; +#else + static const int ctiArgumentInitSize = 2; +#endif +#elif USE(JIT_STUB_ARGUMENT_STACK) + static const int ctiArgumentInitSize = 4; +#else // JIT_STUB_ARGUMENT_VA_LIST + static const int ctiArgumentInitSize = 0; +#endif + +#if PLATFORM(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 = 31; + static const int patchOffsetGetByIdPutResult = 31; +#if ENABLE(OPCODE_SAMPLING) + static const int patchOffsetGetByIdSlowCaseCall = 53 + ctiArgumentInitSize; +#else + static const int patchOffsetGetByIdSlowCaseCall = 30 + ctiArgumentInitSize; +#endif + static const int patchOffsetOpCallCompareToJump = 9; +#else + // 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 = 31 + ctiArgumentInitSize; +#else + static const int patchOffsetGetByIdSlowCaseCall = 21 + ctiArgumentInitSize; +#endif + static const int patchOffsetOpCallCompareToJump = 6; +#endif + + public: + static void compile(JSGlobalData* globalData, CodeBlock* codeBlock) + { + JIT jit(globalData, codeBlock); + jit.privateCompile(); + } + + static void compileGetByIdSelf(JSGlobalData* globalData, CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* structure, size_t cachedOffset, void* returnAddress) + { + JIT jit(globalData, codeBlock); + jit.privateCompileGetByIdSelf(stubInfo, structure, cachedOffset, returnAddress); + } + + static void compileGetByIdProto(JSGlobalData* globalData, CallFrame* callFrame, CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* structure, Structure* prototypeStructure, size_t cachedOffset, void* returnAddress) + { + JIT jit(globalData, codeBlock); + jit.privateCompileGetByIdProto(stubInfo, structure, prototypeStructure, cachedOffset, returnAddress, callFrame); + } + +#if USE(CTI_REPATCH_PIC) + static void compileGetByIdSelfList(JSGlobalData* globalData, CodeBlock* codeBlock, StructureStubInfo* stubInfo, PolymorphicAccessStructureList* polymorphicStructures, int currentIndex, Structure* structure, size_t cachedOffset) + { + JIT jit(globalData, codeBlock); + jit.privateCompileGetByIdSelfList(stubInfo, polymorphicStructures, currentIndex, structure, cachedOffset); + } + static void compileGetByIdProtoList(JSGlobalData* globalData, CallFrame* callFrame, CodeBlock* codeBlock, StructureStubInfo* stubInfo, PolymorphicAccessStructureList* prototypeStructureList, int currentIndex, Structure* structure, Structure* prototypeStructure, size_t cachedOffset) + { + JIT jit(globalData, codeBlock); + jit.privateCompileGetByIdProtoList(stubInfo, prototypeStructureList, currentIndex, structure, prototypeStructure, cachedOffset, callFrame); + } + static void compileGetByIdChainList(JSGlobalData* globalData, CallFrame* callFrame, CodeBlock* codeBlock, StructureStubInfo* stubInfo, PolymorphicAccessStructureList* prototypeStructureList, int currentIndex, Structure* structure, StructureChain* chain, size_t count, size_t cachedOffset) + { + JIT jit(globalData, codeBlock); + jit.privateCompileGetByIdChainList(stubInfo, prototypeStructureList, currentIndex, structure, chain, count, cachedOffset, callFrame); + } +#endif + + static void compileGetByIdChain(JSGlobalData* globalData, CallFrame* callFrame, CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* structure, StructureChain* chain, size_t count, size_t cachedOffset, void* returnAddress) + { + JIT jit(globalData, codeBlock); + jit.privateCompileGetByIdChain(stubInfo, structure, chain, count, cachedOffset, returnAddress, callFrame); + } + + static void compilePutByIdReplace(JSGlobalData* globalData, CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* structure, size_t cachedOffset, void* returnAddress) + { + JIT jit(globalData, codeBlock); + jit.privateCompilePutByIdReplace(stubInfo, structure, cachedOffset, returnAddress); + } + + static void compilePutByIdTransition(JSGlobalData* globalData, CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* oldStructure, Structure* newStructure, size_t cachedOffset, StructureChain* chain, void* returnAddress) + { + JIT jit(globalData, codeBlock); + jit.privateCompilePutByIdTransition(stubInfo, oldStructure, newStructure, cachedOffset, chain, returnAddress); + } + + static void compileCTIMachineTrampolines(JSGlobalData* globalData) + { + JIT jit(globalData); + jit.privateCompileCTIMachineTrampolines(); + } + + static void patchGetByIdSelf(StructureStubInfo*, Structure*, size_t cachedOffset, void* returnAddress); + static void patchPutByIdReplace(StructureStubInfo*, Structure*, size_t cachedOffset, void* returnAddress); + + static void compilePatchGetArrayLength(JSGlobalData* globalData, CodeBlock* codeBlock, void* returnAddress) + { + JIT jit(globalData, codeBlock); + return jit.privateCompilePatchGetArrayLength(returnAddress); + } + + static void linkCall(JSFunction* callee, CodeBlock* calleeCodeBlock, void* ctiCode, CallLinkInfo* callLinkInfo, int callerArgCount); + static void unlinkCall(CallLinkInfo*); + + inline static JSValuePtr execute(void* code, RegisterFile* registerFile, CallFrame* callFrame, JSGlobalData* globalData, JSValuePtr* exception) + { + return JSValuePtr::decode(ctiTrampoline( +#if PLATFORM(X86_64) + 0, 0, 0, 0, 0, 0, +#endif + code, registerFile, callFrame, exception, Profiler::enabledProfilerReference(), globalData)); + } + + private: + JIT(JSGlobalData*, CodeBlock* = 0); + + void privateCompileMainPass(); + void privateCompileLinkPass(); + void privateCompileSlowCases(); + void privateCompile(); + void privateCompileGetByIdSelf(StructureStubInfo*, Structure*, size_t cachedOffset, void* returnAddress); + void privateCompileGetByIdProto(StructureStubInfo*, Structure*, Structure* prototypeStructure, size_t cachedOffset, void* returnAddress, CallFrame* callFrame); +#if USE(CTI_REPATCH_PIC) + void privateCompileGetByIdSelfList(StructureStubInfo*, PolymorphicAccessStructureList*, int, Structure*, size_t cachedOffset); + void privateCompileGetByIdProtoList(StructureStubInfo*, PolymorphicAccessStructureList*, int, Structure*, Structure* prototypeStructure, size_t cachedOffset, CallFrame* callFrame); + void privateCompileGetByIdChainList(StructureStubInfo*, PolymorphicAccessStructureList*, int, Structure*, StructureChain* chain, size_t count, size_t cachedOffset, CallFrame* callFrame); +#endif + void privateCompileGetByIdChain(StructureStubInfo*, Structure*, StructureChain*, size_t count, size_t cachedOffset, void* returnAddress, CallFrame* callFrame); + void privateCompilePutByIdReplace(StructureStubInfo*, Structure*, size_t cachedOffset, void* returnAddress); + void privateCompilePutByIdTransition(StructureStubInfo*, Structure*, Structure*, size_t cachedOffset, StructureChain*, void* returnAddress); + + void privateCompileCTIMachineTrampolines(); + void privateCompilePatchGetArrayLength(void* returnAddress); + + void addSlowCase(Jump); + void addJump(Jump, int); + void emitJumpSlowToHot(Jump, int); + + void compileGetByIdHotPath(int resultVReg, int baseVReg, Identifier* ident, unsigned propertyAccessInstructionIndex); + void compileGetByIdSlowCase(int resultVReg, int baseVReg, Identifier* ident, Vector<SlowCaseEntry>::iterator& iter, unsigned propertyAccessInstructionIndex); + void compilePutByIdHotPath(int baseVReg, Identifier* ident, int valueVReg, unsigned propertyAccessInstructionIndex); + void compilePutByIdSlowCase(int baseVReg, Identifier* ident, int valueVReg, Vector<SlowCaseEntry>::iterator& iter, unsigned propertyAccessInstructionIndex); + void compileOpCall(OpcodeID, Instruction* instruction, unsigned callLinkInfoIndex); + void compileOpCallInitializeCallFrame(); + void compileOpCallSetupArgs(Instruction*); + void compileOpCallEvalSetupArgs(Instruction*); + void compileOpCallSlowCase(Instruction* instruction, Vector<SlowCaseEntry>::iterator& iter, unsigned callLinkInfoIndex, OpcodeID opcodeID); + void compileOpConstructSetupArgs(Instruction*); + enum CompileOpStrictEqType { OpStrictEq, OpNStrictEq }; + void compileOpStrictEq(Instruction* instruction, CompileOpStrictEqType type); + void putDoubleResultToJSNumberCellOrJSImmediate(X86Assembler::XMMRegisterID xmmSource, RegisterID jsNumberCell, unsigned dst, X86Assembler::JmpSrc* wroteJSNumberCell, X86Assembler::XMMRegisterID tempXmm, RegisterID tempReg1, RegisterID tempReg2); + + void compileFastArith_op_add(Instruction*); + void compileFastArith_op_sub(Instruction*); + void compileFastArith_op_mul(Instruction*); + void compileFastArith_op_mod(unsigned result, unsigned op1, unsigned op2); + void compileFastArith_op_bitand(unsigned result, unsigned op1, unsigned op2); + void compileFastArith_op_lshift(unsigned result, unsigned op1, unsigned op2); + void compileFastArith_op_rshift(unsigned result, unsigned op1, unsigned op2); + void compileFastArith_op_pre_inc(unsigned srcDst); + void compileFastArith_op_pre_dec(unsigned srcDst); + void compileFastArith_op_post_inc(unsigned result, unsigned srcDst); + void compileFastArith_op_post_dec(unsigned result, unsigned srcDst); + void compileFastArithSlow_op_add(Instruction*, Vector<SlowCaseEntry>::iterator&); + void compileFastArithSlow_op_sub(Instruction*, Vector<SlowCaseEntry>::iterator&); + void compileFastArithSlow_op_mul(Instruction*, Vector<SlowCaseEntry>::iterator&); + void compileFastArithSlow_op_mod(unsigned result, unsigned op1, unsigned op2, Vector<SlowCaseEntry>::iterator&); + void compileFastArithSlow_op_bitand(unsigned result, unsigned op1, unsigned op2, Vector<SlowCaseEntry>::iterator&); + void compileFastArithSlow_op_lshift(unsigned result, unsigned op1, unsigned op2, Vector<SlowCaseEntry>::iterator&); + void compileFastArithSlow_op_rshift(unsigned result, unsigned op1, unsigned op2, Vector<SlowCaseEntry>::iterator&); + void compileFastArithSlow_op_pre_inc(unsigned srcDst, Vector<SlowCaseEntry>::iterator&); + void compileFastArithSlow_op_pre_dec(unsigned srcDst, Vector<SlowCaseEntry>::iterator&); + void compileFastArithSlow_op_post_inc(unsigned result, unsigned srcDst, Vector<SlowCaseEntry>::iterator&); + void compileFastArithSlow_op_post_dec(unsigned result, unsigned srcDst, Vector<SlowCaseEntry>::iterator&); +#if ENABLE(JIT_OPTIMIZE_ARITHMETIC) + void compileBinaryArithOp(OpcodeID, unsigned dst, unsigned src1, unsigned src2, OperandTypes opi); + void compileBinaryArithOpSlowCase(OpcodeID, Vector<SlowCaseEntry>::iterator&, unsigned dst, unsigned src1, unsigned src2, OperandTypes opi); +#endif + + void emitGetVirtualRegister(int src, RegisterID dst); + void emitGetVirtualRegisters(int src1, RegisterID dst1, int src2, RegisterID dst2); + void emitPutVirtualRegister(unsigned dst, RegisterID from = X86::eax); + + void emitPutJITStubArg(RegisterID src, unsigned argumentNumber); + void emitPutJITStubArgFromVirtualRegister(unsigned src, unsigned argumentNumber, RegisterID scratch); + void emitPutJITStubArgConstant(unsigned value, unsigned argumentNumber); + void emitPutJITStubArgConstant(void* value, unsigned argumentNumber); + void emitGetJITStubArg(unsigned argumentNumber, RegisterID dst); + + void emitInitRegister(unsigned dst); + + void emitPutCTIParam(void* value, unsigned name); + void emitPutCTIParam(RegisterID from, unsigned name); + void emitGetCTIParam(unsigned name, RegisterID to); + + void emitPutToCallFrameHeader(RegisterID from, RegisterFile::CallFrameHeaderEntry entry); + void emitPutImmediateToCallFrameHeader(void* value, RegisterFile::CallFrameHeaderEntry entry); + void emitGetFromCallFrameHeader(RegisterFile::CallFrameHeaderEntry entry, RegisterID to); + + JSValuePtr getConstantOperand(unsigned src); + int32_t getConstantOperandImmediateInt(unsigned src); + bool isOperandConstantImmediateInt(unsigned src); + + Jump emitJumpIfJSCell(RegisterID); + Jump emitJumpIfBothJSCells(RegisterID, RegisterID, RegisterID); + void emitJumpSlowCaseIfJSCell(RegisterID); + Jump emitJumpIfNotJSCell(RegisterID); + void emitJumpSlowCaseIfNotJSCell(RegisterID); + void emitJumpSlowCaseIfNotJSCell(RegisterID, int VReg); +#if USE(ALTERNATE_JSIMMEDIATE) + JIT::Jump emitJumpIfImmediateNumber(RegisterID); + JIT::Jump emitJumpIfNotImmediateNumber(RegisterID); +#endif + + Jump getSlowCase(Vector<SlowCaseEntry>::iterator& iter) + { + return iter++->from; + } + void linkSlowCase(Vector<SlowCaseEntry>::iterator& iter) + { + iter->from.link(this); + ++iter; + } + void linkSlowCaseIfNotJSCell(Vector<SlowCaseEntry>::iterator&, int vReg); + + JIT::Jump emitJumpIfImmediateInteger(RegisterID); + JIT::Jump emitJumpIfNotImmediateInteger(RegisterID); + JIT::Jump emitJumpIfNotImmediateIntegers(RegisterID, RegisterID, RegisterID); + void emitJumpSlowCaseIfNotImmediateInteger(RegisterID); + void emitJumpSlowCaseIfNotImmediateIntegers(RegisterID, RegisterID, RegisterID); + + Jump checkStructure(RegisterID reg, Structure* structure); + +#if !USE(ALTERNATE_JSIMMEDIATE) + void emitFastArithDeTagImmediate(RegisterID); + Jump emitFastArithDeTagImmediateJumpIfZero(RegisterID); +#endif + void emitFastArithReTagImmediate(RegisterID src, RegisterID dest); + void emitFastArithImmToInt(RegisterID); + void emitFastArithIntToImmNoCheck(RegisterID src, RegisterID dest); + + void emitTagAsBoolImmediate(RegisterID reg); + + void restoreArgumentReference(); + void restoreArgumentReferenceForTrampoline(); + + Jump emitNakedCall(RegisterID); + Jump emitNakedCall(void* function); + Jump emitCTICall_internal(void*); + Jump emitCTICall(CTIHelper_j helper) { return emitCTICall_internal(reinterpret_cast<void*>(helper)); } + Jump emitCTICall(CTIHelper_o helper) { return emitCTICall_internal(reinterpret_cast<void*>(helper)); } + Jump emitCTICall(CTIHelper_p helper) { return emitCTICall_internal(reinterpret_cast<void*>(helper)); } + Jump emitCTICall(CTIHelper_v helper) { return emitCTICall_internal(reinterpret_cast<void*>(helper)); } + Jump emitCTICall(CTIHelper_s helper) { return emitCTICall_internal(reinterpret_cast<void*>(helper)); } + Jump emitCTICall(CTIHelper_b helper) { return emitCTICall_internal(reinterpret_cast<void*>(helper)); } + Jump emitCTICall(CTIHelper_2 helper) { return emitCTICall_internal(reinterpret_cast<void*>(helper)); } + + void emitGetVariableObjectRegister(RegisterID variableObject, int index, RegisterID dst); + void emitPutVariableObjectRegister(RegisterID src, RegisterID variableObject, int index); + + void emitSlowScriptCheck(); +#ifndef NDEBUG + void printBytecodeOperandTypes(unsigned src1, unsigned src2); +#endif + + void killLastResultRegister(); + +#if ENABLE(CODEBLOCK_SAMPLING) + void sampleCodeBlock(CodeBlock* codeBlock) + { +#if PLATFORM(X86_64) + move(ImmPtr(m_interpreter->sampler()->codeBlockSlot()), X86::ecx); + storePtr(ImmPtr(codeBlock), X86::ecx); +#else + storePtr(ImmPtr(codeBlock), m_interpreter->sampler()->codeBlockSlot()); +#endif + } +#else + void sampleCodeBlock(CodeBlock*) {} +#endif + +#if ENABLE(OPCODE_SAMPLING) + void sampleInstruction(Instruction* instruction, bool inHostFunction=false) + { +#if PLATFORM(X86_64) + move(ImmPtr(m_interpreter->sampler()->sampleSlot()), X86::ecx); + storePtr(ImmPtr(m_interpreter->sampler()->encodeSample(instruction, inHostFunction)), X86::ecx); +#else + storePtr(ImmPtr(m_interpreter->sampler()->encodeSample(instruction, inHostFunction)), m_interpreter->sampler()->sampleSlot()); +#endif + } +#else + void sampleInstruction(Instruction*, bool) {} +#endif + + Interpreter* m_interpreter; + JSGlobalData* m_globalData; + CodeBlock* m_codeBlock; + + Vector<CallRecord> m_calls; + Vector<Label> m_labels; + Vector<PropertyStubCompilationInfo> m_propertyAccessCompilationInfo; + Vector<StructureStubCompilationInfo> m_callStructureStubCompilationInfo; + Vector<JumpTable> m_jmpTable; + + struct JSRInfo { + DataLabelPtr storeLocation; + Label target; + + JSRInfo(DataLabelPtr storeLocation, Label targetLocation) + : storeLocation(storeLocation) + , target(targetLocation) + { + } + }; + + unsigned m_bytecodeIndex; + Vector<JSRInfo> m_jsrSites; + Vector<SlowCaseEntry> m_slowCases; + Vector<SwitchRecord> m_switches; + + int m_lastResultBytecodeRegister; + unsigned m_jumpTargetsPosition; + }; +} + +#endif // ENABLE(JIT) + +#endif // JIT_h diff --git a/JavaScriptCore/jit/JITArithmetic.cpp b/JavaScriptCore/jit/JITArithmetic.cpp new file mode 100644 index 0000000..0a3e9ab --- /dev/null +++ b/JavaScriptCore/jit/JITArithmetic.cpp @@ -0,0 +1,974 @@ +/* + * Copyright (C) 2008 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "JIT.h" + +#if ENABLE(JIT) + +#include "CodeBlock.h" +#include "JITInlineMethods.h" +#include "JSArray.h" +#include "JSFunction.h" +#include "Interpreter.h" +#include "ResultType.h" +#include "SamplingTool.h" + +#ifndef NDEBUG +#include <stdio.h> +#endif + +#define __ m_assembler. + +using namespace std; + +namespace JSC { + +void JIT::compileFastArith_op_lshift(unsigned result, unsigned op1, unsigned op2) +{ + emitGetVirtualRegisters(op1, X86::eax, op2, X86::ecx); + // FIXME: would we be better using 'emitJumpSlowCaseIfNotImmediateIntegers'? - we *probably* ought to be consistent. + emitJumpSlowCaseIfNotImmediateInteger(X86::eax); + emitJumpSlowCaseIfNotImmediateInteger(X86::ecx); + emitFastArithImmToInt(X86::eax); + emitFastArithImmToInt(X86::ecx); +#if !PLATFORM(X86) + // Mask with 0x1f as per ecma-262 11.7.2 step 7. + // On 32-bit x86 this is not necessary, since the shift anount is implicitly masked in the instruction. + and32(Imm32(0x1f), X86::ecx); +#endif + lshift32(X86::ecx, X86::eax); +#if !USE(ALTERNATE_JSIMMEDIATE) + addSlowCase(joAdd32(X86::eax, X86::eax)); + signExtend32ToPtr(X86::eax, X86::eax); +#endif + emitFastArithReTagImmediate(X86::eax, X86::eax); + emitPutVirtualRegister(result); +} +void JIT::compileFastArithSlow_op_lshift(unsigned result, unsigned op1, unsigned op2, Vector<SlowCaseEntry>::iterator& iter) +{ +#if USE(ALTERNATE_JSIMMEDIATE) + UNUSED_PARAM(op1); + UNUSED_PARAM(op2); + linkSlowCase(iter); + linkSlowCase(iter); +#else + // If we are limited to 32-bit immediates there is a third slow case, which required the operands to have been reloaded. + Jump notImm1 = getSlowCase(iter); + Jump notImm2 = getSlowCase(iter); + linkSlowCase(iter); + emitGetVirtualRegisters(op1, X86::eax, op2, X86::ecx); + notImm1.link(this); + notImm2.link(this); +#endif + emitPutJITStubArg(X86::eax, 1); + emitPutJITStubArg(X86::ecx, 2); + emitCTICall(Interpreter::cti_op_lshift); + emitPutVirtualRegister(result); +} + +void JIT::compileFastArith_op_rshift(unsigned result, unsigned op1, unsigned op2) +{ + if (isOperandConstantImmediateInt(op2)) { + emitGetVirtualRegister(op1, X86::eax); + emitJumpSlowCaseIfNotImmediateInteger(X86::eax); + // Mask with 0x1f as per ecma-262 11.7.2 step 7. +#if USE(ALTERNATE_JSIMMEDIATE) + rshift32(Imm32(getConstantOperandImmediateInt(op2) & 0x1f), X86::eax); +#else + rshiftPtr(Imm32(getConstantOperandImmediateInt(op2) & 0x1f), X86::eax); +#endif + } else { + emitGetVirtualRegisters(op1, X86::eax, op2, X86::ecx); + emitJumpSlowCaseIfNotImmediateInteger(X86::eax); + emitJumpSlowCaseIfNotImmediateInteger(X86::ecx); + emitFastArithImmToInt(X86::ecx); +#if !PLATFORM(X86) + // Mask with 0x1f as per ecma-262 11.7.2 step 7. + // On 32-bit x86 this is not necessary, since the shift anount is implicitly masked in the instruction. + and32(Imm32(0x1f), X86::ecx); +#endif +#if USE(ALTERNATE_JSIMMEDIATE) + rshift32(X86::ecx, X86::eax); +#else + rshiftPtr(X86::ecx, X86::eax); +#endif + } +#if USE(ALTERNATE_JSIMMEDIATE) + emitFastArithIntToImmNoCheck(X86::eax, X86::eax); +#else + orPtr(Imm32(JSImmediate::TagTypeNumber), X86::eax); +#endif + emitPutVirtualRegister(result); +} +void JIT::compileFastArithSlow_op_rshift(unsigned result, unsigned, unsigned op2, Vector<SlowCaseEntry>::iterator& iter) +{ + linkSlowCase(iter); + if (isOperandConstantImmediateInt(op2)) + emitPutJITStubArgFromVirtualRegister(op2, 2, X86::ecx); + else { + linkSlowCase(iter); + emitPutJITStubArg(X86::ecx, 2); + } + + emitPutJITStubArg(X86::eax, 1); + emitCTICall(Interpreter::cti_op_rshift); + emitPutVirtualRegister(result); +} + +void JIT::compileFastArith_op_bitand(unsigned result, unsigned op1, unsigned op2) +{ + if (isOperandConstantImmediateInt(op1)) { + emitGetVirtualRegister(op2, X86::eax); + emitJumpSlowCaseIfNotImmediateInteger(X86::eax); +#if USE(ALTERNATE_JSIMMEDIATE) + int32_t imm = getConstantOperandImmediateInt(op1); + andPtr(Imm32(imm), X86::eax); + if (imm >= 0) + emitFastArithIntToImmNoCheck(X86::eax, X86::eax); +#else + andPtr(Imm32(static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op1)))), X86::eax); +#endif + } else if (isOperandConstantImmediateInt(op2)) { + emitGetVirtualRegister(op1, X86::eax); + emitJumpSlowCaseIfNotImmediateInteger(X86::eax); +#if USE(ALTERNATE_JSIMMEDIATE) + int32_t imm = getConstantOperandImmediateInt(op2); + andPtr(Imm32(imm), X86::eax); + if (imm >= 0) + emitFastArithIntToImmNoCheck(X86::eax, X86::eax); +#else + andPtr(Imm32(static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2)))), X86::eax); +#endif + } else { + emitGetVirtualRegisters(op1, X86::eax, op2, X86::edx); + andPtr(X86::edx, X86::eax); + emitJumpSlowCaseIfNotImmediateInteger(X86::eax); + } + emitPutVirtualRegister(result); +} +void JIT::compileFastArithSlow_op_bitand(unsigned result, unsigned op1, unsigned op2, Vector<SlowCaseEntry>::iterator& iter) +{ + linkSlowCase(iter); + if (isOperandConstantImmediateInt(op1)) { + emitPutJITStubArgFromVirtualRegister(op1, 1, X86::ecx); + emitPutJITStubArg(X86::eax, 2); + } else if (isOperandConstantImmediateInt(op2)) { + emitPutJITStubArg(X86::eax, 1); + emitPutJITStubArgFromVirtualRegister(op2, 2, X86::ecx); + } else { + emitPutJITStubArgFromVirtualRegister(op1, 1, X86::ecx); + emitPutJITStubArg(X86::edx, 2); + } + emitCTICall(Interpreter::cti_op_bitand); + emitPutVirtualRegister(result); +} + +void JIT::compileFastArith_op_mod(unsigned result, unsigned op1, unsigned op2) +{ + emitGetVirtualRegisters(op1, X86::eax, op2, X86::ecx); + emitJumpSlowCaseIfNotImmediateInteger(X86::eax); + emitJumpSlowCaseIfNotImmediateInteger(X86::ecx); +#if USE(ALTERNATE_JSIMMEDIATE) + addSlowCase(jePtr(X86::ecx, ImmPtr(JSValuePtr::encode(js0())))); + mod32(X86::ecx, X86::eax, X86::edx); +#else + emitFastArithDeTagImmediate(X86::eax); + addSlowCase(emitFastArithDeTagImmediateJumpIfZero(X86::ecx)); + mod32(X86::ecx, X86::eax, X86::edx); + signExtend32ToPtr(X86::edx, X86::edx); +#endif + emitFastArithReTagImmediate(X86::edx, X86::eax); + emitPutVirtualRegister(result); +} +void JIT::compileFastArithSlow_op_mod(unsigned result, unsigned, unsigned, Vector<SlowCaseEntry>::iterator& iter) +{ +#if USE(ALTERNATE_JSIMMEDIATE) + linkSlowCase(iter); + linkSlowCase(iter); + linkSlowCase(iter); +#else + Jump notImm1 = getSlowCase(iter); + Jump notImm2 = getSlowCase(iter); + linkSlowCase(iter); + emitFastArithReTagImmediate(X86::eax, X86::eax); + emitFastArithReTagImmediate(X86::ecx, X86::ecx); + notImm1.link(this); + notImm2.link(this); +#endif + emitPutJITStubArg(X86::eax, 1); + emitPutJITStubArg(X86::ecx, 2); + emitCTICall(Interpreter::cti_op_mod); + emitPutVirtualRegister(result); +} + +void JIT::compileFastArith_op_post_inc(unsigned result, unsigned srcDst) +{ + emitGetVirtualRegister(srcDst, X86::eax); + move(X86::eax, X86::edx); + emitJumpSlowCaseIfNotImmediateInteger(X86::eax); +#if USE(ALTERNATE_JSIMMEDIATE) + addSlowCase(joAdd32(Imm32(1), X86::edx)); + emitFastArithIntToImmNoCheck(X86::edx, X86::edx); +#else + addSlowCase(joAdd32(Imm32(1 << JSImmediate::IntegerPayloadShift), X86::edx)); + signExtend32ToPtr(X86::edx, X86::edx); +#endif + emitPutVirtualRegister(srcDst, X86::edx); + emitPutVirtualRegister(result); +} +void JIT::compileFastArithSlow_op_post_inc(unsigned result, unsigned srcDst, Vector<SlowCaseEntry>::iterator& iter) +{ + linkSlowCase(iter); + linkSlowCase(iter); + emitPutJITStubArg(X86::eax, 1); + emitCTICall(Interpreter::cti_op_post_inc); + emitPutVirtualRegister(srcDst, X86::edx); + emitPutVirtualRegister(result); +} + +void JIT::compileFastArith_op_post_dec(unsigned result, unsigned srcDst) +{ + emitGetVirtualRegister(srcDst, X86::eax); + move(X86::eax, X86::edx); + emitJumpSlowCaseIfNotImmediateInteger(X86::eax); +#if USE(ALTERNATE_JSIMMEDIATE) + addSlowCase(joSub32(Imm32(1), X86::edx)); + emitFastArithIntToImmNoCheck(X86::edx, X86::edx); +#else + addSlowCase(joSub32(Imm32(1 << JSImmediate::IntegerPayloadShift), X86::edx)); + signExtend32ToPtr(X86::edx, X86::edx); +#endif + emitPutVirtualRegister(srcDst, X86::edx); + emitPutVirtualRegister(result); +} +void JIT::compileFastArithSlow_op_post_dec(unsigned result, unsigned srcDst, Vector<SlowCaseEntry>::iterator& iter) +{ + linkSlowCase(iter); + linkSlowCase(iter); + emitPutJITStubArg(X86::eax, 1); + emitCTICall(Interpreter::cti_op_post_dec); + emitPutVirtualRegister(srcDst, X86::edx); + emitPutVirtualRegister(result); +} + +void JIT::compileFastArith_op_pre_inc(unsigned srcDst) +{ + emitGetVirtualRegister(srcDst, X86::eax); + emitJumpSlowCaseIfNotImmediateInteger(X86::eax); +#if USE(ALTERNATE_JSIMMEDIATE) + addSlowCase(joAdd32(Imm32(1), X86::eax)); + emitFastArithIntToImmNoCheck(X86::eax, X86::eax); +#else + addSlowCase(joAdd32(Imm32(1 << JSImmediate::IntegerPayloadShift), X86::eax)); + signExtend32ToPtr(X86::eax, X86::eax); +#endif + emitPutVirtualRegister(srcDst); +} +void JIT::compileFastArithSlow_op_pre_inc(unsigned srcDst, Vector<SlowCaseEntry>::iterator& iter) +{ + Jump notImm = getSlowCase(iter); + linkSlowCase(iter); + emitGetVirtualRegister(srcDst, X86::eax); + notImm.link(this); + emitPutJITStubArg(X86::eax, 1); + emitCTICall(Interpreter::cti_op_pre_inc); + emitPutVirtualRegister(srcDst); +} + +void JIT::compileFastArith_op_pre_dec(unsigned srcDst) +{ + emitGetVirtualRegister(srcDst, X86::eax); + emitJumpSlowCaseIfNotImmediateInteger(X86::eax); +#if USE(ALTERNATE_JSIMMEDIATE) + addSlowCase(joSub32(Imm32(1), X86::eax)); + emitFastArithIntToImmNoCheck(X86::eax, X86::eax); +#else + addSlowCase(joSub32(Imm32(1 << JSImmediate::IntegerPayloadShift), X86::eax)); + signExtend32ToPtr(X86::eax, X86::eax); +#endif + emitPutVirtualRegister(srcDst); +} +void JIT::compileFastArithSlow_op_pre_dec(unsigned srcDst, Vector<SlowCaseEntry>::iterator& iter) +{ + Jump notImm = getSlowCase(iter); + linkSlowCase(iter); + emitGetVirtualRegister(srcDst, X86::eax); + notImm.link(this); + emitPutJITStubArg(X86::eax, 1); + emitCTICall(Interpreter::cti_op_pre_dec); + emitPutVirtualRegister(srcDst); +} + + +#if !ENABLE(JIT_OPTIMIZE_ARITHMETIC) + +void JIT::compileFastArith_op_add(Instruction* currentInstruction) +{ + unsigned result = currentInstruction[1].u.operand; + unsigned op1 = currentInstruction[2].u.operand; + unsigned op2 = currentInstruction[3].u.operand; + + emitPutJITStubArgFromVirtualRegister(op1, 1, X86::ecx); + emitPutJITStubArgFromVirtualRegister(op2, 2, X86::ecx); + emitCTICall(Interpreter::cti_op_add); + emitPutVirtualRegister(result); +} +void JIT::compileFastArithSlow_op_add(Instruction*, Vector<SlowCaseEntry>::iterator&) +{ + ASSERT_NOT_REACHED(); +} + +void JIT::compileFastArith_op_mul(Instruction* currentInstruction) +{ + unsigned result = currentInstruction[1].u.operand; + unsigned op1 = currentInstruction[2].u.operand; + unsigned op2 = currentInstruction[3].u.operand; + + emitPutJITStubArgFromVirtualRegister(op1, 1, X86::ecx); + emitPutJITStubArgFromVirtualRegister(op2, 2, X86::ecx); + emitCTICall(Interpreter::cti_op_mul); + emitPutVirtualRegister(result); +} +void JIT::compileFastArithSlow_op_mul(Instruction*, Vector<SlowCaseEntry>::iterator&) +{ + ASSERT_NOT_REACHED(); +} + +void JIT::compileFastArith_op_sub(Instruction* currentInstruction) +{ + unsigned result = currentInstruction[1].u.operand; + unsigned op1 = currentInstruction[2].u.operand; + unsigned op2 = currentInstruction[3].u.operand; + + emitPutJITStubArgFromVirtualRegister(op1, 1, X86::ecx); + emitPutJITStubArgFromVirtualRegister(op2, 2, X86::ecx); + emitCTICall(Interpreter::cti_op_sub); + emitPutVirtualRegister(result); +} +void JIT::compileFastArithSlow_op_sub(Instruction*, Vector<SlowCaseEntry>::iterator&) +{ + ASSERT_NOT_REACHED(); +} + +#elif USE(ALTERNATE_JSIMMEDIATE) // *AND* ENABLE(JIT_OPTIMIZE_ARITHMETIC) + +void JIT::compileBinaryArithOp(OpcodeID opcodeID, unsigned, unsigned op1, unsigned op2, OperandTypes) +{ + emitGetVirtualRegisters(op1, X86::eax, op2, X86::edx); + emitJumpSlowCaseIfNotImmediateInteger(X86::eax); + emitJumpSlowCaseIfNotImmediateInteger(X86::edx); + if (opcodeID == op_add) + addSlowCase(joAdd32(X86::edx, X86::eax)); + else if (opcodeID == op_sub) + addSlowCase(joSub32(X86::edx, X86::eax)); + else { + ASSERT(opcodeID == op_mul); + addSlowCase(joMul32(X86::edx, X86::eax)); + addSlowCase(jz32(X86::eax)); + } + emitFastArithIntToImmNoCheck(X86::eax, X86::eax); +} + +void JIT::compileBinaryArithOpSlowCase(OpcodeID opcodeID, Vector<SlowCaseEntry>::iterator& iter, unsigned, unsigned op1, unsigned, OperandTypes types) +{ + // We assume that subtracting TagTypeNumber is equivalent to adding DoubleEncodeOffset. + COMPILE_ASSERT(((JSImmediate::TagTypeNumber + JSImmediate::DoubleEncodeOffset) == 0), TagTypeNumber_PLUS_DoubleEncodeOffset_EQUALS_0); + + Jump notImm1 = getSlowCase(iter); + Jump notImm2 = getSlowCase(iter); + + linkSlowCase(iter); // Integer overflow case - we could handle this in JIT code, but this is likely rare. + if (opcodeID == op_mul) // op_mul has an extra slow case to handle 0 * negative number. + linkSlowCase(iter); + emitGetVirtualRegister(op1, X86::eax); + + Label stubFunctionCall(this); + emitPutJITStubArg(X86::eax, 1); + emitPutJITStubArg(X86::edx, 2); + if (opcodeID == op_add) + emitCTICall(Interpreter::cti_op_add); + else if (opcodeID == op_sub) + emitCTICall(Interpreter::cti_op_sub); + else { + ASSERT(opcodeID == op_mul); + emitCTICall(Interpreter::cti_op_mul); + } + Jump end = jump(); + + // if we get here, eax is not an int32, edx not yet checked. + notImm1.link(this); + if (!types.first().definitelyIsNumber()) + emitJumpIfNotImmediateNumber(X86::eax).linkTo(stubFunctionCall, this); + if (!types.second().definitelyIsNumber()) + emitJumpIfNotImmediateNumber(X86::edx).linkTo(stubFunctionCall, this); + addPtr(tagTypeNumberRegister, X86::eax); + m_assembler.movq_rr(X86::eax, X86::xmm1); + Jump op2isDouble = emitJumpIfNotImmediateInteger(X86::edx); + m_assembler.cvtsi2sd_rr(X86::edx, X86::xmm2); + Jump op2wasInteger = jump(); + + // if we get here, eax IS an int32, edx is not. + notImm2.link(this); + if (!types.second().definitelyIsNumber()) + emitJumpIfNotImmediateNumber(X86::edx).linkTo(stubFunctionCall, this); + m_assembler.cvtsi2sd_rr(X86::eax, X86::xmm1); + op2isDouble.link(this); + addPtr(tagTypeNumberRegister, X86::edx); + m_assembler.movq_rr(X86::edx, X86::xmm2); + op2wasInteger.link(this); + + if (opcodeID == op_add) + m_assembler.addsd_rr(X86::xmm2, X86::xmm1); + else if (opcodeID == op_sub) + m_assembler.subsd_rr(X86::xmm2, X86::xmm1); + else { + ASSERT(opcodeID == op_mul); + m_assembler.mulsd_rr(X86::xmm2, X86::xmm1); + } + m_assembler.movq_rr(X86::xmm1, X86::eax); + subPtr(tagTypeNumberRegister, X86::eax); + + end.link(this); +} + +void JIT::compileFastArith_op_add(Instruction* currentInstruction) +{ + unsigned result = currentInstruction[1].u.operand; + unsigned op1 = currentInstruction[2].u.operand; + unsigned op2 = currentInstruction[3].u.operand; + OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand); + + if (!types.first().mightBeNumber() || !types.second().mightBeNumber()) { + emitPutJITStubArgFromVirtualRegister(op1, 1, X86::ecx); + emitPutJITStubArgFromVirtualRegister(op2, 2, X86::ecx); + emitCTICall(Interpreter::cti_op_add); + emitPutVirtualRegister(result); + return; + } + + if (isOperandConstantImmediateInt(op1)) { + emitGetVirtualRegister(op2, X86::eax); + emitJumpSlowCaseIfNotImmediateInteger(X86::eax); + addSlowCase(joAdd32(Imm32(getConstantOperandImmediateInt(op1)), X86::eax)); + emitFastArithIntToImmNoCheck(X86::eax, X86::eax); + } else if (isOperandConstantImmediateInt(op2)) { + emitGetVirtualRegister(op1, X86::eax); + emitJumpSlowCaseIfNotImmediateInteger(X86::eax); + addSlowCase(joAdd32(Imm32(getConstantOperandImmediateInt(op2)), X86::eax)); + emitFastArithIntToImmNoCheck(X86::eax, X86::eax); + } else + compileBinaryArithOp(op_add, result, op1, op2, types); + + emitPutVirtualRegister(result); +} +void JIT::compileFastArithSlow_op_add(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) +{ + unsigned result = currentInstruction[1].u.operand; + unsigned op1 = currentInstruction[2].u.operand; + unsigned op2 = currentInstruction[3].u.operand; + OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand); + + if (isOperandConstantImmediateInt(op1)) { + linkSlowCase(iter); + linkSlowCase(iter); + emitPutJITStubArgFromVirtualRegister(op1, 1, X86::ecx); + emitPutJITStubArgFromVirtualRegister(op2, 2, X86::ecx); + emitCTICall(Interpreter::cti_op_add); + } else if (isOperandConstantImmediateInt(op2)) { + linkSlowCase(iter); + linkSlowCase(iter); + emitPutJITStubArgFromVirtualRegister(op1, 1, X86::ecx); + emitPutJITStubArgFromVirtualRegister(op2, 2, X86::ecx); + emitCTICall(Interpreter::cti_op_add); + } else + compileBinaryArithOpSlowCase(op_add, iter, result, op1, op2, types); + + emitPutVirtualRegister(result); +} + +void JIT::compileFastArith_op_mul(Instruction* currentInstruction) +{ + unsigned result = currentInstruction[1].u.operand; + unsigned op1 = currentInstruction[2].u.operand; + unsigned op2 = currentInstruction[3].u.operand; + OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand); + + // For now, only plant a fast int case if the constant operand is greater than zero. + int32_t value; + if (isOperandConstantImmediateInt(op1) && ((value = getConstantOperandImmediateInt(op1)) > 0)) { + emitGetVirtualRegister(op2, X86::eax); + emitJumpSlowCaseIfNotImmediateInteger(X86::eax); + addSlowCase(joMul32(Imm32(value), X86::eax, X86::eax)); + emitFastArithReTagImmediate(X86::eax, X86::eax); + } else if (isOperandConstantImmediateInt(op2) && ((value = getConstantOperandImmediateInt(op2)) > 0)) { + emitGetVirtualRegister(op1, X86::eax); + emitJumpSlowCaseIfNotImmediateInteger(X86::eax); + addSlowCase(joMul32(Imm32(value), X86::eax, X86::eax)); + emitFastArithReTagImmediate(X86::eax, X86::eax); + } else + compileBinaryArithOp(op_mul, result, op1, op2, types); + + emitPutVirtualRegister(result); +} +void JIT::compileFastArithSlow_op_mul(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) +{ + unsigned result = currentInstruction[1].u.operand; + unsigned op1 = currentInstruction[2].u.operand; + unsigned op2 = currentInstruction[3].u.operand; + OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand); + + if ((isOperandConstantImmediateInt(op1) && (getConstantOperandImmediateInt(op1) > 0)) + || (isOperandConstantImmediateInt(op2) && (getConstantOperandImmediateInt(op2) > 0))) { + linkSlowCase(iter); + linkSlowCase(iter); + // There is an extra slow case for (op1 * -N) or (-N * op2), to check for 0 since this should produce a result of -0. + emitPutJITStubArgFromVirtualRegister(op1, 1, X86::ecx); + emitPutJITStubArgFromVirtualRegister(op2, 2, X86::ecx); + emitCTICall(Interpreter::cti_op_mul); + } else + compileBinaryArithOpSlowCase(op_mul, iter, result, op1, op2, types); + + emitPutVirtualRegister(result); +} + +void JIT::compileFastArith_op_sub(Instruction* currentInstruction) +{ + unsigned result = currentInstruction[1].u.operand; + unsigned op1 = currentInstruction[2].u.operand; + unsigned op2 = currentInstruction[3].u.operand; + OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand); + + compileBinaryArithOp(op_sub, result, op1, op2, types); + + emitPutVirtualRegister(result); +} +void JIT::compileFastArithSlow_op_sub(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) +{ + unsigned result = currentInstruction[1].u.operand; + unsigned op1 = currentInstruction[2].u.operand; + unsigned op2 = currentInstruction[3].u.operand; + OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand); + + compileBinaryArithOpSlowCase(op_sub, iter, result, op1, op2, types); + + emitPutVirtualRegister(result); +} + +#else + +typedef X86Assembler::JmpSrc JmpSrc; +typedef X86Assembler::JmpDst JmpDst; +typedef X86Assembler::XMMRegisterID XMMRegisterID; + +#if PLATFORM(MAC) + +static inline bool isSSE2Present() +{ + return true; // All X86 Macs are guaranteed to support at least SSE2 +} + +#else + +static bool isSSE2Present() +{ + static const int SSE2FeatureBit = 1 << 26; + struct SSE2Check { + SSE2Check() + { + int flags; +#if COMPILER(MSVC) + _asm { + mov eax, 1 // cpuid function 1 gives us the standard feature set + cpuid; + mov flags, edx; + } +#else + flags = 0; + // FIXME: Add GCC code to do above asm +#endif + present = (flags & SSE2FeatureBit) != 0; + } + bool present; + }; + static SSE2Check check; + return check.present; +} + +#endif + +/* + This is required since number representation is canonical - values representable as a JSImmediate should not be stored in a JSNumberCell. + + In the common case, the double value from 'xmmSource' is written to the reusable JSNumberCell pointed to by 'jsNumberCell', then 'jsNumberCell' + is written to the output SF Register 'dst', and then a jump is planted (stored into *wroteJSNumberCell). + + However if the value from xmmSource is representable as a JSImmediate, then the JSImmediate value will be written to the output, and flow + control will fall through from the code planted. +*/ +void JIT::putDoubleResultToJSNumberCellOrJSImmediate(X86::XMMRegisterID xmmSource, X86::RegisterID jsNumberCell, unsigned dst, JmpSrc* wroteJSNumberCell, X86::XMMRegisterID tempXmm, X86::RegisterID tempReg1, X86::RegisterID tempReg2) +{ + // convert (double -> JSImmediate -> double), and check if the value is unchanged - in which case the value is representable as a JSImmediate. + __ cvttsd2si_rr(xmmSource, tempReg1); + __ addl_rr(tempReg1, tempReg1); + __ sarl_i8r(1, tempReg1); + __ cvtsi2sd_rr(tempReg1, tempXmm); + // Compare & branch if immediate. + __ ucomisd_rr(tempXmm, xmmSource); + JmpSrc resultIsImm = __ je(); + JmpDst resultLookedLikeImmButActuallyIsnt = __ label(); + + // Store the result to the JSNumberCell and jump. + __ movsd_rm(xmmSource, FIELD_OFFSET(JSNumberCell, m_value), jsNumberCell); + if (jsNumberCell != X86::eax) + __ movl_rr(jsNumberCell, X86::eax); + emitPutVirtualRegister(dst); + *wroteJSNumberCell = __ jmp(); + + __ link(resultIsImm, __ label()); + // value == (double)(JSImmediate)value... or at least, it looks that way... + // ucomi will report that (0 == -0), and will report true if either input in NaN (result is unordered). + __ link(__ jp(), resultLookedLikeImmButActuallyIsnt); // Actually was a NaN + __ pextrw_irr(3, xmmSource, tempReg2); + __ cmpl_ir(0x8000, tempReg2); + __ link(__ je(), resultLookedLikeImmButActuallyIsnt); // Actually was -0 + // Yes it really really really is representable as a JSImmediate. + emitFastArithIntToImmNoCheck(tempReg1, X86::eax); + emitPutVirtualRegister(dst); +} + +void JIT::compileBinaryArithOp(OpcodeID opcodeID, unsigned dst, unsigned src1, unsigned src2, OperandTypes types) +{ + Structure* numberStructure = m_globalData->numberStructure.get(); + JmpSrc wasJSNumberCell1; + JmpSrc wasJSNumberCell1b; + JmpSrc wasJSNumberCell2; + JmpSrc wasJSNumberCell2b; + + emitGetVirtualRegisters(src1, X86::eax, src2, X86::edx); + + if (types.second().isReusable() && isSSE2Present()) { + ASSERT(types.second().mightBeNumber()); + + // Check op2 is a number + __ testl_i32r(JSImmediate::TagTypeNumber, X86::edx); + JmpSrc op2imm = __ jne(); + if (!types.second().definitelyIsNumber()) { + emitJumpSlowCaseIfNotJSCell(X86::edx, src2); + __ cmpl_im(reinterpret_cast<unsigned>(numberStructure), FIELD_OFFSET(JSCell, m_structure), X86::edx); + addSlowCase(__ jne()); + } + + // (1) In this case src2 is a reusable number cell. + // Slow case if src1 is not a number type. + __ testl_i32r(JSImmediate::TagTypeNumber, X86::eax); + JmpSrc op1imm = __ jne(); + if (!types.first().definitelyIsNumber()) { + emitJumpSlowCaseIfNotJSCell(X86::eax, src1); + __ cmpl_im(reinterpret_cast<unsigned>(numberStructure), FIELD_OFFSET(JSCell, m_structure), X86::eax); + addSlowCase(__ jne()); + } + + // (1a) if we get here, src1 is also a number cell + __ movsd_mr(FIELD_OFFSET(JSNumberCell, m_value), X86::eax, X86::xmm0); + JmpSrc loadedDouble = __ jmp(); + // (1b) if we get here, src1 is an immediate + __ link(op1imm, __ label()); + emitFastArithImmToInt(X86::eax); + __ cvtsi2sd_rr(X86::eax, X86::xmm0); + // (1c) + __ link(loadedDouble, __ label()); + if (opcodeID == op_add) + __ addsd_mr(FIELD_OFFSET(JSNumberCell, m_value), X86::edx, X86::xmm0); + else if (opcodeID == op_sub) + __ subsd_mr(FIELD_OFFSET(JSNumberCell, m_value), X86::edx, X86::xmm0); + else { + ASSERT(opcodeID == op_mul); + __ mulsd_mr(FIELD_OFFSET(JSNumberCell, m_value), X86::edx, X86::xmm0); + } + + putDoubleResultToJSNumberCellOrJSImmediate(X86::xmm0, X86::edx, dst, &wasJSNumberCell2, X86::xmm1, X86::ecx, X86::eax); + wasJSNumberCell2b = __ jmp(); + + // (2) This handles cases where src2 is an immediate number. + // Two slow cases - either src1 isn't an immediate, or the subtract overflows. + __ link(op2imm, __ label()); + emitJumpSlowCaseIfNotImmediateInteger(X86::eax); + } else if (types.first().isReusable() && isSSE2Present()) { + ASSERT(types.first().mightBeNumber()); + + // Check op1 is a number + __ testl_i32r(JSImmediate::TagTypeNumber, X86::eax); + JmpSrc op1imm = __ jne(); + if (!types.first().definitelyIsNumber()) { + emitJumpSlowCaseIfNotJSCell(X86::eax, src1); + __ cmpl_im(reinterpret_cast<unsigned>(numberStructure), FIELD_OFFSET(JSCell, m_structure), X86::eax); + addSlowCase(__ jne()); + } + + // (1) In this case src1 is a reusable number cell. + // Slow case if src2 is not a number type. + __ testl_i32r(JSImmediate::TagTypeNumber, X86::edx); + JmpSrc op2imm = __ jne(); + if (!types.second().definitelyIsNumber()) { + emitJumpSlowCaseIfNotJSCell(X86::edx, src2); + __ cmpl_im(reinterpret_cast<unsigned>(numberStructure), FIELD_OFFSET(JSCell, m_structure), X86::edx); + addSlowCase(__ jne()); + } + + // (1a) if we get here, src2 is also a number cell + __ movsd_mr(FIELD_OFFSET(JSNumberCell, m_value), X86::edx, X86::xmm1); + JmpSrc loadedDouble = __ jmp(); + // (1b) if we get here, src2 is an immediate + __ link(op2imm, __ label()); + emitFastArithImmToInt(X86::edx); + __ cvtsi2sd_rr(X86::edx, X86::xmm1); + // (1c) + __ link(loadedDouble, __ label()); + __ movsd_mr(FIELD_OFFSET(JSNumberCell, m_value), X86::eax, X86::xmm0); + if (opcodeID == op_add) + __ addsd_rr(X86::xmm1, X86::xmm0); + else if (opcodeID == op_sub) + __ subsd_rr(X86::xmm1, X86::xmm0); + else { + ASSERT(opcodeID == op_mul); + __ mulsd_rr(X86::xmm1, X86::xmm0); + } + __ movsd_rm(X86::xmm0, FIELD_OFFSET(JSNumberCell, m_value), X86::eax); + emitPutVirtualRegister(dst); + + putDoubleResultToJSNumberCellOrJSImmediate(X86::xmm0, X86::eax, dst, &wasJSNumberCell1, X86::xmm1, X86::ecx, X86::edx); + wasJSNumberCell1b = __ jmp(); + + // (2) This handles cases where src1 is an immediate number. + // Two slow cases - either src2 isn't an immediate, or the subtract overflows. + __ link(op1imm, __ label()); + emitJumpSlowCaseIfNotImmediateInteger(X86::edx); + } else + emitJumpSlowCaseIfNotImmediateIntegers(X86::eax, X86::edx, X86::ecx); + + if (opcodeID == op_add) { + emitFastArithDeTagImmediate(X86::eax); + __ addl_rr(X86::edx, X86::eax); + addSlowCase(__ jo()); + } else if (opcodeID == op_sub) { + __ subl_rr(X86::edx, X86::eax); + addSlowCase(__ jo()); + signExtend32ToPtr(X86::eax, X86::eax); + emitFastArithReTagImmediate(X86::eax, X86::eax); + } else { + ASSERT(opcodeID == op_mul); + // convert eax & edx from JSImmediates to ints, and check if either are zero + emitFastArithImmToInt(X86::edx); + JmpSrc op1Zero = emitFastArithDeTagImmediateJumpIfZero(X86::eax); + __ testl_rr(X86::edx, X86::edx); + JmpSrc op2NonZero = __ jne(); + __ link(op1Zero, __ label()); + // if either input is zero, add the two together, and check if the result is < 0. + // If it is, we have a problem (N < 0), (N * 0) == -0, not representatble as a JSImmediate. + __ movl_rr(X86::eax, X86::ecx); + __ addl_rr(X86::edx, X86::ecx); + addSlowCase(__ js()); + // Skip the above check if neither input is zero + __ link(op2NonZero, __ label()); + __ imull_rr(X86::edx, X86::eax); + addSlowCase(__ jo()); + signExtend32ToPtr(X86::eax, X86::eax); + emitFastArithReTagImmediate(X86::eax, X86::eax); + } + emitPutVirtualRegister(dst); + + if (types.second().isReusable() && isSSE2Present()) { + __ link(wasJSNumberCell2, __ label()); + __ link(wasJSNumberCell2b, __ label()); + } + else if (types.first().isReusable() && isSSE2Present()) { + __ link(wasJSNumberCell1, __ label()); + __ link(wasJSNumberCell1b, __ label()); + } +} + +void JIT::compileBinaryArithOpSlowCase(OpcodeID opcodeID, Vector<SlowCaseEntry>::iterator& iter, unsigned dst, unsigned src1, unsigned src2, OperandTypes types) +{ + linkSlowCase(iter); + if (types.second().isReusable() && isSSE2Present()) { + if (!types.first().definitelyIsNumber()) { + linkSlowCaseIfNotJSCell(iter, src1); + linkSlowCase(iter); + } + if (!types.second().definitelyIsNumber()) { + linkSlowCaseIfNotJSCell(iter, src2); + linkSlowCase(iter); + } + } else if (types.first().isReusable() && isSSE2Present()) { + if (!types.first().definitelyIsNumber()) { + linkSlowCaseIfNotJSCell(iter, src1); + linkSlowCase(iter); + } + if (!types.second().definitelyIsNumber()) { + linkSlowCaseIfNotJSCell(iter, src2); + linkSlowCase(iter); + } + } + linkSlowCase(iter); + + // additional entry point to handle -0 cases. + if (opcodeID == op_mul) + linkSlowCase(iter); + + emitPutJITStubArgFromVirtualRegister(src1, 1, X86::ecx); + emitPutJITStubArgFromVirtualRegister(src2, 2, X86::ecx); + if (opcodeID == op_add) + emitCTICall(Interpreter::cti_op_add); + else if (opcodeID == op_sub) + emitCTICall(Interpreter::cti_op_sub); + else { + ASSERT(opcodeID == op_mul); + emitCTICall(Interpreter::cti_op_mul); + } + emitPutVirtualRegister(dst); +} + +void JIT::compileFastArith_op_add(Instruction* currentInstruction) +{ + unsigned result = currentInstruction[1].u.operand; + unsigned op1 = currentInstruction[2].u.operand; + unsigned op2 = currentInstruction[3].u.operand; + + if (isOperandConstantImmediateInt(op1)) { + emitGetVirtualRegister(op2, X86::eax); + emitJumpSlowCaseIfNotImmediateInteger(X86::eax); + addSlowCase(joAdd32(Imm32(getConstantOperandImmediateInt(op1) << JSImmediate::IntegerPayloadShift), X86::eax)); + signExtend32ToPtr(X86::eax, X86::eax); + emitPutVirtualRegister(result); + } else if (isOperandConstantImmediateInt(op2)) { + emitGetVirtualRegister(op1, X86::eax); + emitJumpSlowCaseIfNotImmediateInteger(X86::eax); + addSlowCase(joAdd32(Imm32(getConstantOperandImmediateInt(op2) << JSImmediate::IntegerPayloadShift), X86::eax)); + signExtend32ToPtr(X86::eax, X86::eax); + emitPutVirtualRegister(result); + } else { + OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand); + if (types.first().mightBeNumber() && types.second().mightBeNumber()) + compileBinaryArithOp(op_add, result, op1, op2, OperandTypes::fromInt(currentInstruction[4].u.operand)); + else { + emitPutJITStubArgFromVirtualRegister(op1, 1, X86::ecx); + emitPutJITStubArgFromVirtualRegister(op2, 2, X86::ecx); + emitCTICall(Interpreter::cti_op_add); + emitPutVirtualRegister(result); + } + } +} +void JIT::compileFastArithSlow_op_add(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) +{ + unsigned result = currentInstruction[1].u.operand; + unsigned op1 = currentInstruction[2].u.operand; + unsigned op2 = currentInstruction[3].u.operand; + + if (isOperandConstantImmediateInt(op1)) { + Jump notImm = getSlowCase(iter); + linkSlowCase(iter); + sub32(Imm32(getConstantOperandImmediateInt(op1) << JSImmediate::IntegerPayloadShift), X86::eax); + notImm.link(this); + emitPutJITStubArgFromVirtualRegister(op1, 1, X86::ecx); + emitPutJITStubArg(X86::eax, 2); + emitCTICall(Interpreter::cti_op_add); + emitPutVirtualRegister(result); + } else if (isOperandConstantImmediateInt(op2)) { + Jump notImm = getSlowCase(iter); + linkSlowCase(iter); + sub32(Imm32(getConstantOperandImmediateInt(op2) << JSImmediate::IntegerPayloadShift), X86::eax); + notImm.link(this); + emitPutJITStubArg(X86::eax, 1); + emitPutJITStubArgFromVirtualRegister(op2, 2, X86::ecx); + emitCTICall(Interpreter::cti_op_add); + emitPutVirtualRegister(result); + } else { + OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand); + ASSERT(types.first().mightBeNumber() && types.second().mightBeNumber()); + compileBinaryArithOpSlowCase(op_add, iter, result, op1, op2, types); + } +} + +void JIT::compileFastArith_op_mul(Instruction* currentInstruction) +{ + unsigned result = currentInstruction[1].u.operand; + unsigned op1 = currentInstruction[2].u.operand; + unsigned op2 = currentInstruction[3].u.operand; + + // For now, only plant a fast int case if the constant operand is greater than zero. + int32_t value; + if (isOperandConstantImmediateInt(op1) && ((value = getConstantOperandImmediateInt(op1)) > 0)) { + emitGetVirtualRegister(op2, X86::eax); + emitJumpSlowCaseIfNotImmediateInteger(X86::eax); + emitFastArithDeTagImmediate(X86::eax); + addSlowCase(joMul32(Imm32(value), X86::eax, X86::eax)); + signExtend32ToPtr(X86::eax, X86::eax); + emitFastArithReTagImmediate(X86::eax, X86::eax); + emitPutVirtualRegister(result); + } else if (isOperandConstantImmediateInt(op2) && ((value = getConstantOperandImmediateInt(op2)) > 0)) { + emitGetVirtualRegister(op1, X86::eax); + emitJumpSlowCaseIfNotImmediateInteger(X86::eax); + emitFastArithDeTagImmediate(X86::eax); + addSlowCase(joMul32(Imm32(value), X86::eax, X86::eax)); + signExtend32ToPtr(X86::eax, X86::eax); + emitFastArithReTagImmediate(X86::eax, X86::eax); + emitPutVirtualRegister(result); + } else + compileBinaryArithOp(op_mul, result, op1, op2, OperandTypes::fromInt(currentInstruction[4].u.operand)); +} +void JIT::compileFastArithSlow_op_mul(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) +{ + unsigned result = currentInstruction[1].u.operand; + unsigned op1 = currentInstruction[2].u.operand; + unsigned op2 = currentInstruction[3].u.operand; + + if ((isOperandConstantImmediateInt(op1) && (getConstantOperandImmediateInt(op1) > 0)) + || (isOperandConstantImmediateInt(op2) && (getConstantOperandImmediateInt(op2) > 0))) { + linkSlowCase(iter); + linkSlowCase(iter); + // There is an extra slow case for (op1 * -N) or (-N * op2), to check for 0 since this should produce a result of -0. + emitPutJITStubArgFromVirtualRegister(op1, 1, X86::ecx); + emitPutJITStubArgFromVirtualRegister(op2, 2, X86::ecx); + emitCTICall(Interpreter::cti_op_mul); + emitPutVirtualRegister(result); + } else + compileBinaryArithOpSlowCase(op_mul, iter, result, op1, op2, OperandTypes::fromInt(currentInstruction[4].u.operand)); +} + +void JIT::compileFastArith_op_sub(Instruction* currentInstruction) +{ + compileBinaryArithOp(op_sub, currentInstruction[1].u.operand, currentInstruction[2].u.operand, currentInstruction[3].u.operand, OperandTypes::fromInt(currentInstruction[4].u.operand)); +} +void JIT::compileFastArithSlow_op_sub(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) +{ + compileBinaryArithOpSlowCase(op_sub, iter, currentInstruction[1].u.operand, currentInstruction[2].u.operand, currentInstruction[3].u.operand, OperandTypes::fromInt(currentInstruction[4].u.operand)); +} + +#endif + +} // namespace JSC + +#endif // ENABLE(JIT) diff --git a/JavaScriptCore/jit/JITCall.cpp b/JavaScriptCore/jit/JITCall.cpp new file mode 100644 index 0000000..af26712 --- /dev/null +++ b/JavaScriptCore/jit/JITCall.cpp @@ -0,0 +1,345 @@ +/* + * Copyright (C) 2008 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "JIT.h" + +#if ENABLE(JIT) + +#include "CodeBlock.h" +#include "JITInlineMethods.h" +#include "JSArray.h" +#include "JSFunction.h" +#include "Interpreter.h" +#include "ResultType.h" +#include "SamplingTool.h" + +#ifndef NDEBUG +#include <stdio.h> +#endif + +using namespace std; + +namespace JSC { + +void JIT::unlinkCall(CallLinkInfo* callLinkInfo) +{ + // When the JSFunction is deleted the pointer embedded in the instruction stream will no longer be valid + // (and, if a new JSFunction happened to be constructed at the same location, we could get a false positive + // match). Reset the check so it no longer matches. + DataLabelPtr::patch(callLinkInfo->hotPathBegin, JSValuePtr::encode(jsImpossibleValue())); +} + +void JIT::linkCall(JSFunction* callee, CodeBlock* calleeCodeBlock, void* ctiCode, CallLinkInfo* callLinkInfo, int callerArgCount) +{ + // Currently we only link calls with the exact number of arguments. + if (callerArgCount == calleeCodeBlock->m_numParameters) { + ASSERT(!callLinkInfo->isLinked()); + + calleeCodeBlock->addCaller(callLinkInfo); + + DataLabelPtr::patch(callLinkInfo->hotPathBegin, callee); + Jump::patch(callLinkInfo->hotPathOther, ctiCode); + } + + // patch the instruction that jumps out to the cold path, so that we only try to link once. + void* patchCheck = reinterpret_cast<void*>(reinterpret_cast<ptrdiff_t>(callLinkInfo->hotPathBegin) + patchOffsetOpCallCompareToJump); + Jump::patch(patchCheck, callLinkInfo->coldPathOther); +} + +void JIT::compileOpCallInitializeCallFrame() +{ + store32(X86::edx, Address(callFrameRegister, RegisterFile::ArgumentCount * static_cast<int>(sizeof(Register)))); + + loadPtr(Address(X86::ecx, FIELD_OFFSET(JSFunction, m_scopeChain) + FIELD_OFFSET(ScopeChain, m_node)), X86::edx); // newScopeChain + + storePtr(ImmPtr(JSValuePtr::encode(noValue())), Address(callFrameRegister, RegisterFile::OptionalCalleeArguments * static_cast<int>(sizeof(Register)))); + storePtr(X86::ecx, Address(callFrameRegister, RegisterFile::Callee * static_cast<int>(sizeof(Register)))); + storePtr(X86::edx, Address(callFrameRegister, RegisterFile::ScopeChain * static_cast<int>(sizeof(Register)))); +} + +void JIT::compileOpCallSetupArgs(Instruction* instruction) +{ + int argCount = instruction[3].u.operand; + int registerOffset = instruction[4].u.operand; + + // ecx holds func + emitPutJITStubArg(X86::ecx, 1); + emitPutJITStubArgConstant(registerOffset, 2); + emitPutJITStubArgConstant(argCount, 3); +} + +void JIT::compileOpCallEvalSetupArgs(Instruction* instruction) +{ + int argCount = instruction[3].u.operand; + int registerOffset = instruction[4].u.operand; + + // ecx holds func + emitPutJITStubArg(X86::ecx, 1); + emitPutJITStubArgConstant(registerOffset, 2); + emitPutJITStubArgConstant(argCount, 3); +} + +void JIT::compileOpConstructSetupArgs(Instruction* instruction) +{ + int argCount = instruction[3].u.operand; + int registerOffset = instruction[4].u.operand; + int proto = instruction[5].u.operand; + int thisRegister = instruction[6].u.operand; + + // ecx holds func + emitPutJITStubArg(X86::ecx, 1); + emitPutJITStubArgConstant(registerOffset, 2); + emitPutJITStubArgConstant(argCount, 3); + emitPutJITStubArgFromVirtualRegister(proto, 4, X86::eax); + emitPutJITStubArgConstant(thisRegister, 5); +} + +#if !ENABLE(JIT_OPTIMIZE_CALL) + +void JIT::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned) +{ + int dst = instruction[1].u.operand; + int callee = instruction[2].u.operand; + int argCount = instruction[3].u.operand; + int registerOffset = instruction[4].u.operand; + + // Handle eval + Jump wasEval; + if (opcodeID == op_call_eval) { + emitGetVirtualRegister(callee, X86::ecx); + compileOpCallEvalSetupArgs(instruction); + + emitCTICall(Interpreter::cti_op_call_eval); + wasEval = jnePtr(X86::eax, ImmPtr(JSValuePtr::encode(jsImpossibleValue()))); + } + + emitGetVirtualRegister(callee, X86::ecx); + // The arguments have been set up on the hot path for op_call_eval + if (opcodeID == op_call) + compileOpCallSetupArgs(instruction); + else if (opcodeID == op_construct) + compileOpConstructSetupArgs(instruction); + + // Check for JSFunctions. + emitJumpSlowCaseIfNotJSCell(X86::ecx); + addSlowCase(jnePtr(Address(X86::ecx), ImmPtr(m_interpreter->m_jsFunctionVptr))); + + // First, in the case of a construct, allocate the new object. + if (opcodeID == op_construct) { + emitCTICall(Interpreter::cti_op_construct_JSConstruct); + emitPutVirtualRegister(registerOffset - RegisterFile::CallFrameHeaderSize - argCount); + emitGetVirtualRegister(callee, X86::ecx); + } + + // Speculatively roll the callframe, assuming argCount will match the arity. + storePtr(callFrameRegister, Address(callFrameRegister, (RegisterFile::CallerFrame + registerOffset) * static_cast<int>(sizeof(Register)))); + addPtr(Imm32(registerOffset * static_cast<int>(sizeof(Register))), callFrameRegister); + move(Imm32(argCount), X86::edx); + + emitNakedCall(m_interpreter->m_ctiVirtualCall); + + if (opcodeID == op_call_eval) + wasEval.link(this); + + // Put the return value in dst. In the interpreter, op_ret does this. + emitPutVirtualRegister(dst); + + sampleCodeBlock(m_codeBlock); +} + +void JIT::compileOpCallSlowCase(Instruction* instruction, Vector<SlowCaseEntry>::iterator& iter, unsigned, OpcodeID opcodeID) +{ + int dst = instruction[1].u.operand; + + linkSlowCase(iter); + linkSlowCase(iter); + + // This handles host functions + emitCTICall(((opcodeID == op_construct) ? Interpreter::cti_op_construct_NotJSConstruct : Interpreter::cti_op_call_NotJSFunction)); + // Put the return value in dst. In the interpreter, op_ret does this. + emitPutVirtualRegister(dst); + + sampleCodeBlock(m_codeBlock); +} + +#else + +static NO_RETURN void unreachable() +{ + ASSERT_NOT_REACHED(); + exit(1); +} + +void JIT::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned callLinkInfoIndex) +{ + int dst = instruction[1].u.operand; + int callee = instruction[2].u.operand; + int argCount = instruction[3].u.operand; + int registerOffset = instruction[4].u.operand; + + // Handle eval + Jump wasEval; + if (opcodeID == op_call_eval) { + emitGetVirtualRegister(callee, X86::ecx); + compileOpCallEvalSetupArgs(instruction); + + emitCTICall(Interpreter::cti_op_call_eval); + wasEval = jnePtr(X86::eax, ImmPtr(JSValuePtr::encode(jsImpossibleValue()))); + } + + // This plants a check for a cached JSFunction value, so we can plant a fast link to the callee. + // This deliberately leaves the callee in ecx, used when setting up the stack frame below + emitGetVirtualRegister(callee, X86::ecx); + DataLabelPtr addressOfLinkedFunctionCheck; + Jump jumpToSlow = jnePtrWithPatch(X86::ecx, addressOfLinkedFunctionCheck, ImmPtr(JSValuePtr::encode(jsImpossibleValue()))); + addSlowCase(jumpToSlow); + ASSERT(differenceBetween(addressOfLinkedFunctionCheck, jumpToSlow) == patchOffsetOpCallCompareToJump); + m_callStructureStubCompilationInfo[callLinkInfoIndex].hotPathBegin = addressOfLinkedFunctionCheck; + + // The following is the fast case, only used whan a callee can be linked. + + // In the case of OpConstruct, call out to a cti_ function to create the new object. + if (opcodeID == op_construct) { + int proto = instruction[5].u.operand; + int thisRegister = instruction[6].u.operand; + + emitPutJITStubArg(X86::ecx, 1); + emitPutJITStubArgFromVirtualRegister(proto, 4, X86::eax); + emitCTICall(Interpreter::cti_op_construct_JSConstruct); + emitPutVirtualRegister(thisRegister); + emitGetVirtualRegister(callee, X86::ecx); + } + + // Fast version of stack frame initialization, directly relative to edi. + // Note that this omits to set up RegisterFile::CodeBlock, which is set in the callee + storePtr(ImmPtr(JSValuePtr::encode(noValue())), Address(callFrameRegister, (registerOffset + RegisterFile::OptionalCalleeArguments) * static_cast<int>(sizeof(Register)))); + storePtr(X86::ecx, Address(callFrameRegister, (registerOffset + RegisterFile::Callee) * static_cast<int>(sizeof(Register)))); + loadPtr(Address(X86::ecx, FIELD_OFFSET(JSFunction, m_scopeChain) + FIELD_OFFSET(ScopeChain, m_node)), X86::edx); // newScopeChain + store32(Imm32(argCount), Address(callFrameRegister, (registerOffset + RegisterFile::ArgumentCount) * static_cast<int>(sizeof(Register)))); + storePtr(callFrameRegister, Address(callFrameRegister, (registerOffset + RegisterFile::CallerFrame) * static_cast<int>(sizeof(Register)))); + storePtr(X86::edx, Address(callFrameRegister, (registerOffset + RegisterFile::ScopeChain) * static_cast<int>(sizeof(Register)))); + addPtr(Imm32(registerOffset * sizeof(Register)), callFrameRegister); + + // Call to the callee + m_callStructureStubCompilationInfo[callLinkInfoIndex].hotPathOther = emitNakedCall(reinterpret_cast<void*>(unreachable)); + + if (opcodeID == op_call_eval) + wasEval.link(this); + + // Put the return value in dst. In the interpreter, op_ret does this. + emitPutVirtualRegister(dst); + + sampleCodeBlock(m_codeBlock); +} + +void JIT::compileOpCallSlowCase(Instruction* instruction, Vector<SlowCaseEntry>::iterator& iter, unsigned callLinkInfoIndex, OpcodeID opcodeID) +{ + int dst = instruction[1].u.operand; + int callee = instruction[2].u.operand; + int argCount = instruction[3].u.operand; + int registerOffset = instruction[4].u.operand; + + linkSlowCase(iter); + + // The arguments have been set up on the hot path for op_call_eval + if (opcodeID == op_call) + compileOpCallSetupArgs(instruction); + else if (opcodeID == op_construct) + compileOpConstructSetupArgs(instruction); + + // Fast check for JS function. + Jump callLinkFailNotObject = emitJumpIfNotJSCell(X86::ecx); + Jump callLinkFailNotJSFunction = jnePtr(Address(X86::ecx), ImmPtr(m_interpreter->m_jsFunctionVptr)); + + // First, in the case of a construct, allocate the new object. + if (opcodeID == op_construct) { + emitCTICall(Interpreter::cti_op_construct_JSConstruct); + emitPutVirtualRegister(registerOffset - RegisterFile::CallFrameHeaderSize - argCount); + emitGetVirtualRegister(callee, X86::ecx); + } + + move(Imm32(argCount), X86::edx); + + // Speculatively roll the callframe, assuming argCount will match the arity. + storePtr(callFrameRegister, Address(callFrameRegister, (RegisterFile::CallerFrame + registerOffset) * static_cast<int>(sizeof(Register)))); + addPtr(Imm32(registerOffset * static_cast<int>(sizeof(Register))), callFrameRegister); + + m_callStructureStubCompilationInfo[callLinkInfoIndex].callReturnLocation = + emitNakedCall(m_interpreter->m_ctiVirtualCallPreLink); + + Jump storeResultForFirstRun = jump(); + +// FIXME: this label can be removed, since it is a fixed offset from 'callReturnLocation'. + // This is the address for the cold path *after* the first run (which tries to link the call). + m_callStructureStubCompilationInfo[callLinkInfoIndex].coldPathOther = MacroAssembler::Label(this); + + // The arguments have been set up on the hot path for op_call_eval + if (opcodeID == op_call) + compileOpCallSetupArgs(instruction); + else if (opcodeID == op_construct) + compileOpConstructSetupArgs(instruction); + + // Check for JSFunctions. + Jump isNotObject = emitJumpIfNotJSCell(X86::ecx); + Jump isJSFunction = jePtr(Address(X86::ecx), ImmPtr(m_interpreter->m_jsFunctionVptr)); + + // This handles host functions + isNotObject.link(this); + callLinkFailNotObject.link(this); + callLinkFailNotJSFunction.link(this); + emitCTICall(((opcodeID == op_construct) ? Interpreter::cti_op_construct_NotJSConstruct : Interpreter::cti_op_call_NotJSFunction)); + Jump wasNotJSFunction = jump(); + + // Next, handle JSFunctions... + isJSFunction.link(this); + + // First, in the case of a construct, allocate the new object. + if (opcodeID == op_construct) { + emitCTICall(Interpreter::cti_op_construct_JSConstruct); + emitPutVirtualRegister(registerOffset - RegisterFile::CallFrameHeaderSize - argCount); + emitGetVirtualRegister(callee, X86::ecx); + } + + // Speculatively roll the callframe, assuming argCount will match the arity. + storePtr(callFrameRegister, Address(callFrameRegister, (RegisterFile::CallerFrame + registerOffset) * static_cast<int>(sizeof(Register)))); + addPtr(Imm32(registerOffset * static_cast<int>(sizeof(Register))), callFrameRegister); + move(Imm32(argCount), X86::edx); + + emitNakedCall(m_interpreter->m_ctiVirtualCall); + + // Put the return value in dst. In the interpreter, op_ret does this. + wasNotJSFunction.link(this); + storeResultForFirstRun.link(this); + emitPutVirtualRegister(dst); + + sampleCodeBlock(m_codeBlock); +} + +#endif + +} // namespace JSC + +#endif // ENABLE(JIT) diff --git a/JavaScriptCore/jit/JITInlineMethods.h b/JavaScriptCore/jit/JITInlineMethods.h new file mode 100644 index 0000000..7a97cd8 --- /dev/null +++ b/JavaScriptCore/jit/JITInlineMethods.h @@ -0,0 +1,434 @@ +/* + * 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 JITInlineMethods_h +#define JITInlineMethods_h + +#include <wtf/Platform.h> + +#if ENABLE(JIT) + +#if PLATFORM(WIN) +#undef FIELD_OFFSET // Fix conflict with winnt.h. +#endif + +// FIELD_OFFSET: 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 FIELD_OFFSET(class, field) (reinterpret_cast<ptrdiff_t>(&(reinterpret_cast<class*>(0x4000)->field)) - 0x4000) + +namespace JSC { + +ALWAYS_INLINE void JIT::killLastResultRegister() +{ + m_lastResultBytecodeRegister = std::numeric_limits<int>::max(); +} + +// get arg puts an arg from the SF register array into a h/w register +ALWAYS_INLINE void JIT::emitGetVirtualRegister(int src, RegisterID dst) +{ + ASSERT(m_bytecodeIndex != (unsigned)-1); // This method should only be called during hot/cold path generation, so that m_bytecodeIndex is set. + + // TODO: we want to reuse values that are already in registers if we can - add a register allocator! + if (m_codeBlock->isConstantRegisterIndex(src)) { + JSValuePtr value = m_codeBlock->getConstant(src); + move(ImmPtr(JSValuePtr::encode(value)), dst); + killLastResultRegister(); + return; + } + + if (src == m_lastResultBytecodeRegister && m_codeBlock->isTemporaryRegisterIndex(src)) { + bool atJumpTarget = false; + while (m_jumpTargetsPosition < m_codeBlock->numberOfJumpTargets() && m_codeBlock->jumpTarget(m_jumpTargetsPosition) <= m_bytecodeIndex) { + if (m_codeBlock->jumpTarget(m_jumpTargetsPosition) == m_bytecodeIndex) + atJumpTarget = true; + ++m_jumpTargetsPosition; + } + + if (!atJumpTarget) { + // The argument we want is already stored in eax + if (dst != X86::eax) + move(X86::eax, dst); + killLastResultRegister(); + return; + } + } + + loadPtr(Address(callFrameRegister, src * sizeof(Register)), dst); + killLastResultRegister(); +} + +ALWAYS_INLINE void JIT::emitGetVirtualRegisters(int src1, RegisterID dst1, int src2, RegisterID dst2) +{ + if (src2 == m_lastResultBytecodeRegister) { + emitGetVirtualRegister(src2, dst2); + emitGetVirtualRegister(src1, dst1); + } else { + emitGetVirtualRegister(src1, dst1); + emitGetVirtualRegister(src2, dst2); + } +} + +// puts an arg onto the stack, as an arg to a context threaded function. +ALWAYS_INLINE void JIT::emitPutJITStubArg(RegisterID src, unsigned argumentNumber) +{ + poke(src, argumentNumber); +} + +ALWAYS_INLINE void JIT::emitPutJITStubArgConstant(unsigned value, unsigned argumentNumber) +{ + poke(Imm32(value), argumentNumber); +} + +ALWAYS_INLINE void JIT::emitPutJITStubArgConstant(void* value, unsigned argumentNumber) +{ + poke(ImmPtr(value), argumentNumber); +} + +ALWAYS_INLINE void JIT::emitGetJITStubArg(unsigned argumentNumber, RegisterID dst) +{ + peek(dst, argumentNumber); +} + +ALWAYS_INLINE JSValuePtr JIT::getConstantOperand(unsigned src) +{ + ASSERT(m_codeBlock->isConstantRegisterIndex(src)); + return m_codeBlock->getConstant(src); +} + +ALWAYS_INLINE int32_t JIT::getConstantOperandImmediateInt(unsigned src) +{ + return getConstantOperand(src).getInt32Fast(); +} + +ALWAYS_INLINE bool JIT::isOperandConstantImmediateInt(unsigned src) +{ + return m_codeBlock->isConstantRegisterIndex(src) && getConstantOperand(src).isInt32Fast(); +} + +// get arg puts an arg from the SF register array onto the stack, as an arg to a context threaded function. +ALWAYS_INLINE void JIT::emitPutJITStubArgFromVirtualRegister(unsigned src, unsigned argumentNumber, RegisterID scratch) +{ + if (m_codeBlock->isConstantRegisterIndex(src)) { + JSValuePtr value = m_codeBlock->getConstant(src); + emitPutJITStubArgConstant(JSValuePtr::encode(value), argumentNumber); + } else { + loadPtr(Address(callFrameRegister, src * sizeof(Register)), scratch); + emitPutJITStubArg(scratch, argumentNumber); + } + + killLastResultRegister(); +} + +ALWAYS_INLINE void JIT::emitPutCTIParam(void* value, unsigned name) +{ + poke(ImmPtr(value), name); +} + +ALWAYS_INLINE void JIT::emitPutCTIParam(RegisterID from, unsigned name) +{ + poke(from, name); +} + +ALWAYS_INLINE void JIT::emitGetCTIParam(unsigned name, RegisterID to) +{ + peek(to, name); + killLastResultRegister(); +} + +ALWAYS_INLINE void JIT::emitPutToCallFrameHeader(RegisterID from, RegisterFile::CallFrameHeaderEntry entry) +{ + storePtr(from, Address(callFrameRegister, entry * sizeof(Register))); +} + +ALWAYS_INLINE void JIT::emitPutImmediateToCallFrameHeader(void* value, RegisterFile::CallFrameHeaderEntry entry) +{ + storePtr(ImmPtr(value), Address(callFrameRegister, entry * sizeof(Register))); +} + +ALWAYS_INLINE void JIT::emitGetFromCallFrameHeader(RegisterFile::CallFrameHeaderEntry entry, RegisterID to) +{ + loadPtr(Address(callFrameRegister, entry * sizeof(Register)), to); + killLastResultRegister(); +} + +ALWAYS_INLINE void JIT::emitPutVirtualRegister(unsigned dst, RegisterID from) +{ + storePtr(from, Address(callFrameRegister, dst * sizeof(Register))); + m_lastResultBytecodeRegister = (from == X86::eax) ? dst : std::numeric_limits<int>::max(); + // FIXME: #ifndef NDEBUG, Write the correct m_type to the register. +} + +ALWAYS_INLINE void JIT::emitInitRegister(unsigned dst) +{ + storePtr(ImmPtr(JSValuePtr::encode(jsUndefined())), Address(callFrameRegister, dst * sizeof(Register))); + // FIXME: #ifndef NDEBUG, Write the correct m_type to the register. +} + +ALWAYS_INLINE JIT::Jump JIT::emitNakedCall(X86::RegisterID r) +{ + ASSERT(m_bytecodeIndex != (unsigned)-1); // This method should only be called during hot/cold path generation, so that m_bytecodeIndex is set. + + Jump nakedCall = call(r); + m_calls.append(CallRecord(nakedCall, m_bytecodeIndex)); + return nakedCall; +} + +ALWAYS_INLINE JIT::Jump JIT::emitNakedCall(void* function) +{ + ASSERT(m_bytecodeIndex != (unsigned)-1); // This method should only be called during hot/cold path generation, so that m_bytecodeIndex is set. + + Jump nakedCall = call(); + m_calls.append(CallRecord(nakedCall, m_bytecodeIndex, function)); + return nakedCall; +} + +#if USE(JIT_STUB_ARGUMENT_REGISTER) +ALWAYS_INLINE void JIT::restoreArgumentReference() +{ +#if PLATFORM(X86_64) + move(X86::esp, X86::edi); +#else + move(X86::esp, X86::ecx); +#endif + emitPutCTIParam(callFrameRegister, STUB_ARGS_callFrame); +} +ALWAYS_INLINE void JIT::restoreArgumentReferenceForTrampoline() +{ + // In the trampoline on x86-64, the first argument register is not overwritten. +#if !PLATFORM(X86_64) + move(X86::esp, X86::ecx); + addPtr(Imm32(sizeof(void*)), X86::ecx); +#endif +} +#elif USE(JIT_STUB_ARGUMENT_STACK) +ALWAYS_INLINE void JIT::restoreArgumentReference() +{ + storePtr(X86::esp, X86::esp); + emitPutCTIParam(callFrameRegister, STUB_ARGS_callFrame); +} +ALWAYS_INLINE void JIT::restoreArgumentReferenceForTrampoline() {} +#else // JIT_STUB_ARGUMENT_VA_LIST +ALWAYS_INLINE void JIT::restoreArgumentReference() +{ + emitPutCTIParam(callFrameRegister, STUB_ARGS_callFrame); +} +ALWAYS_INLINE void JIT::restoreArgumentReferenceForTrampoline() {} +#endif + +ALWAYS_INLINE JIT::Jump JIT::emitCTICall_internal(void* helper) +{ + ASSERT(m_bytecodeIndex != (unsigned)-1); // This method should only be called during hot/cold path generation, so that m_bytecodeIndex is set. + +#if ENABLE(OPCODE_SAMPLING) + sampleInstruction(m_codeBlock->instructions().begin() + m_bytecodeIndex, true); +#endif + restoreArgumentReference(); + Jump ctiCall = call(); + m_calls.append(CallRecord(ctiCall, m_bytecodeIndex, helper)); +#if ENABLE(OPCODE_SAMPLING) + sampleInstruction(m_codeBlock->instructions().begin() + m_bytecodeIndex, false); +#endif + killLastResultRegister(); + + return ctiCall; +} + +ALWAYS_INLINE JIT::Jump JIT::checkStructure(RegisterID reg, Structure* structure) +{ + return jnePtr(Address(reg, FIELD_OFFSET(JSCell, m_structure)), ImmPtr(structure)); +} + +ALWAYS_INLINE JIT::Jump JIT::emitJumpIfJSCell(RegisterID reg) +{ +#if USE(ALTERNATE_JSIMMEDIATE) + return jzPtr(reg, tagMaskRegister); +#else + return jz32(reg, Imm32(JSImmediate::TagMask)); +#endif +} + +ALWAYS_INLINE JIT::Jump JIT::emitJumpIfBothJSCells(RegisterID reg1, RegisterID reg2, RegisterID scratch) +{ + move(reg1, scratch); + orPtr(reg2, scratch); + return emitJumpIfJSCell(scratch); +} + +ALWAYS_INLINE void JIT::emitJumpSlowCaseIfJSCell(RegisterID reg) +{ + addSlowCase(emitJumpIfJSCell(reg)); +} + +ALWAYS_INLINE JIT::Jump JIT::emitJumpIfNotJSCell(RegisterID reg) +{ +#if USE(ALTERNATE_JSIMMEDIATE) + return jnzPtr(reg, tagMaskRegister); +#else + return jnz32(reg, Imm32(JSImmediate::TagMask)); +#endif +} + +ALWAYS_INLINE void JIT::emitJumpSlowCaseIfNotJSCell(RegisterID reg) +{ + addSlowCase(emitJumpIfNotJSCell(reg)); +} + +ALWAYS_INLINE void JIT::emitJumpSlowCaseIfNotJSCell(RegisterID reg, int vReg) +{ + if (!m_codeBlock->isKnownNotImmediate(vReg)) + emitJumpSlowCaseIfNotJSCell(reg); +} + +ALWAYS_INLINE void JIT::linkSlowCaseIfNotJSCell(Vector<SlowCaseEntry>::iterator& iter, int vReg) +{ + if (!m_codeBlock->isKnownNotImmediate(vReg)) + linkSlowCase(iter); +} + +#if USE(ALTERNATE_JSIMMEDIATE) +ALWAYS_INLINE JIT::Jump JIT::emitJumpIfImmediateNumber(RegisterID reg) +{ + return jnzPtr(reg, tagTypeNumberRegister); +} +ALWAYS_INLINE JIT::Jump JIT::emitJumpIfNotImmediateNumber(RegisterID reg) +{ + return jzPtr(reg, tagTypeNumberRegister); +} +#endif + +ALWAYS_INLINE JIT::Jump JIT::emitJumpIfImmediateInteger(RegisterID reg) +{ +#if USE(ALTERNATE_JSIMMEDIATE) + return jaePtr(reg, tagTypeNumberRegister); +#else + return jnz32(reg, Imm32(JSImmediate::TagTypeNumber)); +#endif +} + +ALWAYS_INLINE JIT::Jump JIT::emitJumpIfNotImmediateInteger(RegisterID reg) +{ +#if USE(ALTERNATE_JSIMMEDIATE) + return jbPtr(reg, tagTypeNumberRegister); +#else + return jz32(reg, Imm32(JSImmediate::TagTypeNumber)); +#endif +} + +ALWAYS_INLINE JIT::Jump JIT::emitJumpIfNotImmediateIntegers(RegisterID reg1, RegisterID reg2, RegisterID scratch) +{ + move(reg1, scratch); + andPtr(reg2, scratch); + return emitJumpIfNotImmediateInteger(scratch); +} + +ALWAYS_INLINE void JIT::emitJumpSlowCaseIfNotImmediateInteger(RegisterID reg) +{ + addSlowCase(emitJumpIfNotImmediateInteger(reg)); +} + +ALWAYS_INLINE void JIT::emitJumpSlowCaseIfNotImmediateIntegers(RegisterID reg1, RegisterID reg2, RegisterID scratch) +{ + addSlowCase(emitJumpIfNotImmediateIntegers(reg1, reg2, scratch)); +} + +#if !USE(ALTERNATE_JSIMMEDIATE) +ALWAYS_INLINE void JIT::emitFastArithDeTagImmediate(RegisterID reg) +{ + subPtr(Imm32(JSImmediate::TagTypeNumber), reg); +} + +ALWAYS_INLINE JIT::Jump JIT::emitFastArithDeTagImmediateJumpIfZero(RegisterID reg) +{ + return jzSubPtr(Imm32(JSImmediate::TagTypeNumber), reg); +} +#endif + +ALWAYS_INLINE void JIT::emitFastArithReTagImmediate(RegisterID src, RegisterID dest) +{ +#if USE(ALTERNATE_JSIMMEDIATE) + emitFastArithIntToImmNoCheck(src, dest); +#else + if (src != dest) + move(src, dest); + addPtr(Imm32(JSImmediate::TagTypeNumber), dest); +#endif +} + +ALWAYS_INLINE void JIT::emitFastArithImmToInt(RegisterID reg) +{ +#if USE(ALTERNATE_JSIMMEDIATE) + UNUSED_PARAM(reg); +#else + rshiftPtr(Imm32(JSImmediate::IntegerPayloadShift), reg); +#endif +} + +// operand is int32_t, must have been zero-extended if register is 64-bit. +ALWAYS_INLINE void JIT::emitFastArithIntToImmNoCheck(RegisterID src, RegisterID dest) +{ +#if USE(ALTERNATE_JSIMMEDIATE) + if (src != dest) + move(src, dest); + orPtr(tagTypeNumberRegister, dest); +#else + signExtend32ToPtr(src, dest); + addPtr(dest, dest); + emitFastArithReTagImmediate(dest, dest); +#endif +} + +ALWAYS_INLINE void JIT::emitTagAsBoolImmediate(RegisterID reg) +{ + lshift32(Imm32(JSImmediate::ExtendedPayloadShift), reg); + or32(Imm32(static_cast<int32_t>(JSImmediate::FullTagTypeBool)), reg); +} + +ALWAYS_INLINE void JIT::addSlowCase(Jump jump) +{ + ASSERT(m_bytecodeIndex != (unsigned)-1); // This method should only be called during hot/cold path generation, so that m_bytecodeIndex is set. + + m_slowCases.append(SlowCaseEntry(jump, m_bytecodeIndex)); +} + +ALWAYS_INLINE void JIT::addJump(Jump jump, int relativeOffset) +{ + ASSERT(m_bytecodeIndex != (unsigned)-1); // This method should only be called during hot/cold path generation, so that m_bytecodeIndex is set. + + m_jmpTable.append(JumpTable(jump, m_bytecodeIndex + relativeOffset)); +} + +ALWAYS_INLINE void JIT::emitJumpSlowToHot(Jump jump, int relativeOffset) +{ + ASSERT(m_bytecodeIndex != (unsigned)-1); // This method should only be called during hot/cold path generation, so that m_bytecodeIndex is set. + + jump.linkTo(m_labels[m_bytecodeIndex + relativeOffset], this); +} + +} + +#endif // ENABLE(JIT) + +#endif diff --git a/JavaScriptCore/jit/JITPropertyAccess.cpp b/JavaScriptCore/jit/JITPropertyAccess.cpp new file mode 100644 index 0000000..6740bec --- /dev/null +++ b/JavaScriptCore/jit/JITPropertyAccess.cpp @@ -0,0 +1,704 @@ +/* + * Copyright (C) 2008 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "JIT.h" + +#if ENABLE(JIT) + +#include "CodeBlock.h" +#include "JITInlineMethods.h" +#include "JSArray.h" +#include "JSFunction.h" +#include "Interpreter.h" +#include "ResultType.h" +#include "SamplingTool.h" + +#ifndef NDEBUG +#include <stdio.h> +#endif + +using namespace std; + +namespace JSC { + +#if !ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS) + +void JIT::compileGetByIdHotPath(int resultVReg, int baseVReg, Identifier* ident, unsigned) +{ + // As for put_by_id, get_by_id requires the offset of the Structure and the offset of the access to be patched. + // Additionally, for get_by_id we need patch the offset of the branch to the slow case (we patch this to jump + // to array-length / prototype access tranpolines, and finally we also the the property-map access offset as a label + // to jump back to if one of these trampolies finds a match. + + emitGetVirtualRegister(baseVReg, X86::eax); + + emitPutJITStubArg(X86::eax, 1); + emitPutJITStubArgConstant(ident, 2); + emitCTICall(Interpreter::cti_op_get_by_id_generic); + emitPutVirtualRegister(resultVReg); +} + + +void JIT::compileGetByIdSlowCase(int, int, Identifier*, Vector<SlowCaseEntry>::iterator&, unsigned) +{ + ASSERT_NOT_REACHED(); +} + +void JIT::compilePutByIdHotPath(int baseVReg, Identifier* ident, int valueVReg, unsigned) +{ + // In order to be able to patch both the Structure, and the object offset, we store one pointer, + // to just after the arguments have been loaded into registers 'hotPathBegin', and we generate code + // such that the Structure & offset are always at the same distance from this. + + emitGetVirtualRegisters(baseVReg, X86::eax, valueVReg, X86::edx); + + emitPutJITStubArgConstant(ident, 2); + emitPutJITStubArg(X86::eax, 1); + emitPutJITStubArg(X86::edx, 3); + emitCTICall(Interpreter::cti_op_put_by_id_generic); +} + +void JIT::compilePutByIdSlowCase(int, Identifier*, int, Vector<SlowCaseEntry>::iterator&, unsigned) +{ + ASSERT_NOT_REACHED(); +} + +#else + +void JIT::compileGetByIdHotPath(int resultVReg, int baseVReg, Identifier*, unsigned propertyAccessInstructionIndex) +{ + // As for put_by_id, get_by_id requires the offset of the Structure and the offset of the access to be patched. + // Additionally, for get_by_id we need patch the offset of the branch to the slow case (we patch this to jump + // to array-length / prototype access tranpolines, and finally we also the the property-map access offset as a label + // to jump back to if one of these trampolies finds a match. + + emitGetVirtualRegister(baseVReg, X86::eax); + + emitJumpSlowCaseIfNotJSCell(X86::eax, baseVReg); + + Label hotPathBegin(this); + m_propertyAccessCompilationInfo[propertyAccessInstructionIndex].hotPathBegin = hotPathBegin; + + DataLabelPtr structureToCompare; + Jump structureCheck = jnePtrWithPatch(Address(X86::eax, FIELD_OFFSET(JSCell, m_structure)), structureToCompare, ImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure))); + addSlowCase(structureCheck); + ASSERT(differenceBetween(hotPathBegin, structureToCompare) == patchOffsetGetByIdStructure); + ASSERT(differenceBetween(hotPathBegin, structureCheck) == patchOffsetGetByIdBranchToSlowCase); + + loadPtr(Address(X86::eax, FIELD_OFFSET(JSObject, m_propertyStorage)), X86::eax); + DataLabel32 displacementLabel = loadPtrWithAddressOffsetPatch(Address(X86::eax, patchGetByIdDefaultOffset), X86::eax); + ASSERT(differenceBetween(hotPathBegin, displacementLabel) == patchOffsetGetByIdPropertyMapOffset); + + Label putResult(this); + ASSERT(differenceBetween(hotPathBegin, putResult) == patchOffsetGetByIdPutResult); + emitPutVirtualRegister(resultVReg); +} + + +void JIT::compileGetByIdSlowCase(int resultVReg, int baseVReg, Identifier* ident, Vector<SlowCaseEntry>::iterator& iter, unsigned propertyAccessInstructionIndex) +{ + // As for the hot path of get_by_id, above, we ensure that we can use an architecture specific offset + // so that we only need track one pointer into the slow case code - we track a pointer to the location + // of the call (which we can use to look up the patch information), but should a array-length or + // prototype access trampoline fail we want to bail out back to here. To do so we can subtract back + // the distance from the call to the head of the slow case. + + linkSlowCaseIfNotJSCell(iter, baseVReg); + linkSlowCase(iter); + +#ifndef NDEBUG + Label coldPathBegin(this); +#endif + emitPutJITStubArg(X86::eax, 1); + emitPutJITStubArgConstant(ident, 2); + Jump call = emitCTICall(Interpreter::cti_op_get_by_id); + emitPutVirtualRegister(resultVReg); + + ASSERT(differenceBetween(coldPathBegin, call) == patchOffsetGetByIdSlowCaseCall); + + // Track the location of the call; this will be used to recover patch information. + m_propertyAccessCompilationInfo[propertyAccessInstructionIndex].callReturnLocation = call; +} + +void JIT::compilePutByIdHotPath(int baseVReg, Identifier*, int valueVReg, unsigned propertyAccessInstructionIndex) +{ + // In order to be able to patch both the Structure, and the object offset, we store one pointer, + // to just after the arguments have been loaded into registers 'hotPathBegin', and we generate code + // such that the Structure & offset are always at the same distance from this. + + emitGetVirtualRegisters(baseVReg, X86::eax, valueVReg, X86::edx); + + // Jump to a slow case if either the base object is an immediate, or if the Structure does not match. + emitJumpSlowCaseIfNotJSCell(X86::eax, baseVReg); + + Label hotPathBegin(this); + m_propertyAccessCompilationInfo[propertyAccessInstructionIndex].hotPathBegin = hotPathBegin; + + // It is important that the following instruction plants a 32bit immediate, in order that it can be patched over. + DataLabelPtr structureToCompare; + addSlowCase(jnePtrWithPatch(Address(X86::eax, FIELD_OFFSET(JSCell, m_structure)), structureToCompare, ImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure)))); + ASSERT(differenceBetween(hotPathBegin, structureToCompare) == patchOffsetPutByIdStructure); + + // Plant a load from a bogus ofset in the object's property map; we will patch this later, if it is to be used. + loadPtr(Address(X86::eax, FIELD_OFFSET(JSObject, m_propertyStorage)), X86::eax); + DataLabel32 displacementLabel = storePtrWithAddressOffsetPatch(X86::edx, Address(X86::eax, patchGetByIdDefaultOffset)); + ASSERT(differenceBetween(hotPathBegin, displacementLabel) == patchOffsetPutByIdPropertyMapOffset); +} + +void JIT::compilePutByIdSlowCase(int baseVReg, Identifier* ident, int, Vector<SlowCaseEntry>::iterator& iter, unsigned propertyAccessInstructionIndex) +{ + linkSlowCaseIfNotJSCell(iter, baseVReg); + linkSlowCase(iter); + + emitPutJITStubArgConstant(ident, 2); + emitPutJITStubArg(X86::eax, 1); + emitPutJITStubArg(X86::edx, 3); + Jump call = emitCTICall(Interpreter::cti_op_put_by_id); + + // Track the location of the call; this will be used to recover patch information. + m_propertyAccessCompilationInfo[propertyAccessInstructionIndex].callReturnLocation = call; +} + +static JSObject* resizePropertyStorage(JSObject* baseObject, int32_t oldSize, int32_t newSize) +{ + baseObject->allocatePropertyStorage(oldSize, newSize); + return baseObject; +} + +static inline bool transitionWillNeedStorageRealloc(Structure* oldStructure, Structure* newStructure) +{ + return oldStructure->propertyStorageCapacity() != newStructure->propertyStorageCapacity(); +} + +void JIT::privateCompilePutByIdTransition(StructureStubInfo* stubInfo, Structure* oldStructure, Structure* newStructure, size_t cachedOffset, StructureChain* chain, void* returnAddress) +{ + JumpList failureCases; + // Check eax is an object of the right Structure. + failureCases.append(emitJumpIfNotJSCell(X86::eax)); + failureCases.append(jnePtr(Address(X86::eax, FIELD_OFFSET(JSCell, m_structure)), ImmPtr(oldStructure))); + JumpList successCases; + + // ecx = baseObject + loadPtr(Address(X86::eax, FIELD_OFFSET(JSCell, m_structure)), X86::ecx); + // proto(ecx) = baseObject->structure()->prototype() + failureCases.append(jne32(Address(X86::ecx, FIELD_OFFSET(Structure, m_typeInfo) + FIELD_OFFSET(TypeInfo, m_type)), Imm32(ObjectType))); + + loadPtr(Address(X86::ecx, FIELD_OFFSET(Structure, m_prototype)), X86::ecx); + + // ecx = baseObject->m_structure + for (RefPtr<Structure>* it = chain->head(); *it; ++it) { + // null check the prototype + successCases.append(jePtr(X86::ecx, ImmPtr(JSValuePtr::encode(jsNull())))); + + // Check the structure id + failureCases.append(jnePtr(Address(X86::ecx, FIELD_OFFSET(JSCell, m_structure)), ImmPtr(it->get()))); + + loadPtr(Address(X86::ecx, FIELD_OFFSET(JSCell, m_structure)), X86::ecx); + failureCases.append(jne32(Address(X86::ecx, FIELD_OFFSET(Structure, m_typeInfo) + FIELD_OFFSET(TypeInfo, m_type)), Imm32(ObjectType))); + loadPtr(Address(X86::ecx, FIELD_OFFSET(Structure, m_prototype)), X86::ecx); + } + + successCases.link(this); + + Jump callTarget; + + // emit a call only if storage realloc is needed + if (transitionWillNeedStorageRealloc(oldStructure, newStructure)) { + pop(X86::ebx); +#if PLATFORM(X86_64) + move(Imm32(newStructure->propertyStorageCapacity()), X86::edx); + move(Imm32(oldStructure->propertyStorageCapacity()), X86::esi); + move(X86::eax, X86::edi); + callTarget = call(); +#else + push(Imm32(newStructure->propertyStorageCapacity())); + push(Imm32(oldStructure->propertyStorageCapacity())); + push(X86::eax); + callTarget = call(); + addPtr(Imm32(3 * sizeof(void*)), X86::esp); +#endif + emitGetJITStubArg(3, X86::edx); + push(X86::ebx); + } + + // Assumes m_refCount can be decremented easily, refcount decrement is safe as + // codeblock should ensure oldStructure->m_refCount > 0 + sub32(Imm32(1), AbsoluteAddress(oldStructure->addressOfCount())); + add32(Imm32(1), AbsoluteAddress(newStructure->addressOfCount())); + storePtr(ImmPtr(newStructure), Address(X86::eax, FIELD_OFFSET(JSCell, m_structure))); + + // write the value + loadPtr(Address(X86::eax, FIELD_OFFSET(JSObject, m_propertyStorage)), X86::eax); + storePtr(X86::edx, Address(X86::eax, cachedOffset * sizeof(JSValuePtr))); + + ret(); + + Jump failureJump; + bool plantedFailureJump = false; + if (!failureCases.empty()) { + failureCases.link(this); + restoreArgumentReferenceForTrampoline(); + failureJump = jump(); + plantedFailureJump = true; + } + + void* code = m_assembler.executableCopy(m_codeBlock->executablePool()); + PatchBuffer patchBuffer(code); + + if (plantedFailureJump) + patchBuffer.link(failureJump, reinterpret_cast<void*>(Interpreter::cti_op_put_by_id_fail)); + + if (transitionWillNeedStorageRealloc(oldStructure, newStructure)) + patchBuffer.link(callTarget, reinterpret_cast<void*>(resizePropertyStorage)); + + stubInfo->stubRoutine = code; + + Jump::patch(returnAddress, code); +} + +void JIT::patchGetByIdSelf(StructureStubInfo* stubInfo, Structure* structure, size_t cachedOffset, void* returnAddress) +{ + // We don't want to patch more than once - in future go to cti_op_get_by_id_generic. + // Should probably go to Interpreter::cti_op_get_by_id_fail, but that doesn't do anything interesting right now. + Jump::patch(returnAddress, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_self_fail)); + + // Patch the offset into the propoerty map to load from, then patch the Structure to look for. + void* structureAddress = reinterpret_cast<void*>(reinterpret_cast<intptr_t>(stubInfo->hotPathBegin) + patchOffsetGetByIdStructure); + void* displacementAddress = reinterpret_cast<void*>(reinterpret_cast<intptr_t>(stubInfo->hotPathBegin) + patchOffsetGetByIdPropertyMapOffset); + DataLabelPtr::patch(structureAddress, structure); + DataLabel32::patch(displacementAddress, cachedOffset * sizeof(JSValuePtr)); +} + +void JIT::patchPutByIdReplace(StructureStubInfo* stubInfo, Structure* structure, size_t cachedOffset, void* returnAddress) +{ + // We don't want to patch more than once - in future go to cti_op_put_by_id_generic. + // Should probably go to Interpreter::cti_op_put_by_id_fail, but that doesn't do anything interesting right now. + Jump::patch(returnAddress, reinterpret_cast<void*>(Interpreter::cti_op_put_by_id_generic)); + + // Patch the offset into the propoerty map to load from, then patch the Structure to look for. + void* structureAddress = reinterpret_cast<char*>(stubInfo->hotPathBegin) + patchOffsetPutByIdStructure; + void* displacementAddress = reinterpret_cast<char*>(stubInfo->hotPathBegin) + patchOffsetPutByIdPropertyMapOffset; + DataLabelPtr::patch(structureAddress, structure); + DataLabel32::patch(displacementAddress, cachedOffset * sizeof(JSValuePtr)); +} + +void JIT::privateCompilePatchGetArrayLength(void* returnAddress) +{ + StructureStubInfo* stubInfo = &m_codeBlock->getStubInfo(returnAddress); + + // We don't want to patch more than once - in future go to cti_op_put_by_id_generic. + Jump::patch(returnAddress, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_array_fail)); + + // Check eax is an array + Jump failureCases1 = jnePtr(Address(X86::eax), ImmPtr(m_interpreter->m_jsArrayVptr)); + + // Checks out okay! - get the length from the storage + loadPtr(Address(X86::eax, FIELD_OFFSET(JSArray, m_storage)), X86::ecx); + load32(Address(X86::ecx, FIELD_OFFSET(ArrayStorage, m_length)), X86::ecx); + + Jump failureCases2 = ja32(X86::ecx, Imm32(JSImmediate::maxImmediateInt)); + + emitFastArithIntToImmNoCheck(X86::ecx, X86::eax); + Jump success = jump(); + + void* code = m_assembler.executableCopy(m_codeBlock->executablePool()); + PatchBuffer patchBuffer(code); + + // Use the patch information to link the failure cases back to the original slow case routine. + void* slowCaseBegin = reinterpret_cast<char*>(stubInfo->callReturnLocation) - patchOffsetGetByIdSlowCaseCall; + 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. + void* hotPathPutResult = reinterpret_cast<char*>(stubInfo->hotPathBegin) + patchOffsetGetByIdPutResult; + patchBuffer.link(success, hotPathPutResult); + + // Track the stub we have created so that it will be deleted later. + stubInfo->stubRoutine = code; + + // Finally patch the jump to sow case back in the hot path to jump here instead. + void* jumpLocation = reinterpret_cast<char*>(stubInfo->hotPathBegin) + patchOffsetGetByIdBranchToSlowCase; + Jump::patch(jumpLocation, code); +} + +void JIT::privateCompileGetByIdSelf(StructureStubInfo* stubInfo, Structure* structure, size_t cachedOffset, void* returnAddress) +{ + // Check eax is an object of the right Structure. + Jump failureCases1 = emitJumpIfNotJSCell(X86::eax); + Jump failureCases2 = checkStructure(X86::eax, structure); + + // Checks out okay! - getDirectOffset + loadPtr(Address(X86::eax, FIELD_OFFSET(JSObject, m_propertyStorage)), X86::eax); + loadPtr(Address(X86::eax, cachedOffset * sizeof(JSValuePtr)), X86::eax); + ret(); + + void* code = m_assembler.executableCopy(m_codeBlock->executablePool()); + PatchBuffer patchBuffer(code); + + patchBuffer.link(failureCases1, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_self_fail)); + patchBuffer.link(failureCases2, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_self_fail)); + + stubInfo->stubRoutine = code; + + Jump::patch(returnAddress, code); +} + +void JIT::privateCompileGetByIdProto(StructureStubInfo* stubInfo, Structure* structure, Structure* prototypeStructure, size_t cachedOffset, void* returnAddress, CallFrame* callFrame) +{ +#if USE(CTI_REPATCH_PIC) + // We don't want to patch more than once - in future go to cti_op_put_by_id_generic. + Jump::patch(returnAddress, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_proto_list)); + + // The prototype object definitely exists (if this stub exists the CodeBlock is referencing a Structure that is + // referencing the prototype object - let's speculatively load it's table nice and early!) + JSObject* protoObject = asObject(structure->prototypeForLookup(callFrame)); + PropertyStorage* protoPropertyStorage = &protoObject->m_propertyStorage; + loadPtr(static_cast<void*>(protoPropertyStorage), X86::edx); + + // Check eax is an object of the right Structure. + Jump failureCases1 = checkStructure(X86::eax, structure); + + // Check the prototype object's Structure had not changed. + Structure** prototypeStructureAddress = &(protoObject->m_structure); +#if PLATFORM(X86_64) + move(ImmPtr(prototypeStructure), X86::ebx); + Jump failureCases2 = jnePtr(X86::ebx, AbsoluteAddress(prototypeStructureAddress)); +#else + Jump failureCases2 = jnePtr(AbsoluteAddress(prototypeStructureAddress), ImmPtr(prototypeStructure)); +#endif + + // Checks out okay! - getDirectOffset + loadPtr(Address(X86::edx, cachedOffset * sizeof(JSValuePtr)), X86::eax); + + Jump success = jump(); + + void* code = m_assembler.executableCopy(m_codeBlock->executablePool()); + PatchBuffer patchBuffer(code); + + // Use the patch information to link the failure cases back to the original slow case routine. + void* slowCaseBegin = reinterpret_cast<char*>(stubInfo->callReturnLocation) - patchOffsetGetByIdSlowCaseCall; + 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. + intptr_t successDest = reinterpret_cast<intptr_t>(stubInfo->hotPathBegin) + patchOffsetGetByIdPutResult; + patchBuffer.link(success, reinterpret_cast<void*>(successDest)); + + // Track the stub we have created so that it will be deleted later. + stubInfo->stubRoutine = code; + + // Finally patch the jump to slow case back in the hot path to jump here instead. + void* jumpLocation = reinterpret_cast<char*>(stubInfo->hotPathBegin) + patchOffsetGetByIdBranchToSlowCase; + Jump::patch(jumpLocation, code); +#else + // The prototype object definitely exists (if this stub exists the CodeBlock is referencing a Structure that is + // referencing the prototype object - let's speculatively load it's table nice and early!) + JSObject* protoObject = asObject(structure->prototypeForLookup(callFrame)); + PropertyStorage* protoPropertyStorage = &protoObject->m_propertyStorage; + loadPtr(protoPropertyStorage, X86::edx); + + // Check eax is an object of the right Structure. + Jump failureCases1 = emitJumpIfNotJSCell(X86::eax); + Jump failureCases2 = checkStructure(X86::eax, structure); + + // Check the prototype object's Structure had not changed. + Structure** prototypeStructureAddress = &(protoObject->m_structure); + Jump failureCases3 = jnePtr(AbsoluteAddress(prototypeStructureAddress), ImmPtr(prototypeStructure)); + + // Checks out okay! - getDirectOffset + loadPtr(Address(X86::edx, cachedOffset * sizeof(JSValuePtr)), X86::eax); + + ret(); + + void* code = m_assembler.executableCopy(m_codeBlock->executablePool()); + PatchBuffer patchBuffer(code); + + patchBuffer.link(failureCases1, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_proto_fail)); + patchBuffer.link(failureCases2, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_proto_fail)); + patchBuffer.link(failureCases3, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_proto_fail)); + + stubInfo->stubRoutine = code; + + Jump::patch(returnAddress, code); +#endif +} + +#if USE(CTI_REPATCH_PIC) +void JIT::privateCompileGetByIdSelfList(StructureStubInfo* stubInfo, PolymorphicAccessStructureList* polymorphicStructures, int currentIndex, Structure* structure, size_t cachedOffset) +{ + Jump failureCase = checkStructure(X86::eax, structure); + loadPtr(Address(X86::eax, FIELD_OFFSET(JSObject, m_propertyStorage)), X86::eax); + loadPtr(Address(X86::eax, cachedOffset * sizeof(JSValuePtr)), X86::eax); + Jump success = jump(); + + void* code = m_assembler.executableCopy(m_codeBlock->executablePool()); + ASSERT(code); + PatchBuffer patchBuffer(code); + + // Use the patch information to link the failure cases back to the original slow case routine. + void* lastProtoBegin = polymorphicStructures->list[currentIndex - 1].stubRoutine; + if (!lastProtoBegin) + lastProtoBegin = reinterpret_cast<char*>(stubInfo->callReturnLocation) - patchOffsetGetByIdSlowCaseCall; + + 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. + intptr_t successDest = reinterpret_cast<intptr_t>(stubInfo->hotPathBegin) + patchOffsetGetByIdPutResult; + patchBuffer.link(success, reinterpret_cast<void*>(successDest)); + + structure->ref(); + polymorphicStructures->list[currentIndex].set(code, structure); + + // Finally patch the jump to slow case back in the hot path to jump here instead. + void* jumpLocation = reinterpret_cast<char*>(stubInfo->hotPathBegin) + patchOffsetGetByIdBranchToSlowCase; + Jump::patch(jumpLocation, code); +} + +void JIT::privateCompileGetByIdProtoList(StructureStubInfo* stubInfo, PolymorphicAccessStructureList* prototypeStructures, int currentIndex, Structure* structure, Structure* prototypeStructure, size_t cachedOffset, CallFrame* callFrame) +{ + // The prototype object definitely exists (if this stub exists the CodeBlock is referencing a Structure that is + // referencing the prototype object - let's speculatively load it's table nice and early!) + JSObject* protoObject = asObject(structure->prototypeForLookup(callFrame)); + PropertyStorage* protoPropertyStorage = &protoObject->m_propertyStorage; + loadPtr(protoPropertyStorage, X86::edx); + + // Check eax is an object of the right Structure. + Jump failureCases1 = checkStructure(X86::eax, structure); + + // Check the prototype object's Structure had not changed. + Structure** prototypeStructureAddress = &(protoObject->m_structure); +#if PLATFORM(X86_64) + move(ImmPtr(prototypeStructure), X86::ebx); + Jump failureCases2 = jnePtr(X86::ebx, AbsoluteAddress(prototypeStructureAddress)); +#else + Jump failureCases2 = jnePtr(AbsoluteAddress(prototypeStructureAddress), ImmPtr(prototypeStructure)); +#endif + + // Checks out okay! - getDirectOffset + loadPtr(Address(X86::edx, cachedOffset * sizeof(JSValuePtr)), X86::eax); + + Jump success = jump(); + + void* code = m_assembler.executableCopy(m_codeBlock->executablePool()); + PatchBuffer patchBuffer(code); + + // Use the patch information to link the failure cases back to the original slow case routine. + void* lastProtoBegin = prototypeStructures->list[currentIndex - 1].stubRoutine; + patchBuffer.link(failureCases1, lastProtoBegin); + 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. + intptr_t successDest = reinterpret_cast<intptr_t>(stubInfo->hotPathBegin) + patchOffsetGetByIdPutResult; + patchBuffer.link(success, reinterpret_cast<void*>(successDest)); + + structure->ref(); + prototypeStructure->ref(); + prototypeStructures->list[currentIndex].set(code, structure, prototypeStructure); + + // Finally patch the jump to slow case back in the hot path to jump here instead. + void* jumpLocation = reinterpret_cast<char*>(stubInfo->hotPathBegin) + patchOffsetGetByIdBranchToSlowCase; + Jump::patch(jumpLocation, code); +} + +void JIT::privateCompileGetByIdChainList(StructureStubInfo* stubInfo, PolymorphicAccessStructureList* prototypeStructures, int currentIndex, Structure* structure, StructureChain* chain, size_t count, size_t cachedOffset, CallFrame* callFrame) +{ + ASSERT(count); + + JumpList bucketsOfFail; + + // Check eax is an object of the right Structure. + Jump baseObjectCheck = checkStructure(X86::eax, structure); + bucketsOfFail.append(baseObjectCheck); + + Structure* currStructure = structure; + RefPtr<Structure>* chainEntries = chain->head(); + JSObject* protoObject = 0; + for (unsigned i = 0; i < count; ++i) { + protoObject = asObject(currStructure->prototypeForLookup(callFrame)); + currStructure = chainEntries[i].get(); + + // Check the prototype object's Structure had not changed. + Structure** prototypeStructureAddress = &(protoObject->m_structure); +#if PLATFORM(X86_64) + move(ImmPtr(currStructure), X86::ebx); + bucketsOfFail.append(jnePtr(X86::ebx, AbsoluteAddress(prototypeStructureAddress))); +#else + bucketsOfFail.append(jnePtr(AbsoluteAddress(prototypeStructureAddress), ImmPtr(currStructure))); +#endif + } + ASSERT(protoObject); + + PropertyStorage* protoPropertyStorage = &protoObject->m_propertyStorage; + loadPtr(protoPropertyStorage, X86::edx); + loadPtr(Address(X86::edx, cachedOffset * sizeof(JSValuePtr)), X86::eax); + Jump success = jump(); + + void* code = m_assembler.executableCopy(m_codeBlock->executablePool()); + PatchBuffer patchBuffer(code); + + // Use the patch information to link the failure cases back to the original slow case routine. + void* lastProtoBegin = prototypeStructures->list[currentIndex - 1].stubRoutine; + + 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. + intptr_t successDest = reinterpret_cast<intptr_t>(stubInfo->hotPathBegin) + patchOffsetGetByIdPutResult; + patchBuffer.link(success, reinterpret_cast<void*>(successDest)); + + // Track the stub we have created so that it will be deleted later. + structure->ref(); + chain->ref(); + prototypeStructures->list[currentIndex].set(code, structure, chain); + + // Finally patch the jump to slow case back in the hot path to jump here instead. + void* jumpLocation = reinterpret_cast<char*>(stubInfo->hotPathBegin) + patchOffsetGetByIdBranchToSlowCase; + Jump::patch(jumpLocation, code); +} +#endif + +void JIT::privateCompileGetByIdChain(StructureStubInfo* stubInfo, Structure* structure, StructureChain* chain, size_t count, size_t cachedOffset, void* returnAddress, CallFrame* callFrame) +{ +#if USE(CTI_REPATCH_PIC) + // We don't want to patch more than once - in future go to cti_op_put_by_id_generic. + Jump::patch(returnAddress, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_proto_list)); + + ASSERT(count); + + JumpList bucketsOfFail; + + // Check eax is an object of the right Structure. + bucketsOfFail.append(checkStructure(X86::eax, structure)); + + Structure* currStructure = structure; + RefPtr<Structure>* chainEntries = chain->head(); + JSObject* protoObject = 0; + for (unsigned i = 0; i < count; ++i) { + protoObject = asObject(currStructure->prototypeForLookup(callFrame)); + currStructure = chainEntries[i].get(); + + // Check the prototype object's Structure had not changed. + Structure** prototypeStructureAddress = &(protoObject->m_structure); +#if PLATFORM(X86_64) + move(ImmPtr(currStructure), X86::ebx); + bucketsOfFail.append(jnePtr(X86::ebx, AbsoluteAddress(prototypeStructureAddress))); +#else + bucketsOfFail.append(jnePtr(AbsoluteAddress(prototypeStructureAddress), ImmPtr(currStructure))); +#endif + } + ASSERT(protoObject); + + PropertyStorage* protoPropertyStorage = &protoObject->m_propertyStorage; + loadPtr(protoPropertyStorage, X86::edx); + loadPtr(Address(X86::edx, cachedOffset * sizeof(JSValuePtr)), X86::eax); + Jump success = jump(); + + void* code = m_assembler.executableCopy(m_codeBlock->executablePool()); + PatchBuffer patchBuffer(code); + + // Use the patch information to link the failure cases back to the original slow case routine. + void* slowCaseBegin = reinterpret_cast<char*>(stubInfo->callReturnLocation) - patchOffsetGetByIdSlowCaseCall; + + patchBuffer.link(bucketsOfFail, slowCaseBegin); + + // On success return back to the hot patch code, at a point it will perform the store to dest for us. + intptr_t successDest = reinterpret_cast<intptr_t>(stubInfo->hotPathBegin) + patchOffsetGetByIdPutResult; + patchBuffer.link(success, reinterpret_cast<void*>(successDest)); + + // Track the stub we have created so that it will be deleted later. + stubInfo->stubRoutine = code; + + // Finally patch the jump to slow case back in the hot path to jump here instead. + void* jumpLocation = reinterpret_cast<char*>(stubInfo->hotPathBegin) + patchOffsetGetByIdBranchToSlowCase; + Jump::patch(jumpLocation, code); +#else + ASSERT(count); + + JumpList bucketsOfFail; + + // Check eax is an object of the right Structure. + bucketsOfFail.append(emitJumpIfNotJSCell(X86::eax)); + bucketsOfFail.append(checkStructure(X86::eax, structure)); + + Structure* currStructure = structure; + RefPtr<Structure>* chainEntries = chain->head(); + JSObject* protoObject = 0; + for (unsigned i = 0; i < count; ++i) { + protoObject = asObject(currStructure->prototypeForLookup(callFrame)); + currStructure = chainEntries[i].get(); + + // Check the prototype object's Structure had not changed. + Structure** prototypeStructureAddress = &(protoObject->m_structure); +#if PLATFORM(X86_64) + move(ImmPtr(currStructure), X86::ebx); + bucketsOfFail.append(jnePtr(X86::ebx, AbsoluteAddress(prototypeStructureAddress))); +#else + bucketsOfFail.append(jnePtr(AbsoluteAddress(prototypeStructureAddress), ImmPtr(currStructure))); +#endif + } + ASSERT(protoObject); + + PropertyStorage* protoPropertyStorage = &protoObject->m_propertyStorage; + loadPtr(protoPropertyStorage, X86::edx); + loadPtr(Address(X86::edx, cachedOffset * sizeof(JSValuePtr)), X86::eax); + ret(); + + void* code = m_assembler.executableCopy(m_codeBlock->executablePool()); + + patchBuffer.link(bucketsOfFail, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_proto_fail)); + + stubInfo->stubRoutine = code; + + Jump::patch(returnAddress, code); +#endif +} + +void JIT::privateCompilePutByIdReplace(StructureStubInfo* stubInfo, Structure* structure, size_t cachedOffset, void* returnAddress) +{ + // Check eax is an object of the right Structure. + Jump failureCases1 = emitJumpIfNotJSCell(X86::eax); + Jump failureCases2 = checkStructure(X86::eax, structure); + + // checks out okay! - putDirectOffset + loadPtr(Address(X86::eax, FIELD_OFFSET(JSObject, m_propertyStorage)), X86::eax); + storePtr(X86::edx, Address(X86::eax, cachedOffset * sizeof(JSValuePtr))); + ret(); + + void* code = m_assembler.executableCopy(m_codeBlock->executablePool()); + PatchBuffer patchBuffer(code); + + patchBuffer.link(failureCases1, reinterpret_cast<void*>(Interpreter::cti_op_put_by_id_fail)); + patchBuffer.link(failureCases2, reinterpret_cast<void*>(Interpreter::cti_op_put_by_id_fail)); + + stubInfo->stubRoutine = code; + + Jump::patch(returnAddress, code); +} + +#endif + +} // namespace JSC + +#endif // ENABLE(JIT) diff --git a/JavaScriptCore/kjs/Shell.cpp b/JavaScriptCore/jsc.cpp index f35679e..666bd58 100644 --- a/JavaScriptCore/kjs/Shell.cpp +++ b/JavaScriptCore/jsc.cpp @@ -22,16 +22,16 @@ #include "config.h" -#include "CodeGenerator.h" +#include "BytecodeGenerator.h" +#include "Completion.h" #include "InitializeThreading.h" #include "JSArray.h" #include "JSLock.h" #include "PrototypeFunction.h" #include "SamplingTool.h" -#include "completion.h" -#include "interpreter.h" #include <math.h> #include <stdio.h> +#include <stdlib.h> #include <string.h> #if !PLATFORM(WIN_OS) @@ -51,7 +51,7 @@ #include <signal.h> #endif -#if COMPILER(MSVC) +#if COMPILER(MSVC) && !PLATFORM(WIN_CE) #include <crtdbg.h> #include <windows.h> #endif @@ -64,27 +64,26 @@ using namespace JSC; using namespace WTF; +static void cleanupGlobalData(JSGlobalData*); static bool fillBufferWithContentsOfFile(const UString& fileName, Vector<char>& buffer); -static JSValue* functionPrint(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* functionDebug(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* functionGC(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* functionVersion(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* functionRun(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* functionLoad(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* functionReadline(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* functionQuit(ExecState*, JSObject*, JSValue*, const ArgList&); +static JSValuePtr functionPrint(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr functionDebug(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr functionGC(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr functionVersion(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr functionRun(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr functionLoad(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr functionReadline(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static NO_RETURN JSValuePtr functionQuit(ExecState*, JSObject*, JSValuePtr, const ArgList&); struct Options { Options() : interactive(false) - , prettyPrint(false) , dump(false) { } bool interactive; - bool prettyPrint; bool dump; Vector<UString> fileNames; Vector<UString> arguments; @@ -175,13 +174,13 @@ GlobalObject::GlobalObject(const Vector<UString>& arguments) putDirect(Identifier(globalExec(), "arguments"), array); } -JSValue* functionPrint(ExecState* exec, JSObject*, JSValue*, const ArgList& args) +JSValuePtr functionPrint(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) { for (unsigned i = 0; i < args.size(); ++i) { if (i != 0) putchar(' '); - printf("%s", args.at(exec, i)->toString(exec).UTF8String().c_str()); + printf("%s", args.at(exec, i).toString(exec).UTF8String().c_str()); } putchar('\n'); @@ -189,30 +188,30 @@ JSValue* functionPrint(ExecState* exec, JSObject*, JSValue*, const ArgList& args return jsUndefined(); } -JSValue* functionDebug(ExecState* exec, JSObject*, JSValue*, const ArgList& args) +JSValuePtr functionDebug(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) { - fprintf(stderr, "--> %s\n", args.at(exec, 0)->toString(exec).UTF8String().c_str()); + fprintf(stderr, "--> %s\n", args.at(exec, 0).toString(exec).UTF8String().c_str()); return jsUndefined(); } -JSValue* functionGC(ExecState* exec, JSObject*, JSValue*, const ArgList&) +JSValuePtr functionGC(ExecState* exec, JSObject*, JSValuePtr, const ArgList&) { JSLock lock(false); exec->heap()->collect(); return jsUndefined(); } -JSValue* functionVersion(ExecState*, JSObject*, JSValue*, const ArgList&) +JSValuePtr functionVersion(ExecState*, JSObject*, JSValuePtr, const ArgList&) { // We need this function for compatibility with the Mozilla JS tests but for now // we don't actually do any version-specific handling return jsUndefined(); } -JSValue* functionRun(ExecState* exec, JSObject*, JSValue*, const ArgList& args) +JSValuePtr functionRun(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) { StopWatch stopWatch; - UString fileName = args.at(exec, 0)->toString(exec); + UString fileName = args.at(exec, 0).toString(exec); Vector<char> script; if (!fillBufferWithContentsOfFile(fileName, script)) return throwError(exec, GeneralError, "Could not open file."); @@ -220,26 +219,26 @@ JSValue* functionRun(ExecState* exec, JSObject*, JSValue*, const ArgList& args) JSGlobalObject* globalObject = exec->lexicalGlobalObject(); stopWatch.start(); - Interpreter::evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), makeSource(script.data(), fileName)); + evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), makeSource(script.data(), fileName)); stopWatch.stop(); return jsNumber(globalObject->globalExec(), stopWatch.getElapsedMS()); } -JSValue* functionLoad(ExecState* exec, JSObject*, JSValue*, const ArgList& args) +JSValuePtr functionLoad(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) { - UString fileName = args.at(exec, 0)->toString(exec); + UString fileName = args.at(exec, 0).toString(exec); Vector<char> script; if (!fillBufferWithContentsOfFile(fileName, script)) return throwError(exec, GeneralError, "Could not open file."); JSGlobalObject* globalObject = exec->lexicalGlobalObject(); - Interpreter::evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), makeSource(script.data(), fileName)); + evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), makeSource(script.data(), fileName)); return jsUndefined(); } -JSValue* functionReadline(ExecState* exec, JSObject*, JSValue*, const ArgList&) +JSValuePtr functionReadline(ExecState* exec, JSObject*, JSValuePtr, const ArgList&) { Vector<char, 256> line; int c; @@ -253,13 +252,10 @@ JSValue* functionReadline(ExecState* exec, JSObject*, JSValue*, const ArgList&) return jsString(exec, line.data()); } -JSValue* functionQuit(ExecState*, JSObject*, JSValue*, const ArgList&) +JSValuePtr functionQuit(ExecState* exec, JSObject*, JSValuePtr, const ArgList&) { - exit(0); -#if !COMPILER(MSVC) - // MSVC knows that exit(0) never returns, so it flags this return statement as unreachable. - return jsUndefined(); -#endif + cleanupGlobalData(&exec->globalData()); + exit(EXIT_SUCCESS); } // Use SEH for Release builds only to get rid of the crash report dialog @@ -292,37 +288,38 @@ int main(int argc, char** argv) QCoreApplication app(argc, argv); #endif + // Initialize JSC before getting JSGlobalData. + JSC::initializeThreading(); + + // We can't use destructors in the following code because it uses Windows + // Structured Exception Handling int res = 0; + JSGlobalData* globalData = JSGlobalData::create().releaseRef(); TRY - res = jscmain(argc, argv, JSGlobalData::create().releaseRef()); + res = jscmain(argc, argv, globalData); EXCEPT(res = 3) + + cleanupGlobalData(globalData); return res; } -static bool prettyPrintScript(ExecState* exec, const UString& fileName, const Vector<char>& script) +static void cleanupGlobalData(JSGlobalData* globalData) { - int errLine = 0; - UString errMsg; - RefPtr<ProgramNode> programNode = exec->globalData().parser->parse<ProgramNode>(exec, exec->dynamicGlobalObject()->debugger(), makeSource(script.data(), fileName), &errLine, &errMsg); - if (!programNode) { - fprintf(stderr, "%s:%d: %s.\n", fileName.UTF8String().c_str(), errLine, errMsg.UTF8String().c_str()); - return false; - } - - printf("%s\n", programNode->toString().UTF8String().c_str()); - return true; + JSLock lock(false); + globalData->heap.destroy(); + globalData->deref(); } -static bool runWithScripts(GlobalObject* globalObject, const Vector<UString>& fileNames, bool prettyPrint, bool dump) +static bool runWithScripts(GlobalObject* globalObject, const Vector<UString>& fileNames, bool dump) { Vector<char> script; if (dump) - CodeGenerator::setDumpsGeneratedCode(true); + BytecodeGenerator::setDumpsGeneratedCode(true); #if ENABLE(OPCODE_SAMPLING) - Machine* machine = globalObject->globalData()->machine; - machine->setSampler(new SamplingTool(machine)); + Interpreter* interpreter = globalObject->globalData()->interpreter; + interpreter->setSampler(new SamplingTool(interpreter)); #endif bool success = true; @@ -332,32 +329,28 @@ static bool runWithScripts(GlobalObject* globalObject, const Vector<UString>& fi if (!fillBufferWithContentsOfFile(fileName, script)) return false; // fail early so we can catch missing files - if (prettyPrint) - prettyPrintScript(globalObject->globalExec(), fileName, script); - else { #if ENABLE(OPCODE_SAMPLING) - machine->sampler()->start(); + interpreter->sampler()->start(); #endif - Completion completion = Interpreter::evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), makeSource(script.data(), fileName)); - success = success && completion.complType() != Throw; - if (dump) { - if (completion.complType() == Throw) - printf("Exception: %s\n", completion.value()->toString(globalObject->globalExec()).ascii()); - else - printf("End: %s\n", completion.value()->toString(globalObject->globalExec()).ascii()); - } + Completion completion = evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), makeSource(script.data(), fileName)); + success = success && completion.complType() != Throw; + if (dump) { + if (completion.complType() == Throw) + printf("Exception: %s\n", completion.value().toString(globalObject->globalExec()).ascii()); + else + printf("End: %s\n", completion.value().toString(globalObject->globalExec()).ascii()); + } - globalObject->globalExec()->clearException(); + globalObject->globalExec()->clearException(); #if ENABLE(OPCODE_SAMPLING) - machine->sampler()->stop(); + interpreter->sampler()->stop(); #endif - } } #if ENABLE(OPCODE_SAMPLING) - machine->sampler()->dump(globalObject->globalExec()); - delete machine->sampler(); + interpreter->sampler()->dump(globalObject->globalExec()); + delete interpreter->sampler(); #endif return success; } @@ -371,7 +364,7 @@ static void runInteractive(GlobalObject* globalObject) break; if (line[0]) add_history(line); - Completion completion = Interpreter::evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), makeSource(line, interpreterName)); + Completion completion = evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), makeSource(line, interpreterName)); free(line); #else puts(interactivePrompt); @@ -384,28 +377,27 @@ static void runInteractive(GlobalObject* globalObject) line.append(c); } line.append('\0'); - Completion completion = Interpreter::evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), makeSource(line.data(), interpreterName)); + Completion completion = evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), makeSource(line.data(), interpreterName)); #endif if (completion.complType() == Throw) - printf("Exception: %s\n", completion.value()->toString(globalObject->globalExec()).ascii()); + printf("Exception: %s\n", completion.value().toString(globalObject->globalExec()).ascii()); else - printf("%s\n", completion.value()->toString(globalObject->globalExec()).UTF8String().c_str()); + printf("%s\n", completion.value().toString(globalObject->globalExec()).UTF8String().c_str()); globalObject->globalExec()->clearException(); } printf("\n"); } -static void printUsageStatement() +static NO_RETURN void printUsageStatement() { fprintf(stderr, "Usage: jsc [options] [files] [-- arguments]\n"); fprintf(stderr, " -d Dumps bytecode (debug builds only)\n"); fprintf(stderr, " -f Specifies a source file (deprecated)\n"); fprintf(stderr, " -h|--help Prints this help message\n"); fprintf(stderr, " -i Enables interactive mode (default if no files are specified)\n"); - fprintf(stderr, " -p Prints formatted source code\n"); fprintf(stderr, " -s Installs signal handlers that exit on a crash (Unix platforms only)\n"); - exit(-1); + exit(EXIT_FAILURE); } static void parseArguments(int argc, char** argv, Options& options) @@ -426,10 +418,6 @@ static void parseArguments(int argc, char** argv, Options& options) options.interactive = true; continue; } - if (strcmp(arg, "-p") == 0) { - options.prettyPrint = true; - continue; - } if (strcmp(arg, "-d") == 0) { options.dump = true; continue; @@ -459,15 +447,13 @@ static void parseArguments(int argc, char** argv, Options& options) int jscmain(int argc, char** argv, JSGlobalData* globalData) { - JSC::initializeThreading(); - JSLock lock(false); Options options; parseArguments(argc, argv, options); GlobalObject* globalObject = new (globalData) GlobalObject(options.arguments); - bool success = runWithScripts(globalObject, options.fileNames, options.prettyPrint, options.dump); + bool success = runWithScripts(globalObject, options.fileNames, options.dump); if (options.interactive && success) runInteractive(globalObject); diff --git a/JavaScriptCore/kjs/jsc.pro b/JavaScriptCore/jsc.pro index 2a30d65..6262e62 100644 --- a/JavaScriptCore/kjs/jsc.pro +++ b/JavaScriptCore/jsc.pro @@ -1,14 +1,15 @@ TEMPLATE = app TARGET = jsc -DESTDIR = .. -SOURCES = Shell.cpp +DESTDIR = . +SOURCES = jsc.cpp QT -= gui -INCLUDEPATH += $$PWD/.. \ - $$PWD \ - $$PWD/../bindings \ - $$PWD/../bindings/c \ - $$PWD/../wtf \ - $$PWD/../VM +INCLUDEPATH += $$PWD \ + $$PWD/parser \ + $$PWD/bindings \ + $$PWD/bindings/c \ + $$PWD/wtf \ + $$PWD/jit \ + $$PWD/bytecode CONFIG -= app_bundle DEFINES += BUILDING_QT__ CONFIG += building-libs @@ -17,19 +18,22 @@ CONFIG(release) { DEFINES += NDEBUG USE_SYSTEM_MALLOC } -include($$PWD/../../WebKit.pri) +include($$PWD/../WebKit.pri) CONFIG += link_pkgconfig QMAKE_RPATHDIR += $$OUTPUT_DIR/lib -isEmpty(OUTPUT_DIR):OUTPUT_DIR=$$PWD/../.. +isEmpty(OUTPUT_DIR):OUTPUT_DIR=$$PWD/.. include($$OUTPUT_DIR/config.pri) OBJECTS_DIR = tmp OBJECTS_DIR_WTR = $$OBJECTS_DIR/ win32-*: OBJECTS_DIR_WTR ~= s|/|\| -include($$PWD/../JavaScriptCore.pri) +include($$PWD/JavaScriptCore.pri) lessThan(QT_MINOR_VERSION, 4) { DEFINES += QT_BEGIN_NAMESPACE="" QT_END_NAMESPACE="" } + +*-g++*:QMAKE_CXXFLAGS_RELEASE -= -O2 +*-g++*:QMAKE_CXXFLAGS_RELEASE += -O3 diff --git a/JavaScriptCore/jscore.bkl b/JavaScriptCore/jscore.bkl index c265abc..262c883 100644 --- a/JavaScriptCore/jscore.bkl +++ b/JavaScriptCore/jscore.bkl @@ -37,10 +37,12 @@ JavaScriptCore Bakefile project file. <template id="jscore_base" template="icu,pthreads,wxwk_build_settings"> <sources> - $(JSCORE_SOURCES_API) + $(JSCORE_API_SOURCES) + $(JSCORE_BYTECOMPILER_SOURCES) $(JSCORE_DEBUGGER_SOURCES) - $(JSCORE_SOURCES_KJS) - $(JSCORE_SOURCES_PCRE) + $(JSCORE_JSC_SOURCES) + $(JSCORE_PCRE_SOURCES) + $(JSCORE_PARSER_SOURCES) $(JSCORE_PROFILER_SOURCES) $(JSCORE_RUNTIME_SOURCES) $(JSCORE_VM_SOURCES) @@ -53,14 +55,18 @@ JavaScriptCore Bakefile project file. <include>$(SRCDIR)</include> <include>$(SRCDIR)/..</include> <include>$(SRCDIR)/API</include> + <include>$(SRCDIR)/bytecompiler</include> <include>$(SRCDIR)/DerivedSources/JavaScriptCore</include> <include>$(SRCDIR)/ForwardingHeaders</include> <include>$(SRCDIR)/debugger</include> - <include>$(SRCDIR)/kjs</include> + <include>$(SRCDIR)/parser</include> <include>$(SRCDIR)/pcre</include> <include>$(SRCDIR)/profiler</include> <include>$(SRCDIR)/runtime</include> - <include>$(SRCDIR)/VM</include> + <include>$(SRCDIR)/interpreter</include> + <include>$(SRCDIR)/bytecode</include> + <include>$(SRCDIR)/wrec</include> + <include>$(SRCDIR)/jit</include> <include>$(SRCDIR)/wtf</include> <include>$(SRCDIR)/wtf/unicode</include> @@ -82,22 +88,26 @@ JavaScriptCore Bakefile project file. </template> - <exe id="jsc" template="icu,jscore,pthreads"> + <exe id="jsc" template="icu,jscore,pthreads,wxwk"> <cxx-rtti>off</cxx-rtti> <cxx-exceptions>off</cxx-exceptions> <debug-info>on</debug-info> <depends>jscore</depends> <include>$(SRCDIR)</include> <include>$(WK_ROOT)/JavaScriptCore</include> + <include>$(WK_ROOT)/JavaScriptCore/bytecompiler</include> <include>$(WK_ROOT)/JavaScriptCore/debugger</include> - <include>$(WK_ROOT)/JavaScriptCore/kjs</include> + <include>$(WK_ROOT)/JavaScriptCore/parser</include> <include>$(WK_ROOT)/JavaScriptCore/pcre</include> <include>$(WK_ROOT)/JavaScriptCore/profiler</include> <include>$(WK_ROOT)/JavaScriptCore/runtime</include> - <include>$(WK_ROOT)/JavaScriptCore/VM</include> + <include>$(WK_ROOT)/JavaScriptCore/interpreter</include> + <include>$(WK_ROOT)/JavaScriptCore/bytecode</include> + <include>$(WK_ROOT)/JavaScriptCore/jit</include> + <include>$(WK_ROOT)/JavaScriptCore/wrec</include> <include>$(WK_ROOT)/JavaScriptCore/wtf</include> <dirname>$(WKOUTPUTDIR)</dirname> - <sources>$(SRCDIR)/kjs/Shell.cpp</sources> + <sources>$(SRCDIR)/jsc.cpp</sources> <if cond="FORMAT=='gnu'"> <ldflags>$(WKOUTPUTDIR)/libjscore.a</ldflags> </if> @@ -120,7 +130,7 @@ JavaScriptCore Bakefile project file. <command>bash make-generated-sources.sh</command> </action> - <lib id="jscore" template="jscore_base"> + <lib id="jscore" template="jscore_base,wx-lib"> </lib> </makefile> diff --git a/JavaScriptCore/kjs/interpreter.h b/JavaScriptCore/kjs/interpreter.h deleted file mode 100644 index 0366063..0000000 --- a/JavaScriptCore/kjs/interpreter.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) - * Copyright (C) 2001 Peter Kelly (pmk@post.com) - * Copyright (C) 2003, 2007 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 KJS_Interpreter_h -#define KJS_Interpreter_h - -#include "JSValue.h" -#include <wtf/PassRefPtr.h> -#include <wtf/unicode/Unicode.h> - -namespace JSC { - - class Completion; - class ExecState; - class ScopeChain; - class SourceCode; - - class Interpreter { - public: - /** - * Parses the supplied ECMAScript code and checks for syntax errors. - * - * @param code The code to check - * @return A normal completion if there were no syntax errors in the code, - * otherwise a throw completion with the syntax error as its value. - */ - static Completion checkSyntax(ExecState*, const SourceCode&); - - /** - * Evaluates the supplied ECMAScript code. - * - * Since this method returns a Completion, you should check the type of - * completion to detect an error or before attempting to access the returned - * value. For example, if an error occurs during script execution and is not - * caught by the script, the completion type will be Throw. - * - * If the supplied code is invalid, a SyntaxError will be thrown. - * - * @param code The code to evaluate - * @param thisValue The value to pass in as the "this" value for the script - * execution. This should either be jsNull() or an Object. - * @return A completion object representing the result of the execution. - */ - static Completion evaluate(ExecState*, ScopeChain&, const SourceCode&, JSValue* thisValue = noValue()); - }; - -} // namespace JSC - -#endif // KJS_Interpreter_h diff --git a/JavaScriptCore/kjs/nodes2string.cpp b/JavaScriptCore/kjs/nodes2string.cpp deleted file mode 100644 index 4afefe0..0000000 --- a/JavaScriptCore/kjs/nodes2string.cpp +++ /dev/null @@ -1,936 +0,0 @@ -/* - * Copyright (C) 2002 Harri Porten (porten@kde.org) - * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 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 Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ - -#include "config.h" -#include "nodes.h" - -#include <wtf/MathExtras.h> -#include <wtf/StringExtras.h> -#include <wtf/unicode/Unicode.h> - -using namespace WTF; -using namespace Unicode; - -namespace JSC { - -// A simple text streaming class that helps with code indentation. - -enum EndlType { Endl }; -enum IndentType { Indent }; -enum UnindentType { Unindent }; -enum DotExprType { DotExpr }; - -class SourceStream { -public: - SourceStream() - : m_numberNeedsParens(false) - , m_atStartOfStatement(true) - , m_precedence(PrecExpression) - { - } - - UString toString() const { return m_string; } - - SourceStream& operator<<(const Identifier&); - SourceStream& operator<<(const UString&); - SourceStream& operator<<(const char*); - SourceStream& operator<<(double); - SourceStream& operator<<(char); - SourceStream& operator<<(EndlType); - SourceStream& operator<<(IndentType); - SourceStream& operator<<(UnindentType); - SourceStream& operator<<(DotExprType); - SourceStream& operator<<(Precedence); - SourceStream& operator<<(const Node*); - template <typename T> SourceStream& operator<<(const RefPtr<T>& n) { return *this << n.get(); } - -private: - UString m_string; - UString m_spacesForIndentation; - bool m_numberNeedsParens; - bool m_atStartOfStatement; - Precedence m_precedence; -}; - -// -------- - -static UString escapeStringForPrettyPrinting(const UString& s) -{ - UString escapedString; - - for (int i = 0; i < s.size(); i++) { - UChar c = s.data()[i]; - switch (c) { - case '\"': - escapedString += "\\\""; - break; - case '\n': - escapedString += "\\n"; - break; - case '\r': - escapedString += "\\r"; - break; - case '\t': - escapedString += "\\t"; - break; - case '\\': - escapedString += "\\\\"; - break; - default: - if (c < 128 && isPrintableChar(c)) - escapedString.append(c); - else { - char hexValue[7]; - snprintf(hexValue, 7, "\\u%04x", c); - escapedString += hexValue; - } - } - } - - return escapedString; -} - -static const char* operatorString(Operator oper) -{ - switch (oper) { - case OpEqual: - return "="; - case OpMultEq: - return "*="; - case OpDivEq: - return "/="; - case OpPlusEq: - return "+="; - case OpMinusEq: - return "-="; - case OpLShift: - return "<<="; - case OpRShift: - return ">>="; - case OpURShift: - return ">>>="; - case OpAndEq: - return "&="; - case OpXOrEq: - return "^="; - case OpOrEq: - return "|="; - case OpModEq: - return "%="; - case OpPlusPlus: - return "++"; - case OpMinusMinus: - return "--"; - } - ASSERT_NOT_REACHED(); - return "???"; -} - -static bool isParserRoundTripNumber(const UString& string) -{ - double number = string.toDouble(false, false); - if (isnan(number) || isinf(number)) - return false; - return string == UString::from(number); -} - -// -------- - -SourceStream& SourceStream::operator<<(char c) -{ - m_numberNeedsParens = false; - m_atStartOfStatement = false; - // use unsigned char to zero-extend instead of sign-extend - UChar ch(static_cast<unsigned char>(c)); - m_string.append(ch); - return *this; -} - -SourceStream& SourceStream::operator<<(const char* s) -{ - m_numberNeedsParens = false; - m_atStartOfStatement = false; - m_string += s; - return *this; -} - -SourceStream& SourceStream::operator<<(double value) -{ - bool needParens = m_numberNeedsParens; - m_numberNeedsParens = false; - m_atStartOfStatement = false; - - if (needParens) - m_string.append('('); - m_string += UString::from(value); - if (needParens) - m_string.append(')'); - - return *this; -} - -SourceStream& SourceStream::operator<<(const UString& s) -{ - m_numberNeedsParens = false; - m_atStartOfStatement = false; - m_string += s; - return *this; -} - -SourceStream& SourceStream::operator<<(const Identifier& s) -{ - m_numberNeedsParens = false; - m_atStartOfStatement = false; - m_string += s.ustring(); - return *this; -} - -SourceStream& SourceStream::operator<<(const Node* n) -{ - bool needParens = (m_precedence != PrecExpression && n->precedence() > m_precedence) || (m_atStartOfStatement && n->needsParensIfLeftmost()); - m_precedence = PrecExpression; - if (!n) - return *this; - if (needParens) { - m_numberNeedsParens = false; - m_string.append('('); - } - n->streamTo(*this); - if (needParens) - m_string.append(')'); - return *this; -} - -SourceStream& SourceStream::operator<<(EndlType) -{ - m_numberNeedsParens = false; - m_atStartOfStatement = true; - m_string.append('\n'); - m_string.append(m_spacesForIndentation); - return *this; -} - -SourceStream& SourceStream::operator<<(IndentType) -{ - m_numberNeedsParens = false; - m_atStartOfStatement = false; - m_spacesForIndentation += " "; - return *this; -} - -SourceStream& SourceStream::operator<<(UnindentType) -{ - m_numberNeedsParens = false; - m_atStartOfStatement = false; - m_spacesForIndentation = m_spacesForIndentation.substr(0, m_spacesForIndentation.size() - 2); - return *this; -} - -inline SourceStream& SourceStream::operator<<(DotExprType) -{ - m_numberNeedsParens = true; - return *this; -} - -inline SourceStream& SourceStream::operator<<(Precedence precedence) -{ - m_precedence = precedence; - return *this; -} - -static void streamLeftAssociativeBinaryOperator(SourceStream& s, Precedence precedence, - const char* operatorString, const Node* left, const Node* right) -{ - s << precedence << left - << ' ' << operatorString << ' ' - << static_cast<Precedence>(precedence - 1) << right; -} - -template <typename T> static inline void streamLeftAssociativeBinaryOperator(SourceStream& s, - Precedence p, const char* o, const RefPtr<T>& l, const RefPtr<T>& r) -{ - streamLeftAssociativeBinaryOperator(s, p, o, l.get(), r.get()); -} - -static inline void bracketNodeStreamTo(SourceStream& s, const RefPtr<ExpressionNode>& base, const RefPtr<ExpressionNode>& subscript) -{ - s << PrecCall << base.get() << "[" << subscript.get() << "]"; -} - -static inline void dotNodeStreamTo(SourceStream& s, const RefPtr<ExpressionNode>& base, const Identifier& ident) -{ - s << DotExpr << PrecCall << base.get() << "." << ident; -} - -// -------- - -UString Node::toString() const -{ - SourceStream stream; - streamTo(stream); - return stream.toString(); -} - -// -------- - -void NullNode::streamTo(SourceStream& s) const -{ - s << "null"; -} - -void BooleanNode::streamTo(SourceStream& s) const -{ - s << (m_value ? "true" : "false"); -} - -void NumberNode::streamTo(SourceStream& s) const -{ - s << value(); -} - -void StringNode::streamTo(SourceStream& s) const -{ - s << '"' << escapeStringForPrettyPrinting(m_value.ustring()) << '"'; -} - -void RegExpNode::streamTo(SourceStream& s) const -{ - s << '/' << m_pattern << '/' << m_flags; -} - -void ThisNode::streamTo(SourceStream& s) const -{ - s << "this"; -} - -void ResolveNode::streamTo(SourceStream& s) const -{ - s << m_ident; -} - -void ElementNode::streamTo(SourceStream& s) const -{ - for (const ElementNode* n = this; n; n = n->m_next.get()) { - for (int i = 0; i < n->m_elision; i++) - s << ','; - s << PrecAssignment << n->m_node; - if (n->m_next) - s << ','; - } -} - -void ArrayNode::streamTo(SourceStream& s) const -{ - s << '[' << m_element; - for (int i = 0; i < m_elision; i++) - s << ','; - // Parser consumes one elision comma if there's array elements - // present in the expression. - if (m_optional && m_element) - s << ','; - s << ']'; -} - -void ObjectLiteralNode::streamTo(SourceStream& s) const -{ - if (m_list) - s << "{ " << m_list << " }"; - else - s << "{ }"; -} - -void PropertyListNode::streamTo(SourceStream& s) const -{ - s << m_node; - for (const PropertyListNode* n = m_next.get(); n; n = n->m_next.get()) - s << ", " << n->m_node; -} - -void PropertyNode::streamTo(SourceStream& s) const -{ - switch (m_type) { - case Constant: { - UString propertyName = name().ustring(); - if (isParserRoundTripNumber(propertyName)) - s << propertyName; - else - s << '"' << escapeStringForPrettyPrinting(propertyName) << '"'; - s << ": " << PrecAssignment << m_assign; - break; - } - case Getter: - case Setter: { - const FuncExprNode* func = static_cast<const FuncExprNode*>(m_assign.get()); - if (m_type == Getter) - s << "get "; - else - s << "set "; - s << escapeStringForPrettyPrinting(name().ustring()) - << "(" << func->m_parameter << ')' << func->m_body; - break; - } - } -} - -void BracketAccessorNode::streamTo(SourceStream& s) const -{ - bracketNodeStreamTo(s, m_base, m_subscript); -} - -void DotAccessorNode::streamTo(SourceStream& s) const -{ - dotNodeStreamTo(s, m_base, m_ident); -} - -void ArgumentListNode::streamTo(SourceStream& s) const -{ - s << PrecAssignment << m_expr; - for (ArgumentListNode* n = m_next.get(); n; n = n->m_next.get()) - s << ", " << PrecAssignment << n->m_expr; -} - -void ArgumentsNode::streamTo(SourceStream& s) const -{ - s << '(' << m_listNode << ')'; -} - -void NewExprNode::streamTo(SourceStream& s) const -{ - s << "new " << PrecMember << m_expr << m_args; -} - -void EvalFunctionCallNode::streamTo(SourceStream& s) const -{ - s << "eval" << m_args; -} - -void FunctionCallValueNode::streamTo(SourceStream& s) const -{ - s << PrecCall << m_expr << m_args; -} - -void FunctionCallResolveNode::streamTo(SourceStream& s) const -{ - s << m_ident << m_args; -} - -void FunctionCallBracketNode::streamTo(SourceStream& s) const -{ - bracketNodeStreamTo(s, m_base, m_subscript); - s << m_args; -} - -void FunctionCallDotNode::streamTo(SourceStream& s) const -{ - dotNodeStreamTo(s, m_base, m_ident); - s << m_args; -} - -void PostfixResolveNode::streamTo(SourceStream& s) const -{ - s << m_ident << operatorString(m_operator); -} - -void PostfixBracketNode::streamTo(SourceStream& s) const -{ - bracketNodeStreamTo(s, m_base, m_subscript); - s << operatorString(m_operator); -} - -void PostfixDotNode::streamTo(SourceStream& s) const -{ - dotNodeStreamTo(s, m_base, m_ident); - s << operatorString(m_operator); -} - -void PostfixErrorNode::streamTo(SourceStream& s) const -{ - s << PrecLeftHandSide << m_expr; - if (m_operator == OpPlusPlus) - s << "++"; - else - s << "--"; -} - -void DeleteResolveNode::streamTo(SourceStream& s) const -{ - s << "delete " << m_ident; -} - -void DeleteBracketNode::streamTo(SourceStream& s) const -{ - s << "delete "; - bracketNodeStreamTo(s, m_base, m_subscript); -} - -void DeleteDotNode::streamTo(SourceStream& s) const -{ - s << "delete "; - dotNodeStreamTo(s, m_base, m_ident); -} - -void DeleteValueNode::streamTo(SourceStream& s) const -{ - s << "delete " << PrecUnary << m_expr; -} - -void VoidNode::streamTo(SourceStream& s) const -{ - s << "void " << PrecUnary << m_expr; -} - -void TypeOfValueNode::streamTo(SourceStream& s) const -{ - s << "typeof " << PrecUnary << m_expr; -} - -void TypeOfResolveNode::streamTo(SourceStream& s) const -{ - s << "typeof " << m_ident; -} - -void PrefixResolveNode::streamTo(SourceStream& s) const -{ - s << operatorString(m_operator) << m_ident; -} - -void PrefixBracketNode::streamTo(SourceStream& s) const -{ - s << operatorString(m_operator); - bracketNodeStreamTo(s, m_base, m_subscript); -} - -void PrefixDotNode::streamTo(SourceStream& s) const -{ - s << operatorString(m_operator); - dotNodeStreamTo(s, m_base, m_ident); -} - -void PrefixErrorNode::streamTo(SourceStream& s) const -{ - if (m_operator == OpPlusPlus) - s << "++" << PrecUnary << m_expr; - else - s << "--" << PrecUnary << m_expr; -} - -void UnaryPlusNode::streamTo(SourceStream& s) const -{ - s << "+ " << PrecUnary << m_expr; -} - -void NegateNode::streamTo(SourceStream& s) const -{ - s << "- " << PrecUnary << m_expr; -} - -void BitwiseNotNode::streamTo(SourceStream& s) const -{ - s << "~" << PrecUnary << m_expr; -} - -void LogicalNotNode::streamTo(SourceStream& s) const -{ - s << "!" << PrecUnary << m_expr; -} - -void MultNode::streamTo(SourceStream& s) const -{ - streamLeftAssociativeBinaryOperator(s, precedence(), "*", m_expr1, m_expr2); -} - -void DivNode::streamTo(SourceStream& s) const -{ - streamLeftAssociativeBinaryOperator(s, precedence(), "/", m_expr1, m_expr2); -} - -void ModNode::streamTo(SourceStream& s) const -{ - streamLeftAssociativeBinaryOperator(s, precedence(), "%", m_expr1, m_expr2); -} - -void AddNode::streamTo(SourceStream& s) const -{ - streamLeftAssociativeBinaryOperator(s, precedence(), "+", m_expr1, m_expr2); -} - -void SubNode::streamTo(SourceStream& s) const -{ - streamLeftAssociativeBinaryOperator(s, precedence(), "-", m_expr1, m_expr2); -} - -void LeftShiftNode::streamTo(SourceStream& s) const -{ - streamLeftAssociativeBinaryOperator(s, precedence(), "<<", m_expr1, m_expr2); -} - -void RightShiftNode::streamTo(SourceStream& s) const -{ - streamLeftAssociativeBinaryOperator(s, precedence(), ">>", m_expr1, m_expr2); -} - -void UnsignedRightShiftNode::streamTo(SourceStream& s) const -{ - streamLeftAssociativeBinaryOperator(s, precedence(), ">>>", m_expr1, m_expr2); -} - -void LessNode::streamTo(SourceStream& s) const -{ - streamLeftAssociativeBinaryOperator(s, precedence(), "<", m_expr1, m_expr2); -} - -void GreaterNode::streamTo(SourceStream& s) const -{ - streamLeftAssociativeBinaryOperator(s, precedence(), ">", m_expr1, m_expr2); -} - -void LessEqNode::streamTo(SourceStream& s) const -{ - streamLeftAssociativeBinaryOperator(s, precedence(), "<=", m_expr1, m_expr2); -} - -void GreaterEqNode::streamTo(SourceStream& s) const -{ - streamLeftAssociativeBinaryOperator(s, precedence(), ">=", m_expr1, m_expr2); -} - -void InstanceOfNode::streamTo(SourceStream& s) const -{ - streamLeftAssociativeBinaryOperator(s, precedence(), "instanceof", m_expr1, m_expr2); -} - -void InNode::streamTo(SourceStream& s) const -{ - streamLeftAssociativeBinaryOperator(s, precedence(), "in", m_expr1, m_expr2); -} - -void EqualNode::streamTo(SourceStream& s) const -{ - streamLeftAssociativeBinaryOperator(s, precedence(), "==", m_expr1, m_expr2); -} - -void NotEqualNode::streamTo(SourceStream& s) const -{ - streamLeftAssociativeBinaryOperator(s, precedence(), "!=", m_expr1, m_expr2); -} - -void StrictEqualNode::streamTo(SourceStream& s) const -{ - streamLeftAssociativeBinaryOperator(s, precedence(), "===", m_expr1, m_expr2); -} - -void NotStrictEqualNode::streamTo(SourceStream& s) const -{ - streamLeftAssociativeBinaryOperator(s, precedence(), "!==", m_expr1, m_expr2); -} - -void BitAndNode::streamTo(SourceStream& s) const -{ - streamLeftAssociativeBinaryOperator(s, precedence(), "&", m_expr1, m_expr2); -} - -void BitXOrNode::streamTo(SourceStream& s) const -{ - streamLeftAssociativeBinaryOperator(s, precedence(), "^", m_expr1, m_expr2); -} - -void BitOrNode::streamTo(SourceStream& s) const -{ - streamLeftAssociativeBinaryOperator(s, precedence(), "|", m_expr1, m_expr2); -} - -void LogicalOpNode::streamTo(SourceStream& s) const -{ - streamLeftAssociativeBinaryOperator(s, precedence(), (m_operator == OpLogicalAnd) ? "&&" : "||", m_expr1, m_expr2); -} - -void ConditionalNode::streamTo(SourceStream& s) const -{ - s << PrecLogicalOr << m_logical - << " ? " << PrecAssignment << m_expr1 - << " : " << PrecAssignment << m_expr2; -} - -void ReadModifyResolveNode::streamTo(SourceStream& s) const -{ - s << m_ident << ' ' << operatorString(m_operator) << ' ' << PrecAssignment << m_right; -} - -void AssignResolveNode::streamTo(SourceStream& s) const -{ - s << m_ident << " = " << PrecAssignment << m_right; -} - -void ReadModifyBracketNode::streamTo(SourceStream& s) const -{ - bracketNodeStreamTo(s, m_base, m_subscript); - s << ' ' << operatorString(m_operator) << ' ' << PrecAssignment << m_right; -} - -void AssignBracketNode::streamTo(SourceStream& s) const -{ - bracketNodeStreamTo(s, m_base, m_subscript); - s << " = " << PrecAssignment << m_right; -} - -void ReadModifyDotNode::streamTo(SourceStream& s) const -{ - dotNodeStreamTo(s, m_base, m_ident); - s << ' ' << operatorString(m_operator) << ' ' << PrecAssignment << m_right; -} - -void AssignDotNode::streamTo(SourceStream& s) const -{ - dotNodeStreamTo(s, m_base, m_ident); - s << " = " << PrecAssignment << m_right; -} - -void AssignErrorNode::streamTo(SourceStream& s) const -{ - s << PrecLeftHandSide << m_left << ' ' - << operatorString(m_operator) << ' ' << PrecAssignment << m_right; -} - -void CommaNode::streamTo(SourceStream& s) const -{ - s << PrecAssignment << m_expr1 << ", " << PrecAssignment << m_expr2; -} - -void ConstDeclNode::streamTo(SourceStream& s) const -{ - s << m_ident; - if (m_init) - s << " = " << PrecAssignment << m_init; - for (ConstDeclNode* n = m_next.get(); n; n = n->m_next.get()) { - s << ", " << n->m_ident; - if (n->m_init) - s << " = " << PrecAssignment << n->m_init; - } -} - -void ConstStatementNode::streamTo(SourceStream& s) const -{ - s << Endl << "const " << m_next << ';'; -} - -static inline void statementListStreamTo(const Vector<RefPtr<StatementNode> >& nodes, SourceStream& s) -{ - for (Vector<RefPtr<StatementNode> >::const_iterator ptr = nodes.begin(); ptr != nodes.end(); ptr++) - s << *ptr; -} - -void BlockNode::streamTo(SourceStream& s) const -{ - s << Endl << "{" << Indent; - statementListStreamTo(m_children, s); - s << Unindent << Endl << "}"; -} - -void ScopeNode::streamTo(SourceStream& s) const -{ - s << Endl << "{" << Indent; - - bool printedVar = false; - for (size_t i = 0; i < m_varStack.size(); ++i) { - if (m_varStack[i].second == 0) { - if (!printedVar) { - s << Endl << "var "; - printedVar = true; - } else - s << ", "; - s << m_varStack[i].first; - } - } - if (printedVar) - s << ';'; - - statementListStreamTo(m_children, s); - s << Unindent << Endl << "}"; -} - -void EmptyStatementNode::streamTo(SourceStream& s) const -{ - s << Endl << ';'; -} - -void DebuggerStatementNode::streamTo(SourceStream& s) const -{ - s << Endl << "debugger;"; -} - -void ExprStatementNode::streamTo(SourceStream& s) const -{ - s << Endl << m_expr << ';'; -} - -void VarStatementNode::streamTo(SourceStream& s) const -{ - s << Endl << "var " << m_expr << ';'; -} - -void IfNode::streamTo(SourceStream& s) const -{ - s << Endl << "if (" << m_condition << ')' << Indent << m_ifBlock << Unindent; -} - -void IfElseNode::streamTo(SourceStream& s) const -{ - IfNode::streamTo(s); - s << Endl << "else" << Indent << m_elseBlock << Unindent; -} - -void DoWhileNode::streamTo(SourceStream& s) const -{ - s << Endl << "do " << Indent << m_statement << Unindent << Endl - << "while (" << m_expr << ");"; -} - -void WhileNode::streamTo(SourceStream& s) const -{ - s << Endl << "while (" << m_expr << ')' << Indent << m_statement << Unindent; -} - -void ForNode::streamTo(SourceStream& s) const -{ - s << Endl << "for (" - << (m_expr1WasVarDecl ? "var " : "") - << m_expr1 - << "; " << m_expr2 - << "; " << m_expr3 - << ')' << Indent << m_statement << Unindent; -} - -void ForInNode::streamTo(SourceStream& s) const -{ - s << Endl << "for ("; - if (m_identIsVarDecl) { - s << "var "; - if (m_init) - s << m_init; - else - s << PrecLeftHandSide << m_lexpr; - } else - s << PrecLeftHandSide << m_lexpr; - - s << " in " << m_expr << ')' << Indent << m_statement << Unindent; -} - -void ContinueNode::streamTo(SourceStream& s) const -{ - s << Endl << "continue"; - if (!m_ident.isNull()) - s << ' ' << m_ident; - s << ';'; -} - -void BreakNode::streamTo(SourceStream& s) const -{ - s << Endl << "break"; - if (!m_ident.isNull()) - s << ' ' << m_ident; - s << ';'; -} - -void ReturnNode::streamTo(SourceStream& s) const -{ - s << Endl << "return"; - if (m_value) - s << ' ' << m_value; - s << ';'; -} - -void WithNode::streamTo(SourceStream& s) const -{ - s << Endl << "with (" << m_expr << ") " << m_statement; -} - -void CaseClauseNode::streamTo(SourceStream& s) const -{ - s << Endl; - if (m_expr) - s << "case " << m_expr; - else - s << "default"; - s << ":" << Indent; - statementListStreamTo(m_children, s); - s << Unindent; -} - -void ClauseListNode::streamTo(SourceStream& s) const -{ - for (const ClauseListNode* n = this; n; n = n->getNext()) - s << n->getClause(); -} - -void CaseBlockNode::streamTo(SourceStream& s) const -{ - for (const ClauseListNode* n = m_list1.get(); n; n = n->getNext()) - s << n->getClause(); - s << m_defaultClause; - for (const ClauseListNode* n = m_list2.get(); n; n = n->getNext()) - s << n->getClause(); -} - -void SwitchNode::streamTo(SourceStream& s) const -{ - s << Endl << "switch (" << m_expr << ") {" - << Indent << m_block << Unindent - << Endl << "}"; -} - -void LabelNode::streamTo(SourceStream& s) const -{ - s << Endl << m_name << ":" << Indent << m_statement << Unindent; -} - -void ThrowNode::streamTo(SourceStream& s) const -{ - s << Endl << "throw " << m_expr << ';'; -} - -void TryNode::streamTo(SourceStream& s) const -{ - s << Endl << "try " << m_tryBlock; - if (m_catchBlock) - s << Endl << "catch (" << m_exceptionIdent << ')' << m_catchBlock; - if (m_finallyBlock) - s << Endl << "finally " << m_finallyBlock; -} - -void ParameterNode::streamTo(SourceStream& s) const -{ - s << m_ident; - for (ParameterNode* n = m_next.get(); n; n = n->m_next.get()) - s << ", " << n->m_ident; -} - -void FuncDeclNode::streamTo(SourceStream& s) const -{ - s << Endl << "function " << m_ident << '(' << m_parameter << ')' << m_body; -} - -void FuncExprNode::streamTo(SourceStream& s) const -{ - s << "function " << m_ident << '(' << m_parameter << ')' << m_body; -} - -} // namespace JSC diff --git a/JavaScriptCore/kjs/operations.h b/JavaScriptCore/kjs/operations.h deleted file mode 100644 index fad9720..0000000 --- a/JavaScriptCore/kjs/operations.h +++ /dev/null @@ -1,137 +0,0 @@ -/* - * This file is part of the KDE libraries - * Copyright (C) 1999-2000 Harri Porten (porten@kde.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 _KJS_OPERATIONS_H_ -#define _KJS_OPERATIONS_H_ - -#include "JSImmediate.h" -#include "JSNumberCell.h" -#include "JSString.h" - -namespace JSC { - - // ECMA 11.9.3 - bool equal(ExecState*, JSValue*, JSValue*); - bool equalSlowCase(ExecState*, JSValue*, JSValue*); - - ALWAYS_INLINE bool equalSlowCaseInline(ExecState* exec, JSValue* v1, JSValue* v2) - { - ASSERT(!JSImmediate::areBothImmediateNumbers(v1, v2)); - - do { - if (v1->isNumber() && v2->isNumber()) - return v1->uncheckedGetNumber() == v2->uncheckedGetNumber(); - - bool s1 = v1->isString(); - bool s2 = v2->isString(); - if (s1 && s2) - return asString(v1)->value() == asString(v2)->value(); - - if (v1->isUndefinedOrNull()) { - if (v2->isUndefinedOrNull()) - return true; - if (JSImmediate::isImmediate(v2)) - return false; - return v2->asCell()->structureID()->typeInfo().masqueradesAsUndefined(); - } - - if (v2->isUndefinedOrNull()) { - if (JSImmediate::isImmediate(v1)) - return false; - return v1->asCell()->structureID()->typeInfo().masqueradesAsUndefined(); - } - - if (v1->isObject()) { - if (v2->isObject()) - return v1 == v2; - JSValue* p1 = v1->toPrimitive(exec); - if (exec->hadException()) - return false; - v1 = p1; - if (JSImmediate::areBothImmediateNumbers(v1, v2)) - return v1 == v2; - continue; - } - - if (v2->isObject()) { - JSValue* p2 = v2->toPrimitive(exec); - if (exec->hadException()) - return false; - v2 = p2; - if (JSImmediate::areBothImmediateNumbers(v1, v2)) - return v1 == v2; - continue; - } - - if (s1 || s2) { - double d1 = v1->toNumber(exec); - double d2 = v2->toNumber(exec); - return d1 == d2; - } - - if (v1->isBoolean()) { - if (v2->isNumber()) - return static_cast<double>(v1->getBoolean()) == v2->uncheckedGetNumber(); - } else if (v2->isBoolean()) { - if (v1->isNumber()) - return v1->uncheckedGetNumber() == static_cast<double>(v2->getBoolean()); - } - - return v1 == v2; - } while (true); - } - - - bool strictEqual(JSValue*, JSValue*); - bool strictEqualSlowCase(JSValue*, JSValue*); - - inline bool strictEqualSlowCaseInline(JSValue* v1, JSValue* v2) - { - ASSERT(!JSImmediate::areBothImmediate(v1, v2)); - - if (JSImmediate::isEitherImmediate(v1, v2)) { - ASSERT(v1 == JSImmediate::zeroImmediate() || v2 == JSImmediate::zeroImmediate()); - ASSERT(v1 != v2); - - // The reason we can't just return false here is that 0 === -0, - // and while the former is an immediate number, the latter is not. - if (v1 == JSImmediate::zeroImmediate()) - return asCell(v2)->isNumber() && asNumberCell(v2)->value() == 0; - return asCell(v1)->isNumber() && asNumberCell(v1)->value() == 0; - } - - if (asCell(v1)->isNumber()) { - return asCell(v2)->isNumber() - && asNumberCell(v1)->value() == asNumberCell(v2)->value(); - } - - if (asCell(v1)->isString()) { - return asCell(v2)->isString() - && asString(v1)->value() == asString(v2)->value(); - } - - return v1 == v2; - } - - JSValue* throwOutOfMemoryError(ExecState*); -} - -#endif diff --git a/JavaScriptCore/kjs/protect.h b/JavaScriptCore/kjs/protect.h deleted file mode 100644 index b317424..0000000 --- a/JavaScriptCore/kjs/protect.h +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright (C) 2004, 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 protect_h -#define protect_h - -#include "JSCell.h" -#include "collector.h" - -namespace JSC { - - inline void gcProtect(JSCell* val) - { - Heap::heap(val)->protect(val); - } - - inline void gcUnprotect(JSCell* val) - { - Heap::heap(val)->unprotect(val); - } - - inline void gcProtectNullTolerant(JSCell* val) - { - if (val) - gcProtect(val); - } - - inline void gcUnprotectNullTolerant(JSCell* val) - { - if (val) - gcUnprotect(val); - } - - inline void gcProtect(JSValue* value) - { - if (JSImmediate::isImmediate(value)) - return; - gcProtect(asCell(value)); - } - - inline void gcUnprotect(JSValue* value) - { - if (JSImmediate::isImmediate(value)) - return; - gcUnprotect(asCell(value)); - } - - inline void gcProtectNullTolerant(JSValue* value) - { - if (!value || JSImmediate::isImmediate(value)) - return; - gcProtect(asCell(value)); - } - - inline void gcUnprotectNullTolerant(JSValue* value) - { - if (!value || JSImmediate::isImmediate(value)) - return; - gcUnprotect(asCell(value)); - } - - // FIXME: Share more code with RefPtr template? The only differences are the ref/deref operation - // and the implicit conversion to raw pointer - template <class T> class ProtectedPtr { - public: - ProtectedPtr() : m_ptr(0) { } - ProtectedPtr(T* ptr); - ProtectedPtr(const ProtectedPtr&); - ~ProtectedPtr(); - - template <class U> ProtectedPtr(const ProtectedPtr<U>&); - - T* get() const { return m_ptr; } - operator T*() const { return m_ptr; } - T* operator->() const { return m_ptr; } - - bool operator!() const { return !m_ptr; } - - ProtectedPtr& operator=(const ProtectedPtr&); - ProtectedPtr& operator=(T*); - - private: - T* m_ptr; - }; - - template <class T> ProtectedPtr<T>::ProtectedPtr(T* ptr) - : m_ptr(ptr) - { - gcProtectNullTolerant(m_ptr); - } - - template <class T> ProtectedPtr<T>::ProtectedPtr(const ProtectedPtr& o) - : m_ptr(o.get()) - { - gcProtectNullTolerant(m_ptr); - } - - template <class T> ProtectedPtr<T>::~ProtectedPtr() - { - gcUnprotectNullTolerant(m_ptr); - } - - template <class T> template <class U> ProtectedPtr<T>::ProtectedPtr(const ProtectedPtr<U>& o) - : m_ptr(o.get()) - { - gcProtectNullTolerant(m_ptr); - } - - template <class T> ProtectedPtr<T>& ProtectedPtr<T>::operator=(const ProtectedPtr<T>& o) - { - T* optr = o.m_ptr; - gcProtectNullTolerant(optr); - gcUnprotectNullTolerant(m_ptr); - m_ptr = optr; - return *this; - } - - template <class T> inline ProtectedPtr<T>& ProtectedPtr<T>::operator=(T* optr) - { - gcProtectNullTolerant(optr); - gcUnprotectNullTolerant(m_ptr); - m_ptr = optr; - return *this; - } - - template <class T> inline bool operator==(const ProtectedPtr<T>& a, const ProtectedPtr<T>& b) { return a.get() == b.get(); } - template <class T> inline bool operator==(const ProtectedPtr<T>& a, const T* b) { return a.get() == b; } - template <class T> inline bool operator==(const T* a, const ProtectedPtr<T>& b) { return a == b.get(); } - - template <class T> inline bool operator!=(const ProtectedPtr<T>& a, const ProtectedPtr<T>& b) { return a.get() != b.get(); } - template <class T> inline bool operator!=(const ProtectedPtr<T>& a, const T* b) { return a.get() != b; } - template <class T> inline bool operator!=(const T* a, const ProtectedPtr<T>& b) { return a != b.get(); } - -} // namespace JSC - -#endif // protect_h diff --git a/JavaScriptCore/make-generated-sources.sh b/JavaScriptCore/make-generated-sources.sh index e1e247b..943a7cc 100755 --- a/JavaScriptCore/make-generated-sources.sh +++ b/JavaScriptCore/make-generated-sources.sh @@ -2,7 +2,7 @@ export SRCROOT=$PWD export WebCore=$PWD -export CREATE_HASH_TABLE="$SRCROOT/kjs/create_hash_table" +export CREATE_HASH_TABLE="$SRCROOT/create_hash_table" mkdir -p DerivedSources/JavaScriptCore cd DerivedSources/JavaScriptCore diff --git a/JavaScriptCore/masm/X86Assembler.h b/JavaScriptCore/masm/X86Assembler.h deleted file mode 100644 index 547c94e..0000000 --- a/JavaScriptCore/masm/X86Assembler.h +++ /dev/null @@ -1,1262 +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 X86Assembler_h -#define X86Assembler_h - -#if ENABLE(MASM) && PLATFORM(X86) - -#include <wtf/Assertions.h> -#include <wtf/AlwaysInline.h> -#include <wtf/FastMalloc.h> - -#if HAVE(MMAN) -#include <sys/mman.h> -#endif - -#include <string.h> - -namespace JSC { - -class JITCodeBuffer { -public: - JITCodeBuffer(int size) - : m_buffer(static_cast<char*>(fastMalloc(size))) - , m_size(size) - , m_index(0) - { - } - - ~JITCodeBuffer() - { - fastFree(m_buffer); - } - - void ensureSpace(int space) - { - if (m_index > m_size - space) - growBuffer(); - } - - void putByteUnchecked(int value) - { - m_buffer[m_index] = value; - m_index++; - } - - void putByte(int value) - { - if (m_index > m_size - 4) - growBuffer(); - putByteUnchecked(value); - } - - void putShortUnchecked(int value) - { - *(short*)(&m_buffer[m_index]) = value; - m_index += 2; - } - - void putShort(int value) - { - if (m_index > m_size - 4) - growBuffer(); - putShortUnchecked(value); - } - - void putIntUnchecked(int value) - { - *reinterpret_cast<int*>(&m_buffer[m_index]) = value; - m_index += 4; - } - - void putInt(int value) - { - if (m_index > m_size - 4) - growBuffer(); - putIntUnchecked(value); - } - - void* getEIP() - { - return m_buffer + m_index; - } - - void* start() - { - return m_buffer; - } - - int getOffset() - { - return m_index; - } - - JITCodeBuffer* reset() - { - m_index = 0; - return this; - } - - void* copy() - { - if (!m_index) - return 0; - - void* result = WTF::fastMallocExecutable(m_index); - - if (!result) - return 0; - - return memcpy(result, m_buffer, m_index); - } - -private: - void growBuffer() - { - m_size += m_size / 2; - m_buffer = static_cast<char*>(fastRealloc(m_buffer, m_size)); - } - - char* m_buffer; - int m_size; - int m_index; -}; - -#define MODRM(type, reg, rm) ((type << 6) | (reg << 3) | (rm)) -#define SIB(type, reg, rm) MODRM(type, reg, rm) -#define CAN_SIGN_EXTEND_8_32(value) (value == ((int)(signed char)value)) - -namespace X86 { - typedef enum { - eax, - ecx, - edx, - ebx, - esp, - ebp, - esi, - edi, - - noBase = ebp, - hasSib = esp, - noScale = esp, - } RegisterID; - - typedef enum { - xmm0, - xmm1, - xmm2, - xmm3, - xmm4, - xmm5, - xmm6, - xmm7, - } XMMRegisterID; -} - -class X86Assembler { -public: - typedef X86::RegisterID RegisterID; - typedef X86::XMMRegisterID XMMRegisterID; - typedef enum { - OP_ADD_EvGv = 0x01, - OP_ADD_GvEv = 0x03, - OP_OR_EvGv = 0x09, - OP_OR_GvEv = 0x0B, - OP_2BYTE_ESCAPE = 0x0F, - OP_AND_EvGv = 0x21, - OP_SUB_EvGv = 0x29, - OP_SUB_GvEv = 0x2B, - PRE_PREDICT_BRANCH_NOT_TAKEN = 0x2E, - OP_XOR_EvGv = 0x31, - OP_CMP_EvGv = 0x39, - OP_CMP_GvEv = 0x3B, - OP_PUSH_EAX = 0x50, - OP_POP_EAX = 0x58, - PRE_OPERAND_SIZE = 0x66, - PRE_SSE_66 = 0x66, - OP_PUSH_Iz = 0x68, - OP_IMUL_GvEvIz = 0x69, - OP_GROUP1_EvIz = 0x81, - OP_GROUP1_EvIb = 0x83, - OP_TEST_EvGv = 0x85, - OP_MOV_EvGv = 0x89, - OP_MOV_GvEv = 0x8B, - OP_LEA = 0x8D, - OP_GROUP1A_Ev = 0x8F, - OP_CDQ = 0x99, - OP_SETE = 0x94, - OP_SETNE = 0x95, - OP_GROUP2_EvIb = 0xC1, - OP_RET = 0xC3, - OP_GROUP11_EvIz = 0xC7, - OP_INT3 = 0xCC, - OP_GROUP2_Ev1 = 0xD1, - OP_GROUP2_EvCL = 0xD3, - OP_CALL_rel32 = 0xE8, - OP_JMP_rel32 = 0xE9, - PRE_SSE_F2 = 0xF2, - OP_GROUP3_Ev = 0xF7, - OP_GROUP3_EvIz = 0xF7, // OP_GROUP3_Ev has an immediate, when instruction is a test. - OP_GROUP5_Ev = 0xFF, - - OP2_MOVSD_VsdWsd = 0x10, - OP2_MOVSD_WsdVsd = 0x11, - OP2_CVTSI2SD_VsdEd = 0x2A, - OP2_CVTTSD2SI_GdWsd = 0x2C, - OP2_UCOMISD_VsdWsd = 0x2E, - OP2_XORPD_VsdWsd = 0x57, - OP2_ADDSD_VsdWsd = 0x58, - OP2_MULSD_VsdWsd = 0x59, - OP2_SUBSD_VsdWsd = 0x5C, - OP2_MOVD_EdVd = 0x7E, - OP2_JO_rel32 = 0x80, - OP2_JB_rel32 = 0x82, - OP2_JAE_rel32 = 0x83, - OP2_JE_rel32 = 0x84, - OP2_JNE_rel32 = 0x85, - OP2_JBE_rel32 = 0x86, - OP2_JA_rel32 = 0x87, - OP2_JS_rel32 = 0x88, - OP2_JP_rel32 = 0x8A, - OP2_JL_rel32 = 0x8C, - OP2_JGE_rel32 = 0x8D, - OP2_JLE_rel32 = 0x8E, - OP2_JG_rel32 = 0x8F, - OP2_IMUL_GvEv = 0xAF, - OP2_MOVZX_GvEb = 0xB6, - OP2_MOVZX_GvEw = 0xB7, - OP2_PEXTRW_GdUdIb = 0xC5, - - GROUP1_OP_ADD = 0, - GROUP1_OP_OR = 1, - GROUP1_OP_AND = 4, - GROUP1_OP_SUB = 5, - GROUP1_OP_XOR = 6, - GROUP1_OP_CMP = 7, - - GROUP1A_OP_POP = 0, - - GROUP2_OP_SHL = 4, - GROUP2_OP_SAR = 7, - - GROUP3_OP_TEST = 0, - GROUP3_OP_NEG = 3, - GROUP3_OP_IDIV = 7, - - GROUP5_OP_CALLN = 2, - GROUP5_OP_JMPN = 4, - GROUP5_OP_PUSH = 6, - - GROUP11_MOV = 0, - } OpcodeID; - - static const int MAX_INSTRUCTION_SIZE = 16; - - X86Assembler(JITCodeBuffer* m_buffer) - : m_buffer(m_buffer) - { - m_buffer->reset(); - } - - void emitInt3() - { - m_buffer->putByte(OP_INT3); - } - - void pushl_r(RegisterID reg) - { - m_buffer->putByte(OP_PUSH_EAX + reg); - } - - void pushl_m(int offset, RegisterID base) - { - m_buffer->putByte(OP_GROUP5_Ev); - emitModRm_opm(GROUP5_OP_PUSH, base, offset); - } - - void pushl_i32(int imm) - { - m_buffer->putByte(OP_PUSH_Iz); - m_buffer->putInt(imm); - } - - void popl_r(RegisterID reg) - { - m_buffer->putByte(OP_POP_EAX + reg); - } - - void popl_m(int offset, RegisterID base) - { - m_buffer->putByte(OP_GROUP1A_Ev); - emitModRm_opm(GROUP1A_OP_POP, base, offset); - } - - void movl_rr(RegisterID src, RegisterID dst) - { - m_buffer->putByte(OP_MOV_EvGv); - emitModRm_rr(src, dst); - } - - void addl_rr(RegisterID src, RegisterID dst) - { - m_buffer->putByte(OP_ADD_EvGv); - emitModRm_rr(src, dst); - } - - void addl_i8r(int imm, RegisterID dst) - { - m_buffer->putByte(OP_GROUP1_EvIb); - emitModRm_opr(GROUP1_OP_ADD, dst); - m_buffer->putByte(imm); - } - - void addl_i8m(int imm, void* addr) - { - m_buffer->putByte(OP_GROUP1_EvIb); - emitModRm_opm(GROUP1_OP_ADD, addr); - m_buffer->putByte(imm); - } - - void addl_i32r(int imm, RegisterID dst) - { - m_buffer->putByte(OP_GROUP1_EvIz); - emitModRm_opr(GROUP1_OP_ADD, dst); - m_buffer->putInt(imm); - } - - void addl_mr(int offset, RegisterID base, RegisterID dst) - { - m_buffer->putByte(OP_ADD_GvEv); - emitModRm_rm(dst, base, offset); - } - - void andl_rr(RegisterID src, RegisterID dst) - { - m_buffer->putByte(OP_AND_EvGv); - emitModRm_rr(src, dst); - } - - void andl_i32r(int imm, RegisterID dst) - { - m_buffer->putByte(OP_GROUP1_EvIz); - emitModRm_opr(GROUP1_OP_AND, dst); - m_buffer->putInt(imm); - } - - void cmpl_i8r(int imm, RegisterID dst) - { - m_buffer->putByte(OP_GROUP1_EvIb); - emitModRm_opr(GROUP1_OP_CMP, dst); - m_buffer->putByte(imm); - } - - void cmpl_rr(RegisterID src, RegisterID dst) - { - m_buffer->putByte(OP_CMP_EvGv); - emitModRm_rr(src, dst); - } - - void cmpl_rm(RegisterID src, int offset, RegisterID base) - { - m_buffer->putByte(OP_CMP_EvGv); - emitModRm_rm(src, base, offset); - } - - void cmpl_mr(int offset, RegisterID base, RegisterID dst) - { - m_buffer->putByte(OP_CMP_GvEv); - emitModRm_rm(dst, base, offset); - } - - void cmpl_i32r(int imm, RegisterID dst) - { - m_buffer->putByte(OP_GROUP1_EvIz); - emitModRm_opr(GROUP1_OP_CMP, dst); - m_buffer->putInt(imm); - } - - void cmpl_i32m(int imm, RegisterID dst) - { - m_buffer->putByte(OP_GROUP1_EvIz); - emitModRm_opm(GROUP1_OP_CMP, dst); - m_buffer->putInt(imm); - } - - void cmpl_i32m(int imm, int offset, RegisterID dst) - { - m_buffer->putByte(OP_GROUP1_EvIz); - emitModRm_opm(GROUP1_OP_CMP, dst, offset); - m_buffer->putInt(imm); - } - - void cmpl_i32m(int imm, void* addr) - { - m_buffer->putByte(OP_GROUP1_EvIz); - emitModRm_opm(GROUP1_OP_CMP, addr); - m_buffer->putInt(imm); - } - - void cmpl_i8m(int imm, int offset, RegisterID base, RegisterID index, int scale) - { - m_buffer->putByte(OP_GROUP1_EvIb); - emitModRm_opmsib(GROUP1_OP_CMP, base, index, scale, offset); - m_buffer->putByte(imm); - } - - void cmpw_rm(RegisterID src, RegisterID base, RegisterID index, int scale) - { - m_buffer->putByte(PRE_OPERAND_SIZE); - m_buffer->putByte(OP_CMP_EvGv); - emitModRm_rmsib(src, base, index, scale); - } - - void sete_r(RegisterID dst) - { - m_buffer->putByte(OP_2BYTE_ESCAPE); - m_buffer->putByte(OP_SETE); - m_buffer->putByte(MODRM(3, 0, dst)); - } - - void setz_r(RegisterID dst) - { - sete_r(dst); - } - - void setne_r(RegisterID dst) - { - m_buffer->putByte(OP_2BYTE_ESCAPE); - m_buffer->putByte(OP_SETNE); - m_buffer->putByte(MODRM(3, 0, dst)); - } - - void setnz_r(RegisterID dst) - { - setne_r(dst); - } - - void orl_rr(RegisterID src, RegisterID dst) - { - m_buffer->putByte(OP_OR_EvGv); - emitModRm_rr(src, dst); - } - - void orl_mr(int offset, RegisterID base, RegisterID dst) - { - m_buffer->putByte(OP_OR_GvEv); - emitModRm_rm(dst, base, offset); - } - - void orl_i32r(int imm, RegisterID dst) - { - m_buffer->putByte(OP_GROUP1_EvIb); - emitModRm_opr(GROUP1_OP_OR, dst); - m_buffer->putByte(imm); - } - - void subl_rr(RegisterID src, RegisterID dst) - { - m_buffer->putByte(OP_SUB_EvGv); - emitModRm_rr(src, dst); - } - - void subl_i8r(int imm, RegisterID dst) - { - m_buffer->putByte(OP_GROUP1_EvIb); - emitModRm_opr(GROUP1_OP_SUB, dst); - m_buffer->putByte(imm); - } - - void subl_i8m(int imm, void* addr) - { - m_buffer->putByte(OP_GROUP1_EvIb); - emitModRm_opm(GROUP1_OP_SUB, addr); - m_buffer->putByte(imm); - } - - void subl_i32r(int imm, RegisterID dst) - { - m_buffer->putByte(OP_GROUP1_EvIz); - emitModRm_opr(GROUP1_OP_SUB, dst); - m_buffer->putInt(imm); - } - - void subl_mr(int offset, RegisterID base, RegisterID dst) - { - m_buffer->putByte(OP_SUB_GvEv); - emitModRm_rm(dst, base, offset); - } - - void testl_i32r(int imm, RegisterID dst) - { - m_buffer->ensureSpace(MAX_INSTRUCTION_SIZE); - m_buffer->putByteUnchecked(OP_GROUP3_EvIz); - emitModRm_opr_Unchecked(GROUP3_OP_TEST, dst); - m_buffer->putIntUnchecked(imm); - } - - void testl_i32m(int imm, RegisterID dst) - { - m_buffer->putByte(OP_GROUP3_EvIz); - emitModRm_opm(GROUP3_OP_TEST, dst); - m_buffer->putInt(imm); - } - - void testl_i32m(int imm, int offset, RegisterID dst) - { - m_buffer->putByte(OP_GROUP3_EvIz); - emitModRm_opm(GROUP3_OP_TEST, dst, offset); - m_buffer->putInt(imm); - } - - void testl_rr(RegisterID src, RegisterID dst) - { - m_buffer->putByte(OP_TEST_EvGv); - emitModRm_rr(src, dst); - } - - void xorl_i8r(int imm, RegisterID dst) - { - m_buffer->putByte(OP_GROUP1_EvIb); - emitModRm_opr(GROUP1_OP_XOR, dst); - m_buffer->putByte(imm); - } - - void xorl_rr(RegisterID src, RegisterID dst) - { - m_buffer->putByte(OP_XOR_EvGv); - emitModRm_rr(src, dst); - } - - void sarl_i8r(int imm, RegisterID dst) - { - if (imm == 1) { - m_buffer->putByte(OP_GROUP2_Ev1); - emitModRm_opr(GROUP2_OP_SAR, dst); - } else { - m_buffer->putByte(OP_GROUP2_EvIb); - emitModRm_opr(GROUP2_OP_SAR, dst); - m_buffer->putByte(imm); - } - } - - void sarl_CLr(RegisterID dst) - { - m_buffer->putByte(OP_GROUP2_EvCL); - emitModRm_opr(GROUP2_OP_SAR, dst); - } - - void shl_i8r(int imm, RegisterID dst) - { - if (imm == 1) { - m_buffer->putByte(OP_GROUP2_Ev1); - emitModRm_opr(GROUP2_OP_SHL, dst); - } else { - m_buffer->putByte(OP_GROUP2_EvIb); - emitModRm_opr(GROUP2_OP_SHL, dst); - m_buffer->putByte(imm); - } - } - - void shll_CLr(RegisterID dst) - { - m_buffer->putByte(OP_GROUP2_EvCL); - emitModRm_opr(GROUP2_OP_SHL, dst); - } - - void imull_rr(RegisterID src, RegisterID dst) - { - m_buffer->putByte(OP_2BYTE_ESCAPE); - m_buffer->putByte(OP2_IMUL_GvEv); - emitModRm_rr(dst, src); - } - - void imull_i32r(RegisterID src, int32_t value, RegisterID dst) - { - m_buffer->putByte(OP_IMUL_GvEvIz); - emitModRm_rr(dst, src); - m_buffer->putInt(value); - } - - void idivl_r(RegisterID dst) - { - m_buffer->putByte(OP_GROUP3_Ev); - emitModRm_opr(GROUP3_OP_IDIV, dst); - } - - void negl_r(RegisterID dst) - { - m_buffer->putByte(OP_GROUP3_Ev); - emitModRm_opr(GROUP3_OP_NEG, dst); - } - - void cdq() - { - m_buffer->putByte(OP_CDQ); - } - - void movl_mr(RegisterID base, RegisterID dst) - { - m_buffer->putByte(OP_MOV_GvEv); - emitModRm_rm(dst, base); - } - - void movl_mr(int offset, RegisterID base, RegisterID dst) - { - m_buffer->ensureSpace(MAX_INSTRUCTION_SIZE); - m_buffer->putByteUnchecked(OP_MOV_GvEv); - emitModRm_rm_Unchecked(dst, base, offset); - } - - void movl_mr(void* addr, RegisterID dst) - { - m_buffer->putByte(OP_MOV_GvEv); - emitModRm_rm(dst, addr); - } - - void movl_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst) - { - m_buffer->putByte(OP_MOV_GvEv); - emitModRm_rmsib(dst, base, index, scale, offset); - } - - void movzbl_rr(RegisterID src, RegisterID dst) - { - m_buffer->putByte(OP_2BYTE_ESCAPE); - m_buffer->putByte(OP2_MOVZX_GvEb); - emitModRm_rr(dst, src); - } - - void movzwl_mr(int offset, RegisterID base, RegisterID dst) - { - m_buffer->putByte(OP_2BYTE_ESCAPE); - m_buffer->putByte(OP2_MOVZX_GvEw); - emitModRm_rm(dst, base, offset); - } - - void movzwl_mr(RegisterID base, RegisterID index, int scale, RegisterID dst) - { - m_buffer->putByte(OP_2BYTE_ESCAPE); - m_buffer->putByte(OP2_MOVZX_GvEw); - emitModRm_rmsib(dst, base, index, scale); - } - - void movzwl_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst) - { - m_buffer->putByte(OP_2BYTE_ESCAPE); - m_buffer->putByte(OP2_MOVZX_GvEw); - emitModRm_rmsib(dst, base, index, scale, offset); - } - - void movl_rm(RegisterID src, RegisterID base) - { - m_buffer->putByte(OP_MOV_EvGv); - emitModRm_rm(src, base); - } - - void movl_rm(RegisterID src, int offset, RegisterID base) - { - m_buffer->ensureSpace(MAX_INSTRUCTION_SIZE); - m_buffer->putByteUnchecked(OP_MOV_EvGv); - emitModRm_rm_Unchecked(src, base, offset); - } - - void movl_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale) - { - m_buffer->putByte(OP_MOV_EvGv); - emitModRm_rmsib(src, base, index, scale, offset); - } - - void movl_i32r(int imm, RegisterID dst) - { - m_buffer->putByte(OP_GROUP11_EvIz); - emitModRm_opr(GROUP11_MOV, dst); - m_buffer->putInt(imm); - } - - void movl_i32m(int imm, int offset, RegisterID base) - { - m_buffer->ensureSpace(MAX_INSTRUCTION_SIZE); - m_buffer->putByteUnchecked(OP_GROUP11_EvIz); - emitModRm_opm_Unchecked(GROUP11_MOV, base, offset); - m_buffer->putIntUnchecked(imm); - } - - void movl_i32m(int imm, void* addr) - { - m_buffer->putByte(OP_GROUP11_EvIz); - emitModRm_opm(GROUP11_MOV, addr); - m_buffer->putInt(imm); - } - - void leal_mr(int offset, RegisterID base, RegisterID dst) - { - m_buffer->putByte(OP_LEA); - emitModRm_rm(dst, base, offset); - } - - void leal_mr(int offset, RegisterID index, int scale, RegisterID dst) - { - m_buffer->putByte(OP_LEA); - emitModRm_rmsib(dst, X86::noBase, index, scale, offset); - } - - void ret() - { - m_buffer->putByte(OP_RET); - } - - void jmp_r(RegisterID dst) - { - m_buffer->putByte(OP_GROUP5_Ev); - emitModRm_opr(GROUP5_OP_JMPN, dst); - } - - void jmp_m(int offset, RegisterID base) - { - m_buffer->putByte(OP_GROUP5_Ev); - emitModRm_opm(GROUP5_OP_JMPN, base, offset); - } - - void movsd_mr(int offset, RegisterID base, XMMRegisterID dst) - { - m_buffer->putByte(PRE_SSE_F2); - m_buffer->putByte(OP_2BYTE_ESCAPE); - m_buffer->putByte(OP2_MOVSD_VsdWsd); - emitModRm_rm((RegisterID)dst, base, offset); - } - - void xorpd_mr(void* addr, XMMRegisterID dst) - { - m_buffer->putByte(PRE_SSE_66); - m_buffer->putByte(OP_2BYTE_ESCAPE); - m_buffer->putByte(OP2_XORPD_VsdWsd); - emitModRm_rm((RegisterID)dst, addr); - } - - void movsd_rm(XMMRegisterID src, int offset, RegisterID base) - { - m_buffer->putByte(PRE_SSE_F2); - m_buffer->putByte(OP_2BYTE_ESCAPE); - m_buffer->putByte(OP2_MOVSD_WsdVsd); - emitModRm_rm((RegisterID)src, base, offset); - } - - void movd_rr(XMMRegisterID src, RegisterID dst) - { - m_buffer->putByte(PRE_SSE_66); - m_buffer->putByte(OP_2BYTE_ESCAPE); - m_buffer->putByte(OP2_MOVD_EdVd); - emitModRm_rr((RegisterID)src, dst); - } - - void cvtsi2sd_rr(RegisterID src, XMMRegisterID dst) - { - m_buffer->putByte(PRE_SSE_F2); - m_buffer->putByte(OP_2BYTE_ESCAPE); - m_buffer->putByte(OP2_CVTSI2SD_VsdEd); - emitModRm_rr((RegisterID)dst, src); - } - - void cvttsd2si_rr(XMMRegisterID src, RegisterID dst) - { - m_buffer->putByte(PRE_SSE_F2); - m_buffer->putByte(OP_2BYTE_ESCAPE); - m_buffer->putByte(OP2_CVTTSD2SI_GdWsd); - emitModRm_rr(dst, (RegisterID)src); - } - - void addsd_mr(int offset, RegisterID base, XMMRegisterID dst) - { - m_buffer->putByte(PRE_SSE_F2); - m_buffer->putByte(OP_2BYTE_ESCAPE); - m_buffer->putByte(OP2_ADDSD_VsdWsd); - emitModRm_rm((RegisterID)dst, base, offset); - } - - void subsd_mr(int offset, RegisterID base, XMMRegisterID dst) - { - m_buffer->putByte(PRE_SSE_F2); - m_buffer->putByte(OP_2BYTE_ESCAPE); - m_buffer->putByte(OP2_SUBSD_VsdWsd); - emitModRm_rm((RegisterID)dst, base, offset); - } - - void mulsd_mr(int offset, RegisterID base, XMMRegisterID dst) - { - m_buffer->putByte(PRE_SSE_F2); - m_buffer->putByte(OP_2BYTE_ESCAPE); - m_buffer->putByte(OP2_MULSD_VsdWsd); - emitModRm_rm((RegisterID)dst, base, offset); - } - - void addsd_rr(XMMRegisterID src, XMMRegisterID dst) - { - m_buffer->putByte(PRE_SSE_F2); - m_buffer->putByte(OP_2BYTE_ESCAPE); - m_buffer->putByte(OP2_ADDSD_VsdWsd); - emitModRm_rr((RegisterID)dst, (RegisterID)src); - } - - void subsd_rr(XMMRegisterID src, XMMRegisterID dst) - { - m_buffer->putByte(PRE_SSE_F2); - m_buffer->putByte(OP_2BYTE_ESCAPE); - m_buffer->putByte(OP2_SUBSD_VsdWsd); - emitModRm_rr((RegisterID)dst, (RegisterID)src); - } - - void mulsd_rr(XMMRegisterID src, XMMRegisterID dst) - { - m_buffer->putByte(PRE_SSE_F2); - m_buffer->putByte(OP_2BYTE_ESCAPE); - m_buffer->putByte(OP2_MULSD_VsdWsd); - emitModRm_rr((RegisterID)dst, (RegisterID)src); - } - - void ucomis_rr(XMMRegisterID src, XMMRegisterID dst) - { - m_buffer->putByte(PRE_SSE_66); - m_buffer->putByte(OP_2BYTE_ESCAPE); - m_buffer->putByte(OP2_UCOMISD_VsdWsd); - emitModRm_rr((RegisterID)dst, (RegisterID)src); - } - - void pextrw_irr(int whichWord, XMMRegisterID src, RegisterID dst) - { - m_buffer->putByte(PRE_SSE_66); - m_buffer->putByte(OP_2BYTE_ESCAPE); - m_buffer->putByte(OP2_PEXTRW_GdUdIb); - emitModRm_rr(dst, (RegisterID)src); - m_buffer->putByte(whichWord); - } - - // Opaque label types - - class JmpSrc { - friend class X86Assembler; - public: - JmpSrc() - : m_offset(-1) - { - } - - private: - JmpSrc(int offset) - : m_offset(offset) - { - } - - int m_offset; - }; - - class JmpDst { - friend class X86Assembler; - public: - JmpDst() - : m_offset(-1) - { - } - - private: - JmpDst(int offset) - : m_offset(offset) - { - } - - int m_offset; - }; - - // FIXME: make this point to a global label, linked later. - JmpSrc emitCall() - { - m_buffer->putByte(OP_CALL_rel32); - m_buffer->putInt(0); - return JmpSrc(m_buffer->getOffset()); - } - - JmpSrc emitCall(RegisterID dst) - { - m_buffer->putByte(OP_GROUP5_Ev); - emitModRm_opr(GROUP5_OP_CALLN, dst); - return JmpSrc(m_buffer->getOffset()); - } - - JmpDst label() - { - return JmpDst(m_buffer->getOffset()); - } - - JmpSrc emitUnlinkedJmp() - { - m_buffer->putByte(OP_JMP_rel32); - m_buffer->putInt(0); - return JmpSrc(m_buffer->getOffset()); - } - - JmpSrc emitUnlinkedJne() - { - m_buffer->putByte(OP_2BYTE_ESCAPE); - m_buffer->putByte(OP2_JNE_rel32); - m_buffer->putInt(0); - return JmpSrc(m_buffer->getOffset()); - } - - JmpSrc emitUnlinkedJnz() - { - return emitUnlinkedJne(); - } - - JmpSrc emitUnlinkedJe() - { - m_buffer->ensureSpace(MAX_INSTRUCTION_SIZE); - m_buffer->putByteUnchecked(OP_2BYTE_ESCAPE); - m_buffer->putByteUnchecked(OP2_JE_rel32); - m_buffer->putIntUnchecked(0); - return JmpSrc(m_buffer->getOffset()); - } - - JmpSrc emitUnlinkedJl() - { - m_buffer->putByte(OP_2BYTE_ESCAPE); - m_buffer->putByte(OP2_JL_rel32); - m_buffer->putInt(0); - return JmpSrc(m_buffer->getOffset()); - } - - JmpSrc emitUnlinkedJb() - { - m_buffer->putByte(OP_2BYTE_ESCAPE); - m_buffer->putByte(OP2_JB_rel32); - m_buffer->putInt(0); - return JmpSrc(m_buffer->getOffset()); - } - - JmpSrc emitUnlinkedJle() - { - m_buffer->putByte(OP_2BYTE_ESCAPE); - m_buffer->putByte(OP2_JLE_rel32); - m_buffer->putInt(0); - return JmpSrc(m_buffer->getOffset()); - } - - JmpSrc emitUnlinkedJbe() - { - m_buffer->putByte(OP_2BYTE_ESCAPE); - m_buffer->putByte(OP2_JBE_rel32); - m_buffer->putInt(0); - return JmpSrc(m_buffer->getOffset()); - } - - JmpSrc emitUnlinkedJge() - { - m_buffer->putByte(OP_2BYTE_ESCAPE); - m_buffer->putByte(OP2_JGE_rel32); - m_buffer->putInt(0); - return JmpSrc(m_buffer->getOffset()); - } - - JmpSrc emitUnlinkedJg() - { - m_buffer->putByte(OP_2BYTE_ESCAPE); - m_buffer->putByte(OP2_JG_rel32); - m_buffer->putInt(0); - return JmpSrc(m_buffer->getOffset()); - } - - JmpSrc emitUnlinkedJa() - { - m_buffer->putByte(OP_2BYTE_ESCAPE); - m_buffer->putByte(OP2_JA_rel32); - m_buffer->putInt(0); - return JmpSrc(m_buffer->getOffset()); - } - - JmpSrc emitUnlinkedJae() - { - m_buffer->putByte(OP_2BYTE_ESCAPE); - m_buffer->putByte(OP2_JAE_rel32); - m_buffer->putInt(0); - return JmpSrc(m_buffer->getOffset()); - } - - JmpSrc emitUnlinkedJo() - { - m_buffer->putByte(OP_2BYTE_ESCAPE); - m_buffer->putByte(OP2_JO_rel32); - m_buffer->putInt(0); - return JmpSrc(m_buffer->getOffset()); - } - - JmpSrc emitUnlinkedJp() - { - m_buffer->putByte(OP_2BYTE_ESCAPE); - m_buffer->putByte(OP2_JP_rel32); - m_buffer->putInt(0); - return JmpSrc(m_buffer->getOffset()); - } - - JmpSrc emitUnlinkedJs() - { - m_buffer->putByte(OP_2BYTE_ESCAPE); - m_buffer->putByte(OP2_JS_rel32); - m_buffer->putInt(0); - return JmpSrc(m_buffer->getOffset()); - } - - void emitPredictionNotTaken() - { - m_buffer->putByte(PRE_PREDICT_BRANCH_NOT_TAKEN); - } - - void link(JmpSrc from, JmpDst to) - { - ASSERT(to.m_offset != -1); - ASSERT(from.m_offset != -1); - - reinterpret_cast<int*>(reinterpret_cast<ptrdiff_t>(m_buffer->start()) + from.m_offset)[-1] = to.m_offset - from.m_offset; - } - - static void linkAbsoluteAddress(void* code, JmpDst useOffset, JmpDst address) - { - ASSERT(useOffset.m_offset != -1); - ASSERT(address.m_offset != -1); - - reinterpret_cast<int*>(reinterpret_cast<ptrdiff_t>(code) + useOffset.m_offset)[-1] = reinterpret_cast<ptrdiff_t>(code) + address.m_offset; - } - - static void link(void* code, JmpSrc from, void* to) - { - ASSERT(from.m_offset != -1); - - reinterpret_cast<int*>(reinterpret_cast<ptrdiff_t>(code) + from.m_offset)[-1] = reinterpret_cast<ptrdiff_t>(to) - (reinterpret_cast<ptrdiff_t>(code) + from.m_offset); - } - - static void* getRelocatedAddress(void* code, JmpSrc jump) - { - return reinterpret_cast<void*>(reinterpret_cast<ptrdiff_t>(code) + jump.m_offset); - } - - static void* getRelocatedAddress(void* code, JmpDst jump) - { - return reinterpret_cast<void*>(reinterpret_cast<ptrdiff_t>(code) + jump.m_offset); - } - - static int getDifferenceBetweenLabels(JmpDst src, JmpDst dst) - { - return dst.m_offset - src.m_offset; - } - - static int getDifferenceBetweenLabels(JmpDst src, JmpSrc dst) - { - return dst.m_offset - src.m_offset; - } - - static int getDifferenceBetweenLabels(JmpSrc src, JmpDst dst) - { - return dst.m_offset - src.m_offset; - } - - static void repatchImmediate(intptr_t where, int32_t value) - { - reinterpret_cast<int32_t*>(where)[-1] = value; - } - - static void repatchDisplacement(intptr_t where, intptr_t value) - { - reinterpret_cast<intptr_t*>(where)[-1] = value; - } - - static void repatchBranchOffset(intptr_t where, void* destination) - { - reinterpret_cast<intptr_t*>(where)[-1] = (reinterpret_cast<intptr_t>(destination) - where); - } - - void* copy() - { - return m_buffer->copy(); - } - -#if COMPILER(MSVC) - void emitConvertToFastCall() - { - movl_mr(4, X86::esp, X86::eax); - movl_mr(8, X86::esp, X86::edx); - movl_mr(12, X86::esp, X86::ecx); - } -#else - void emitConvertToFastCall() {} -#endif - -#if USE(CTI_ARGUMENT) - void emitRestoreArgumentReference() - { -#if USE(FAST_CALL_CTI_ARGUMENT) - movl_rr(X86::esp, X86::ecx); -#else - movl_rm(X86::esp, 0, X86::esp); -#endif - } - - void emitRestoreArgumentReferenceForTrampoline() - { -#if USE(FAST_CALL_CTI_ARGUMENT) - movl_rr(X86::esp, X86::ecx); - addl_i32r(4, X86::ecx); -#endif - } -#else - void emitRestoreArgumentReference() {} - void emitRestoreArgumentReferenceForTrampoline() {} -#endif - -private: - void emitModRm_rr(RegisterID reg, RegisterID rm) - { - m_buffer->ensureSpace(MAX_INSTRUCTION_SIZE); - emitModRm_rr_Unchecked(reg, rm); - } - - void emitModRm_rr_Unchecked(RegisterID reg, RegisterID rm) - { - m_buffer->putByteUnchecked(MODRM(3, reg, rm)); - } - - void emitModRm_rm(RegisterID reg, void* addr) - { - m_buffer->putByte(MODRM(0, reg, X86::noBase)); - m_buffer->putInt((int)addr); - } - - void emitModRm_rm(RegisterID reg, RegisterID base) - { - if (base == X86::esp) { - m_buffer->putByte(MODRM(0, reg, X86::hasSib)); - m_buffer->putByte(SIB(0, X86::noScale, X86::esp)); - } else - m_buffer->putByte(MODRM(0, reg, base)); - } - - void emitModRm_rm_Unchecked(RegisterID reg, RegisterID base, int offset) - { - if (base == X86::esp) { - if (CAN_SIGN_EXTEND_8_32(offset)) { - m_buffer->putByteUnchecked(MODRM(1, reg, X86::hasSib)); - m_buffer->putByteUnchecked(SIB(0, X86::noScale, X86::esp)); - m_buffer->putByteUnchecked(offset); - } else { - m_buffer->putByteUnchecked(MODRM(2, reg, X86::hasSib)); - m_buffer->putByteUnchecked(SIB(0, X86::noScale, X86::esp)); - m_buffer->putIntUnchecked(offset); - } - } else { - if (CAN_SIGN_EXTEND_8_32(offset)) { - m_buffer->putByteUnchecked(MODRM(1, reg, base)); - m_buffer->putByteUnchecked(offset); - } else { - m_buffer->putByteUnchecked(MODRM(2, reg, base)); - m_buffer->putIntUnchecked(offset); - } - } - } - - void emitModRm_rm(RegisterID reg, RegisterID base, int offset) - { - m_buffer->ensureSpace(MAX_INSTRUCTION_SIZE); - emitModRm_rm_Unchecked(reg, base, offset); - } - - void emitModRm_rmsib(RegisterID reg, RegisterID base, RegisterID index, int scale) - { - int shift = 0; - while (scale >>= 1) - shift++; - - m_buffer->putByte(MODRM(0, reg, X86::hasSib)); - m_buffer->putByte(SIB(shift, index, base)); - } - - void emitModRm_rmsib(RegisterID reg, RegisterID base, RegisterID index, int scale, int offset) - { - int shift = 0; - while (scale >>= 1) - shift++; - - if (CAN_SIGN_EXTEND_8_32(offset)) { - m_buffer->putByte(MODRM(1, reg, X86::hasSib)); - m_buffer->putByte(SIB(shift, index, base)); - m_buffer->putByte(offset); - } else { - m_buffer->putByte(MODRM(2, reg, X86::hasSib)); - m_buffer->putByte(SIB(shift, index, base)); - m_buffer->putInt(offset); - } - } - - void emitModRm_opr(OpcodeID opcode, RegisterID rm) - { - m_buffer->ensureSpace(MAX_INSTRUCTION_SIZE); - emitModRm_opr_Unchecked(opcode, rm); - } - - void emitModRm_opr_Unchecked(OpcodeID opcode, RegisterID rm) - { - emitModRm_rr_Unchecked(static_cast<RegisterID>(opcode), rm); - } - - void emitModRm_opm(OpcodeID opcode, RegisterID base) - { - emitModRm_rm(static_cast<RegisterID>(opcode), base); - } - - void emitModRm_opm_Unchecked(OpcodeID opcode, RegisterID base, int offset) - { - emitModRm_rm_Unchecked(static_cast<RegisterID>(opcode), base, offset); - } - - void emitModRm_opm(OpcodeID opcode, RegisterID base, int offset) - { - emitModRm_rm(static_cast<RegisterID>(opcode), base, offset); - } - - void emitModRm_opm(OpcodeID opcode, void* addr) - { - emitModRm_rm(static_cast<RegisterID>(opcode), addr); - } - - void emitModRm_opmsib(OpcodeID opcode, RegisterID base, RegisterID index, int scale, int offset) - { - emitModRm_rmsib(static_cast<RegisterID>(opcode), base, index, scale, offset); - } - - JITCodeBuffer* m_buffer; -}; - -} // namespace JSC - -#endif // ENABLE(MASM) && PLATFORM(X86) - -#endif // X86Assembler_h diff --git a/JavaScriptCore/kjs/grammar.y b/JavaScriptCore/parser/Grammar.y index 370798d..ae787f6 100644 --- a/JavaScriptCore/kjs/grammar.y +++ b/JavaScriptCore/parser/Grammar.y @@ -4,7 +4,7 @@ /* * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) - * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 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 @@ -29,8 +29,8 @@ #include <stdlib.h> #include "JSValue.h" #include "JSObject.h" -#include "nodes.h" -#include "lexer.h" +#include "Nodes.h" +#include "Lexer.h" #include "JSString.h" #include "JSGlobalData.h" #include "CommonIdentifiers.h" @@ -43,14 +43,14 @@ /* default values for bison */ #define YYDEBUG 0 // Set to 1 to debug a parse error. -#define kjsyydebug 0 // Set to 1 to debug a parse error. +#define jscyydebug 0 // Set to 1 to debug a parse error. #if !PLATFORM(DARWIN) // avoid triggering warnings in older bison #define YYERROR_VERBOSE #endif -int kjsyylex(void* lvalp, void* llocp, void* globalPtr); -int kjsyyerror(const char*); +int jscyylex(void* lvalp, void* llocp, void* globalPtr); +int jscyyerror(const char*); static inline bool allowAutomaticSemicolon(JSC::Lexer&, int); #define GLOBAL_DATA static_cast<JSGlobalData*>(globalPtr) @@ -260,10 +260,9 @@ static inline void appendToVarDeclarationList(void* globalPtr, ParserRefCountedD %type <statementNode> SwitchStatement LabelledStatement %type <statementNode> ThrowStatement TryStatement %type <statementNode> DebuggerStatement -%type <statementNode> SourceElement %type <expressionNode> Initializer InitializerNoIn -%type <funcDeclNode> FunctionDeclaration +%type <statementNode> FunctionDeclaration %type <funcExprNode> FunctionExpr %type <functionBodyNode> FunctionBody %type <sourceElements> SourceElements @@ -283,6 +282,10 @@ static inline void appendToVarDeclarationList(void* globalPtr, ParserRefCountedD %type <propertyList> PropertyList %% +// FIXME: There are currently two versions of the grammar in this file, the normal one, and the NoNodes version used for +// lazy recompilation of FunctionBodyNodes. We should move to generating the two versions from a script to avoid bugs. +// In the mean time, make sure to make any changes to the grammar in both versions. + Literal: NULLTOKEN { $$ = createNodeInfo<ExpressionNode*>(new NullNode(GLOBAL_DATA), 0, 1); } | TRUETOKEN { $$ = createNodeInfo<ExpressionNode*>(new BooleanNode(GLOBAL_DATA, true), 0, 1); } @@ -792,6 +795,7 @@ Statement: Block | VariableStatement | ConstStatement + | FunctionDeclaration | EmptyStatement | ExprStatement | IfStatement @@ -1135,20 +1139,20 @@ ThrowStatement: ; TryStatement: - TRY Block FINALLY Block { $$ = createNodeDeclarationInfo<StatementNode*>(new TryNode(GLOBAL_DATA, $2.m_node, GLOBAL_DATA->propertyNames->nullIdentifier, 0, $4.m_node), + TRY Block FINALLY Block { $$ = createNodeDeclarationInfo<StatementNode*>(new TryNode(GLOBAL_DATA, $2.m_node, GLOBAL_DATA->propertyNames->nullIdentifier, false, 0, $4.m_node), mergeDeclarationLists($2.m_varDeclarations, $4.m_varDeclarations), mergeDeclarationLists($2.m_funcDeclarations, $4.m_funcDeclarations), $2.m_features | $4.m_features, $2.m_numConstants + $4.m_numConstants); DBG($$.m_node, @1, @2); } - | TRY Block CATCH '(' IDENT ')' Block { $$ = createNodeDeclarationInfo<StatementNode*>(new TryNode(GLOBAL_DATA, $2.m_node, *$5, $7.m_node, 0), + | TRY Block CATCH '(' IDENT ')' Block { $$ = createNodeDeclarationInfo<StatementNode*>(new TryNode(GLOBAL_DATA, $2.m_node, *$5, ($7.m_features & EvalFeature) != 0, $7.m_node, 0), mergeDeclarationLists($2.m_varDeclarations, $7.m_varDeclarations), mergeDeclarationLists($2.m_funcDeclarations, $7.m_funcDeclarations), $2.m_features | $7.m_features | CatchFeature, $2.m_numConstants + $7.m_numConstants); DBG($$.m_node, @1, @2); } | TRY Block CATCH '(' IDENT ')' Block FINALLY Block - { $$ = createNodeDeclarationInfo<StatementNode*>(new TryNode(GLOBAL_DATA, $2.m_node, *$5, $7.m_node, $9.m_node), + { $$ = createNodeDeclarationInfo<StatementNode*>(new TryNode(GLOBAL_DATA, $2.m_node, *$5, ($7.m_features & EvalFeature) != 0, $7.m_node, $9.m_node), mergeDeclarationLists(mergeDeclarationLists($2.m_varDeclarations, $7.m_varDeclarations), $9.m_varDeclarations), mergeDeclarationLists(mergeDeclarationLists($2.m_funcDeclarations, $7.m_funcDeclarations), $9.m_funcDeclarations), $2.m_features | $7.m_features | $9.m_features | CatchFeature, @@ -1164,13 +1168,14 @@ DebuggerStatement: ; FunctionDeclaration: - FUNCTION IDENT '(' ')' OPENBRACE FunctionBody CLOSEBRACE { $$ = createNodeInfo(new FuncDeclNode(GLOBAL_DATA, *$2, $6, LEXER->sourceCode($5, $7, @5.first_line)), ((*$2 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0) | ClosureFeature, 0); DBG($6, @5, @7); } + FUNCTION IDENT '(' ')' OPENBRACE FunctionBody CLOSEBRACE { $$ = createNodeDeclarationInfo<StatementNode*>(new FuncDeclNode(GLOBAL_DATA, *$2, $6, LEXER->sourceCode($5, $7, @5.first_line)), 0, new ParserRefCountedData<DeclarationStacks::FunctionStack>(GLOBAL_DATA), ((*$2 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0) | ClosureFeature, 0); DBG($6, @5, @7); $$.m_funcDeclarations->data.append(static_cast<FuncDeclNode*>($$.m_node)); } | FUNCTION IDENT '(' FormalParameterList ')' OPENBRACE FunctionBody CLOSEBRACE { - $$ = createNodeInfo(new FuncDeclNode(GLOBAL_DATA, *$2, $7, LEXER->sourceCode($6, $8, @6.first_line), $4.m_node.head), ((*$2 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0) | $4.m_features | ClosureFeature, 0); + $$ = createNodeDeclarationInfo<StatementNode*>(new FuncDeclNode(GLOBAL_DATA, *$2, $7, LEXER->sourceCode($6, $8, @6.first_line), $4.m_node.head), 0, new ParserRefCountedData<DeclarationStacks::FunctionStack>(GLOBAL_DATA), ((*$2 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0) | $4.m_features | ClosureFeature, 0); if ($4.m_features & ArgumentsFeature) $7->setUsesArguments(); - DBG($7, @6, @8); + DBG($7, @6, @8); + $$.m_funcDeclarations->data.append(static_cast<FuncDeclNode*>($$.m_node)); } ; @@ -1203,21 +1208,8 @@ FormalParameterList: ; FunctionBody: - /* not in spec */ { $$ = FunctionBodyNode::create(GLOBAL_DATA, 0, 0, 0, NoFeatures, 0); } - | SourceElements { $$ = FunctionBodyNode::create(GLOBAL_DATA, $1.m_node, $1.m_varDeclarations ? &$1.m_varDeclarations->data : 0, - $1.m_funcDeclarations ? &$1.m_funcDeclarations->data : 0, - $1.m_features, $1.m_numConstants); - // As in mergeDeclarationLists() we have to ref/deref to safely get rid of - // the declaration lists. - if ($1.m_varDeclarations) { - $1.m_varDeclarations->ref(); - $1.m_varDeclarations->deref(); - } - if ($1.m_funcDeclarations) { - $1.m_funcDeclarations->ref(); - $1.m_funcDeclarations->deref(); - } - } + /* not in spec */ { $$ = FunctionBodyNode::create(GLOBAL_DATA); } + | SourceElements_NoNode { $$ = FunctionBodyNode::create(GLOBAL_DATA); } ; Program: @@ -1227,26 +1219,610 @@ Program: ; SourceElements: - SourceElement { $$.m_node = new SourceElements(GLOBAL_DATA); + Statement { $$.m_node = new SourceElements(GLOBAL_DATA); $$.m_node->append($1.m_node); $$.m_varDeclarations = $1.m_varDeclarations; $$.m_funcDeclarations = $1.m_funcDeclarations; $$.m_features = $1.m_features; $$.m_numConstants = $1.m_numConstants; } - | SourceElements SourceElement { $$.m_node->append($2.m_node); + | SourceElements Statement { $$.m_node->append($2.m_node); $$.m_varDeclarations = mergeDeclarationLists($1.m_varDeclarations, $2.m_varDeclarations); $$.m_funcDeclarations = mergeDeclarationLists($1.m_funcDeclarations, $2.m_funcDeclarations); $$.m_features = $1.m_features | $2.m_features; $$.m_numConstants = $1.m_numConstants + $2.m_numConstants; } ; + +// Start NoNodes -SourceElement: - FunctionDeclaration { $$ = createNodeDeclarationInfo<StatementNode*>($1.m_node, 0, new ParserRefCountedData<DeclarationStacks::FunctionStack>(GLOBAL_DATA), $1.m_features, 0); $$.m_funcDeclarations->data.append($1.m_node); } - | Statement { $$ = $1; } +Literal_NoNode: + NULLTOKEN + | TRUETOKEN + | FALSETOKEN + | NUMBER { } + | STRING { } + | '/' /* regexp */ { Lexer& l = *LEXER; if (!l.scanRegExp()) YYABORT; } + | DIVEQUAL /* regexp with /= */ { Lexer& l = *LEXER; if (!l.scanRegExp()) YYABORT; } ; - + +Property_NoNode: + IDENT ':' AssignmentExpr_NoNode { } + | STRING ':' AssignmentExpr_NoNode { } + | NUMBER ':' AssignmentExpr_NoNode { } + | IDENT IDENT '(' ')' OPENBRACE FunctionBody_NoNode CLOSEBRACE { if (*$1 != "get" && *$1 != "set") YYABORT; } + | IDENT IDENT '(' FormalParameterList_NoNode ')' OPENBRACE FunctionBody_NoNode CLOSEBRACE { if (*$1 != "get" && *$1 != "set") YYABORT; } +; + +PropertyList_NoNode: + Property_NoNode + | PropertyList_NoNode ',' Property_NoNode +; + +PrimaryExpr_NoNode: + PrimaryExprNoBrace_NoNode + | OPENBRACE CLOSEBRACE { } + | OPENBRACE PropertyList_NoNode CLOSEBRACE { } + /* allow extra comma, see http://bugs.webkit.org/show_bug.cgi?id=5939 */ + | OPENBRACE PropertyList_NoNode ',' CLOSEBRACE { } +; + +PrimaryExprNoBrace_NoNode: + THISTOKEN + | Literal_NoNode + | ArrayLiteral_NoNode + | IDENT { } + | '(' Expr_NoNode ')' +; + +ArrayLiteral_NoNode: + '[' ElisionOpt_NoNode ']' + | '[' ElementList_NoNode ']' + | '[' ElementList_NoNode ',' ElisionOpt_NoNode ']' +; + +ElementList_NoNode: + ElisionOpt_NoNode AssignmentExpr_NoNode + | ElementList_NoNode ',' ElisionOpt_NoNode AssignmentExpr_NoNode +; + +ElisionOpt_NoNode: + /* nothing */ + | Elision_NoNode +; + +Elision_NoNode: + ',' + | Elision_NoNode ',' +; + +MemberExpr_NoNode: + PrimaryExpr_NoNode + | FunctionExpr_NoNode + | MemberExpr_NoNode '[' Expr_NoNode ']' + | MemberExpr_NoNode '.' IDENT + | NEW MemberExpr_NoNode Arguments_NoNode +; + +MemberExprNoBF_NoNode: + PrimaryExprNoBrace_NoNode + | MemberExprNoBF_NoNode '[' Expr_NoNode ']' + | MemberExprNoBF_NoNode '.' IDENT + | NEW MemberExpr_NoNode Arguments_NoNode +; + +NewExpr_NoNode: + MemberExpr_NoNode + | NEW NewExpr_NoNode +; + +NewExprNoBF_NoNode: + MemberExprNoBF_NoNode + | NEW NewExpr_NoNode +; + +CallExpr_NoNode: + MemberExpr_NoNode Arguments_NoNode + | CallExpr_NoNode Arguments_NoNode + | CallExpr_NoNode '[' Expr_NoNode ']' + | CallExpr_NoNode '.' IDENT +; + +CallExprNoBF_NoNode: + MemberExprNoBF_NoNode Arguments_NoNode + | CallExprNoBF_NoNode Arguments_NoNode + | CallExprNoBF_NoNode '[' Expr_NoNode ']' + | CallExprNoBF_NoNode '.' IDENT +; + +Arguments_NoNode: + '(' ')' + | '(' ArgumentList_NoNode ')' +; + +ArgumentList_NoNode: + AssignmentExpr_NoNode + | ArgumentList_NoNode ',' AssignmentExpr_NoNode +; + +LeftHandSideExpr_NoNode: + NewExpr_NoNode + | CallExpr_NoNode +; + +LeftHandSideExprNoBF_NoNode: + NewExprNoBF_NoNode + | CallExprNoBF_NoNode +; + +PostfixExpr_NoNode: + LeftHandSideExpr_NoNode + | LeftHandSideExpr_NoNode PLUSPLUS + | LeftHandSideExpr_NoNode MINUSMINUS +; + +PostfixExprNoBF_NoNode: + LeftHandSideExprNoBF_NoNode + | LeftHandSideExprNoBF_NoNode PLUSPLUS + | LeftHandSideExprNoBF_NoNode MINUSMINUS +; + +UnaryExprCommon_NoNode: + DELETETOKEN UnaryExpr_NoNode + | VOIDTOKEN UnaryExpr_NoNode + | TYPEOF UnaryExpr_NoNode + | PLUSPLUS UnaryExpr_NoNode + | AUTOPLUSPLUS UnaryExpr_NoNode + | MINUSMINUS UnaryExpr_NoNode + | AUTOMINUSMINUS UnaryExpr_NoNode + | '+' UnaryExpr_NoNode + | '-' UnaryExpr_NoNode + | '~' UnaryExpr_NoNode + | '!' UnaryExpr_NoNode + +UnaryExpr_NoNode: + PostfixExpr_NoNode + | UnaryExprCommon_NoNode +; + +UnaryExprNoBF_NoNode: + PostfixExprNoBF_NoNode + | UnaryExprCommon_NoNode +; + +MultiplicativeExpr_NoNode: + UnaryExpr_NoNode + | MultiplicativeExpr_NoNode '*' UnaryExpr_NoNode + | MultiplicativeExpr_NoNode '/' UnaryExpr_NoNode + | MultiplicativeExpr_NoNode '%' UnaryExpr_NoNode +; + +MultiplicativeExprNoBF_NoNode: + UnaryExprNoBF_NoNode + | MultiplicativeExprNoBF_NoNode '*' UnaryExpr_NoNode + | MultiplicativeExprNoBF_NoNode '/' UnaryExpr_NoNode + | MultiplicativeExprNoBF_NoNode '%' UnaryExpr_NoNode +; + +AdditiveExpr_NoNode: + MultiplicativeExpr_NoNode + | AdditiveExpr_NoNode '+' MultiplicativeExpr_NoNode + | AdditiveExpr_NoNode '-' MultiplicativeExpr_NoNode +; + +AdditiveExprNoBF_NoNode: + MultiplicativeExprNoBF_NoNode + | AdditiveExprNoBF_NoNode '+' MultiplicativeExpr_NoNode + | AdditiveExprNoBF_NoNode '-' MultiplicativeExpr_NoNode +; + +ShiftExpr_NoNode: + AdditiveExpr_NoNode + | ShiftExpr_NoNode LSHIFT AdditiveExpr_NoNode + | ShiftExpr_NoNode RSHIFT AdditiveExpr_NoNode + | ShiftExpr_NoNode URSHIFT AdditiveExpr_NoNode +; + +ShiftExprNoBF_NoNode: + AdditiveExprNoBF_NoNode + | ShiftExprNoBF_NoNode LSHIFT AdditiveExpr_NoNode + | ShiftExprNoBF_NoNode RSHIFT AdditiveExpr_NoNode + | ShiftExprNoBF_NoNode URSHIFT AdditiveExpr_NoNode +; + +RelationalExpr_NoNode: + ShiftExpr_NoNode + | RelationalExpr_NoNode '<' ShiftExpr_NoNode + | RelationalExpr_NoNode '>' ShiftExpr_NoNode + | RelationalExpr_NoNode LE ShiftExpr_NoNode + | RelationalExpr_NoNode GE ShiftExpr_NoNode + | RelationalExpr_NoNode INSTANCEOF ShiftExpr_NoNode + | RelationalExpr_NoNode INTOKEN ShiftExpr_NoNode +; + +RelationalExprNoIn_NoNode: + ShiftExpr_NoNode + | RelationalExprNoIn_NoNode '<' ShiftExpr_NoNode + | RelationalExprNoIn_NoNode '>' ShiftExpr_NoNode + | RelationalExprNoIn_NoNode LE ShiftExpr_NoNode + | RelationalExprNoIn_NoNode GE ShiftExpr_NoNode + | RelationalExprNoIn_NoNode INSTANCEOF ShiftExpr_NoNode +; + +RelationalExprNoBF_NoNode: + ShiftExprNoBF_NoNode + | RelationalExprNoBF_NoNode '<' ShiftExpr_NoNode + | RelationalExprNoBF_NoNode '>' ShiftExpr_NoNode + | RelationalExprNoBF_NoNode LE ShiftExpr_NoNode + | RelationalExprNoBF_NoNode GE ShiftExpr_NoNode + | RelationalExprNoBF_NoNode INSTANCEOF ShiftExpr_NoNode + | RelationalExprNoBF_NoNode INTOKEN ShiftExpr_NoNode +; + +EqualityExpr_NoNode: + RelationalExpr_NoNode + | EqualityExpr_NoNode EQEQ RelationalExpr_NoNode + | EqualityExpr_NoNode NE RelationalExpr_NoNode + | EqualityExpr_NoNode STREQ RelationalExpr_NoNode + | EqualityExpr_NoNode STRNEQ RelationalExpr_NoNode +; + +EqualityExprNoIn_NoNode: + RelationalExprNoIn_NoNode + | EqualityExprNoIn_NoNode EQEQ RelationalExprNoIn_NoNode + | EqualityExprNoIn_NoNode NE RelationalExprNoIn_NoNode + | EqualityExprNoIn_NoNode STREQ RelationalExprNoIn_NoNode + | EqualityExprNoIn_NoNode STRNEQ RelationalExprNoIn_NoNode +; + +EqualityExprNoBF_NoNode: + RelationalExprNoBF_NoNode + | EqualityExprNoBF_NoNode EQEQ RelationalExpr_NoNode + | EqualityExprNoBF_NoNode NE RelationalExpr_NoNode + | EqualityExprNoBF_NoNode STREQ RelationalExpr_NoNode + | EqualityExprNoBF_NoNode STRNEQ RelationalExpr_NoNode +; + +BitwiseANDExpr_NoNode: + EqualityExpr_NoNode + | BitwiseANDExpr_NoNode '&' EqualityExpr_NoNode +; + +BitwiseANDExprNoIn_NoNode: + EqualityExprNoIn_NoNode + | BitwiseANDExprNoIn_NoNode '&' EqualityExprNoIn_NoNode +; + +BitwiseANDExprNoBF_NoNode: + EqualityExprNoBF_NoNode + | BitwiseANDExprNoBF_NoNode '&' EqualityExpr_NoNode +; + +BitwiseXORExpr_NoNode: + BitwiseANDExpr_NoNode + | BitwiseXORExpr_NoNode '^' BitwiseANDExpr_NoNode +; + +BitwiseXORExprNoIn_NoNode: + BitwiseANDExprNoIn_NoNode + | BitwiseXORExprNoIn_NoNode '^' BitwiseANDExprNoIn_NoNode +; + +BitwiseXORExprNoBF_NoNode: + BitwiseANDExprNoBF_NoNode + | BitwiseXORExprNoBF_NoNode '^' BitwiseANDExpr_NoNode +; + +BitwiseORExpr_NoNode: + BitwiseXORExpr_NoNode + | BitwiseORExpr_NoNode '|' BitwiseXORExpr_NoNode +; + +BitwiseORExprNoIn_NoNode: + BitwiseXORExprNoIn_NoNode + | BitwiseORExprNoIn_NoNode '|' BitwiseXORExprNoIn_NoNode +; + +BitwiseORExprNoBF_NoNode: + BitwiseXORExprNoBF_NoNode + | BitwiseORExprNoBF_NoNode '|' BitwiseXORExpr_NoNode +; + +LogicalANDExpr_NoNode: + BitwiseORExpr_NoNode + | LogicalANDExpr_NoNode AND BitwiseORExpr_NoNode +; + +LogicalANDExprNoIn_NoNode: + BitwiseORExprNoIn_NoNode + | LogicalANDExprNoIn_NoNode AND BitwiseORExprNoIn_NoNode +; + +LogicalANDExprNoBF_NoNode: + BitwiseORExprNoBF_NoNode + | LogicalANDExprNoBF_NoNode AND BitwiseORExpr_NoNode +; + +LogicalORExpr_NoNode: + LogicalANDExpr_NoNode + | LogicalORExpr_NoNode OR LogicalANDExpr_NoNode +; + +LogicalORExprNoIn_NoNode: + LogicalANDExprNoIn_NoNode + | LogicalORExprNoIn_NoNode OR LogicalANDExprNoIn_NoNode +; + +LogicalORExprNoBF_NoNode: + LogicalANDExprNoBF_NoNode + | LogicalORExprNoBF_NoNode OR LogicalANDExpr_NoNode +; + +ConditionalExpr_NoNode: + LogicalORExpr_NoNode + | LogicalORExpr_NoNode '?' AssignmentExpr_NoNode ':' AssignmentExpr_NoNode +; + +ConditionalExprNoIn_NoNode: + LogicalORExprNoIn_NoNode + | LogicalORExprNoIn_NoNode '?' AssignmentExprNoIn_NoNode ':' AssignmentExprNoIn_NoNode +; + +ConditionalExprNoBF_NoNode: + LogicalORExprNoBF_NoNode + | LogicalORExprNoBF_NoNode '?' AssignmentExpr_NoNode ':' AssignmentExpr_NoNode +; + +AssignmentExpr_NoNode: + ConditionalExpr_NoNode + | LeftHandSideExpr_NoNode AssignmentOperator_NoNode AssignmentExpr_NoNode +; + +AssignmentExprNoIn_NoNode: + ConditionalExprNoIn_NoNode + | LeftHandSideExpr_NoNode AssignmentOperator_NoNode AssignmentExprNoIn_NoNode +; + +AssignmentExprNoBF_NoNode: + ConditionalExprNoBF_NoNode + | LeftHandSideExprNoBF_NoNode AssignmentOperator_NoNode AssignmentExpr_NoNode +; + +AssignmentOperator_NoNode: + '=' + | PLUSEQUAL + | MINUSEQUAL + | MULTEQUAL + | DIVEQUAL + | LSHIFTEQUAL + | RSHIFTEQUAL + | URSHIFTEQUAL + | ANDEQUAL + | XOREQUAL + | OREQUAL + | MODEQUAL +; + +Expr_NoNode: + AssignmentExpr_NoNode + | Expr_NoNode ',' AssignmentExpr_NoNode +; + +ExprNoIn_NoNode: + AssignmentExprNoIn_NoNode + | ExprNoIn_NoNode ',' AssignmentExprNoIn_NoNode +; + +ExprNoBF_NoNode: + AssignmentExprNoBF_NoNode + | ExprNoBF_NoNode ',' AssignmentExpr_NoNode +; + +Statement_NoNode: + Block_NoNode + | VariableStatement_NoNode + | ConstStatement_NoNode + | FunctionDeclaration_NoNode + | EmptyStatement_NoNode + | ExprStatement_NoNode + | IfStatement_NoNode + | IterationStatement_NoNode + | ContinueStatement_NoNode + | BreakStatement_NoNode + | ReturnStatement_NoNode + | WithStatement_NoNode + | SwitchStatement_NoNode + | LabelledStatement_NoNode + | ThrowStatement_NoNode + | TryStatement_NoNode + | DebuggerStatement_NoNode +; + +Block_NoNode: + OPENBRACE CLOSEBRACE { } + | OPENBRACE SourceElements_NoNode CLOSEBRACE { } +; + +VariableStatement_NoNode: + VAR VariableDeclarationList_NoNode ';' + | VAR VariableDeclarationList_NoNode error { AUTO_SEMICOLON; } +; + +VariableDeclarationList_NoNode: + IDENT { } + | IDENT Initializer_NoNode { } + | VariableDeclarationList_NoNode ',' IDENT + | VariableDeclarationList_NoNode ',' IDENT Initializer_NoNode +; + +VariableDeclarationListNoIn_NoNode: + IDENT { } + | IDENT InitializerNoIn_NoNode { } + | VariableDeclarationListNoIn_NoNode ',' IDENT + | VariableDeclarationListNoIn_NoNode ',' IDENT InitializerNoIn_NoNode +; + +ConstStatement_NoNode: + CONSTTOKEN ConstDeclarationList_NoNode ';' + | CONSTTOKEN ConstDeclarationList_NoNode error { AUTO_SEMICOLON; } +; + +ConstDeclarationList_NoNode: + ConstDeclaration_NoNode + | ConstDeclarationList_NoNode ',' ConstDeclaration_NoNode +; + +ConstDeclaration_NoNode: + IDENT { } + | IDENT Initializer_NoNode { } +; + +Initializer_NoNode: + '=' AssignmentExpr_NoNode +; + +InitializerNoIn_NoNode: + '=' AssignmentExprNoIn_NoNode +; + +EmptyStatement_NoNode: + ';' +; + +ExprStatement_NoNode: + ExprNoBF_NoNode ';' + | ExprNoBF_NoNode error { AUTO_SEMICOLON; } +; + +IfStatement_NoNode: + IF '(' Expr_NoNode ')' Statement_NoNode %prec IF_WITHOUT_ELSE + | IF '(' Expr_NoNode ')' Statement_NoNode ELSE Statement_NoNode +; + +IterationStatement_NoNode: + DO Statement_NoNode WHILE '(' Expr_NoNode ')' ';' + | DO Statement_NoNode WHILE '(' Expr_NoNode ')' error // Always performs automatic semicolon insertion + | WHILE '(' Expr_NoNode ')' Statement_NoNode + | FOR '(' ExprNoInOpt_NoNode ';' ExprOpt_NoNode ';' ExprOpt_NoNode ')' Statement_NoNode + | FOR '(' VAR VariableDeclarationListNoIn_NoNode ';' ExprOpt_NoNode ';' ExprOpt_NoNode ')' Statement_NoNode + | FOR '(' LeftHandSideExpr_NoNode INTOKEN Expr_NoNode ')' Statement_NoNode + | FOR '(' VAR IDENT INTOKEN Expr_NoNode ')' Statement_NoNode + | FOR '(' VAR IDENT InitializerNoIn_NoNode INTOKEN Expr_NoNode ')' Statement_NoNode +; + +ExprOpt_NoNode: + /* nothing */ + | Expr_NoNode +; + +ExprNoInOpt_NoNode: + /* nothing */ + | ExprNoIn_NoNode +; + +ContinueStatement_NoNode: + CONTINUE ';' + | CONTINUE error { AUTO_SEMICOLON; } + | CONTINUE IDENT ';' + | CONTINUE IDENT error { AUTO_SEMICOLON; } +; + +BreakStatement_NoNode: + BREAK ';' + | BREAK error { AUTO_SEMICOLON; } + | BREAK IDENT ';' + | BREAK IDENT error { AUTO_SEMICOLON; } +; + +ReturnStatement_NoNode: + RETURN ';' + | RETURN error { AUTO_SEMICOLON; } + | RETURN Expr_NoNode ';' + | RETURN Expr_NoNode error { AUTO_SEMICOLON; } +; + +WithStatement_NoNode: + WITH '(' Expr_NoNode ')' Statement_NoNode +; + +SwitchStatement_NoNode: + SWITCH '(' Expr_NoNode ')' CaseBlock_NoNode +; + +CaseBlock_NoNode: + OPENBRACE CaseClausesOpt_NoNode CLOSEBRACE { } + | OPENBRACE CaseClausesOpt_NoNode DefaultClause_NoNode CaseClausesOpt_NoNode CLOSEBRACE { } +; + +CaseClausesOpt_NoNode: + /* nothing */ + | CaseClauses_NoNode +; + +CaseClauses_NoNode: + CaseClause_NoNode + | CaseClauses_NoNode CaseClause_NoNode +; + +CaseClause_NoNode: + CASE Expr_NoNode ':' + | CASE Expr_NoNode ':' SourceElements_NoNode +; + +DefaultClause_NoNode: + DEFAULT ':' + | DEFAULT ':' SourceElements_NoNode +; + +LabelledStatement_NoNode: + IDENT ':' Statement_NoNode { } +; + +ThrowStatement_NoNode: + THROW Expr_NoNode ';' + | THROW Expr_NoNode error { AUTO_SEMICOLON; } +; + +TryStatement_NoNode: + TRY Block_NoNode FINALLY Block_NoNode + | TRY Block_NoNode CATCH '(' IDENT ')' Block_NoNode + | TRY Block_NoNode CATCH '(' IDENT ')' Block_NoNode FINALLY Block_NoNode +; + +DebuggerStatement_NoNode: + DEBUGGER ';' + | DEBUGGER error { AUTO_SEMICOLON; } +; + +FunctionDeclaration_NoNode: + FUNCTION IDENT '(' ')' OPENBRACE FunctionBody_NoNode CLOSEBRACE + | FUNCTION IDENT '(' FormalParameterList_NoNode ')' OPENBRACE FunctionBody_NoNode CLOSEBRACE +; + +FunctionExpr_NoNode: + FUNCTION '(' ')' OPENBRACE FunctionBody_NoNode CLOSEBRACE + | FUNCTION '(' FormalParameterList_NoNode ')' OPENBRACE FunctionBody_NoNode CLOSEBRACE + | FUNCTION IDENT '(' ')' OPENBRACE FunctionBody_NoNode CLOSEBRACE + | FUNCTION IDENT '(' FormalParameterList_NoNode ')' OPENBRACE FunctionBody_NoNode CLOSEBRACE +; + +FormalParameterList_NoNode: + IDENT { } + | FormalParameterList_NoNode ',' IDENT +; + +FunctionBody_NoNode: + /* not in spec */ + | SourceElements_NoNode +; + +SourceElements_NoNode: + Statement_NoNode + | SourceElements_NoNode Statement_NoNode +; + +// End NoNodes + %% static ExpressionNode* makeAssignNode(void* globalPtr, ExpressionNode* loc, Operator op, ExpressionNode* expr, bool locHasAssignments, bool exprHasAssignments, int start, int divot, int end) @@ -1408,9 +1984,6 @@ static ExpressionNode* makeNegateNode(void* globalPtr, ExpressionNode* n) static NumberNode* makeNumberNode(void* globalPtr, double d) { - JSValue* value = JSImmediate::from(d); - if (value) - return new ImmediateNumberNode(GLOBAL_DATA, value, d); return new NumberNode(GLOBAL_DATA, d); } diff --git a/JavaScriptCore/kjs/keywords.table b/JavaScriptCore/parser/Keywords.table index 490c1cc..490c1cc 100644 --- a/JavaScriptCore/kjs/keywords.table +++ b/JavaScriptCore/parser/Keywords.table diff --git a/JavaScriptCore/kjs/lexer.cpp b/JavaScriptCore/parser/Lexer.cpp index 7313b12..22de4a0 100644 --- a/JavaScriptCore/kjs/lexer.cpp +++ b/JavaScriptCore/parser/Lexer.cpp @@ -1,6 +1,6 @@ /* * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) - * Copyright (C) 2006, 2007, 2008 Apple Inc. All Rights Reserved. + * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All Rights Reserved. * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca) * * This library is free software; you can redistribute it and/or @@ -21,16 +21,17 @@ */ #include "config.h" -#include "lexer.h" +#include "Lexer.h" -#include "dtoa.h" #include "JSFunction.h" -#include "nodes.h" -#include "NodeInfo.h" #include "JSGlobalObjectFunctions.h" +#include "NodeInfo.h" +#include "Nodes.h" +#include "dtoa.h" #include <ctype.h> #include <limits.h> #include <string.h> +#include <wtf/ASCIICType.h> #include <wtf/Assertions.h> #include <wtf/unicode/Unicode.h> @@ -41,14 +42,14 @@ using namespace Unicode; using namespace JSC; #ifndef KDE_USE_FINAL -#include "grammar.h" +#include "Grammar.h" #endif -#include "lookup.h" -#include "lexer.lut.h" +#include "Lookup.h" +#include "Lexer.lut.h" // a bridge for yacc from the C world to C++ -int kjsyylex(void* lvalp, void* llocp, void* globalData) +int jscyylex(void* lvalp, void* llocp, void* globalData) { return static_cast<JSGlobalData*>(globalData)->lexer->lex(lvalp, llocp); } @@ -57,9 +58,6 @@ namespace JSC { static bool isDecimalDigit(int); -static const size_t initialReadBufferCapacity = 32; -static const size_t initialStringTableCapacity = 64; - Lexer::Lexer(JSGlobalData* globalData) : yylineno(1) , m_restrKeyword(false) @@ -69,6 +67,7 @@ Lexer::Lexer(JSGlobalData* globalData) , m_position(0) , m_code(0) , m_length(0) + , m_isReparsing(false) , m_atLineStart(true) , m_current(0) , m_next1(0) @@ -83,8 +82,6 @@ Lexer::Lexer(JSGlobalData* globalData) { m_buffer8.reserveCapacity(initialReadBufferCapacity); m_buffer16.reserveCapacity(initialReadBufferCapacity); - m_strings.reserveCapacity(initialStringTableCapacity); - m_identifiers.reserveCapacity(initialStringTableCapacity); } Lexer::~Lexer() @@ -101,10 +98,10 @@ void Lexer::setCode(const SourceCode& source) m_stackToken = -1; m_lastToken = -1; - m_position = 0; + m_position = source.startOffset(); m_source = &source; - m_code = source.data(); - m_length = source.length(); + m_code = source.provider()->data(); + m_length = source.endOffset(); m_skipLF = false; m_skipCR = false; m_error = false; @@ -196,7 +193,7 @@ int Lexer::lex(void* p1, void* p2) shift(1); m_state = InMultiLineComment; } else if (m_current == -1) { - if (!m_terminator && !m_delimited) { + if (!m_terminator && !m_delimited && !m_isReparsing) { // automatic semicolon insertion if program incomplete token = ';'; m_stackToken = 0; @@ -469,7 +466,7 @@ int Lexer::lex(void* p1, void* p2) // terminate string m_buffer8.append('\0'); -#ifdef KJS_DEBUG_LEX +#ifdef JSC_DEBUG_LEX fprintf(stderr, "line: %d ", lineNo()); fprintf(stderr, "yytext (%x): ", m_buffer8[0]); fprintf(stderr, "%s ", m_buffer8.data()); @@ -477,7 +474,7 @@ int Lexer::lex(void* p1, void* p2) double dval = 0; if (m_state == Number) - dval = strtod(m_buffer8.data(), 0L); + dval = WTF::strtod(m_buffer8.data(), 0L); else if (m_state == Hex) { // scan hex numbers const char* p = m_buffer8.data() + 2; while (char c = *p++) { @@ -502,7 +499,7 @@ int Lexer::lex(void* p1, void* p2) m_state = Number; } -#ifdef KJS_DEBUG_LEX +#ifdef JSC_DEBUG_LEX switch (m_state) { case Eof: printf("(EOF)\n"); @@ -576,7 +573,7 @@ int Lexer::lex(void* p1, void* p2) token = NUMBER; break; case Bad: -#ifdef KJS_DEBUG_LEX +#ifdef JSC_DEBUG_LEX fprintf(stderr, "yylex: ERROR.\n"); #endif m_error = true; @@ -608,32 +605,28 @@ bool Lexer::isLineTerminator() bool Lexer::isIdentStart(int c) { - return (category(c) & (Letter_Uppercase | Letter_Lowercase | Letter_Titlecase | Letter_Modifier | Letter_Other)) - || c == '$' || c == '_'; + return isASCIIAlpha(c) || c == '$' || c == '_' || (!isASCII(c) && (category(c) & (Letter_Uppercase | Letter_Lowercase | Letter_Titlecase | Letter_Modifier | Letter_Other))); } bool Lexer::isIdentPart(int c) { - return (category(c) & (Letter_Uppercase | Letter_Lowercase | Letter_Titlecase | Letter_Modifier | Letter_Other - | Mark_NonSpacing | Mark_SpacingCombining | Number_DecimalDigit | Punctuation_Connector)) - || c == '$' || c == '_'; + return isASCIIAlphanumeric(c) || c == '$' || c == '_' || (!isASCII(c) && (category(c) & (Letter_Uppercase | Letter_Lowercase | Letter_Titlecase | Letter_Modifier | Letter_Other + | Mark_NonSpacing | Mark_SpacingCombining | Number_DecimalDigit | Punctuation_Connector))); } static bool isDecimalDigit(int c) { - return (c >= '0' && c <= '9'); + return isASCIIDigit(c); } bool Lexer::isHexDigit(int c) { - return (c >= '0' && c <= '9' - || c >= 'a' && c <= 'f' - || c >= 'A' && c <= 'F'); + return isASCIIHexDigit(c); } bool Lexer::isOctalDigit(int c) { - return (c >= '0' && c <= '7'); + return isASCIIOctalDigit(c); } int Lexer::matchPunctuator(int& charPos, int c1, int c2, int c3, int c4) @@ -765,11 +758,11 @@ int Lexer::matchPunctuator(int& charPos, int c1, int c2, int c3, int c4) shift(1); return static_cast<int>(c1); case '{': - charPos = m_position - 4; + charPos = m_currentOffset; shift(1); return OPENBRACE; case '}': - charPos = m_position - 4; + charPos = m_currentOffset; shift(1); return CLOSEBRACE; default: @@ -888,15 +881,7 @@ bool Lexer::scanRegExp() void Lexer::clear() { - deleteAllValues(m_strings); - Vector<UString*> newStrings; - newStrings.reserveCapacity(initialStringTableCapacity); - m_strings.swap(newStrings); - - deleteAllValues(m_identifiers); - Vector<JSC::Identifier*> newIdentifiers; - newIdentifiers.reserveCapacity(initialStringTableCapacity); - m_identifiers.swap(newIdentifiers); + m_identifiers.clear(); Vector<char> newBuffer8; newBuffer8.reserveCapacity(initialReadBufferCapacity); @@ -906,15 +891,10 @@ void Lexer::clear() newBuffer16.reserveCapacity(initialReadBufferCapacity); m_buffer16.swap(newBuffer16); + m_isReparsing = false; + m_pattern = 0; m_flags = 0; } -Identifier* Lexer::makeIdentifier(const Vector<UChar>& buffer) -{ - JSC::Identifier* identifier = new JSC::Identifier(m_globalData, buffer.data(), buffer.size()); - m_identifiers.append(identifier); - return identifier; -} - } // namespace JSC diff --git a/JavaScriptCore/kjs/lexer.h b/JavaScriptCore/parser/Lexer.h index 16bc4b6..63d3892 100644 --- a/JavaScriptCore/kjs/lexer.h +++ b/JavaScriptCore/parser/Lexer.h @@ -1,7 +1,6 @@ /* - * This file is part of the KDE libraries * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) - * Copyright (C) 2007 Apple Inc. + * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -23,19 +22,20 @@ #ifndef Lexer_h #define Lexer_h -#include "lookup.h" -#include "ustring.h" -#include <wtf/Vector.h> +#include "Identifier.h" +#include "Lookup.h" +#include "SegmentedVector.h" #include "SourceCode.h" +#include <wtf/Vector.h> namespace JSC { - class Identifier; class RegExp; class Lexer : Noncopyable { public: void setCode(const SourceCode&); + void setIsReparsing() { m_isReparsing = true; } int lex(void* lvalp, void* llocp); int lineNo() const { return yylineno; } @@ -88,7 +88,7 @@ namespace JSC { bool sawError() const { return m_error; } void clear(); - SourceCode sourceCode(int openBrace, int closeBrace, int firstLine) { return SourceCode(m_source->provider(), m_source->startOffset() + openBrace + 1, m_source->startOffset() + closeBrace, firstLine); } + SourceCode sourceCode(int openBrace, int closeBrace, int firstLine) { return SourceCode(m_source->provider(), openBrace, closeBrace + 1, firstLine); } private: friend class JSGlobalData; @@ -104,7 +104,7 @@ namespace JSC { bool isLineTerminator(); static bool isOctalDigit(int); - int matchPunctuator(int& charPos, int c1, int c2, int c3, int c4); + ALWAYS_INLINE int matchPunctuator(int& charPos, int c1, int c2, int c3, int c4); static unsigned short singleEscape(unsigned short); static unsigned short convertOctal(int c1, int c2, int c3); @@ -112,7 +112,14 @@ namespace JSC { void record16(int); void record16(UChar); - JSC::Identifier* makeIdentifier(const Vector<UChar>& buffer); + JSC::Identifier* makeIdentifier(const Vector<UChar>& buffer) + { + m_identifiers.append(JSC::Identifier(m_globalData, buffer.data(), buffer.size())); + return &m_identifiers.last(); + } + + static const size_t initialReadBufferCapacity = 32; + static const size_t initialIdentifierTableCapacity = 64; int yylineno; int yycolumn; @@ -134,6 +141,7 @@ namespace JSC { const SourceCode* m_source; const UChar* m_code; unsigned int m_length; + bool m_isReparsing; int m_atLineStart; bool m_error; @@ -148,8 +156,7 @@ namespace JSC { int m_nextOffset2; int m_nextOffset3; - Vector<UString*> m_strings; - Vector<JSC::Identifier*> m_identifiers; + SegmentedVector<JSC::Identifier, initialIdentifierTableCapacity> m_identifiers; JSGlobalData* m_globalData; diff --git a/JavaScriptCore/kjs/NodeInfo.h b/JavaScriptCore/parser/NodeInfo.h index 2d11dc2..a518b23 100644 --- a/JavaScriptCore/kjs/NodeInfo.h +++ b/JavaScriptCore/parser/NodeInfo.h @@ -20,7 +20,7 @@ #ifndef NodeInfo_h #define NodeInfo_h -#include "nodes.h" +#include "Nodes.h" #include "Parser.h" namespace JSC { diff --git a/JavaScriptCore/kjs/nodes.cpp b/JavaScriptCore/parser/Nodes.cpp index b4aeb28..96fe50b 100644 --- a/JavaScriptCore/kjs/nodes.cpp +++ b/JavaScriptCore/parser/Nodes.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 Apple Inc. All rights reserved. +* Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca) * Copyright (C) 2007 Maks Orlovich * Copyright (C) 2007 Eric Seidel <eric@webkit.org> @@ -24,10 +24,10 @@ */ #include "config.h" -#include "nodes.h" +#include "Nodes.h" -#include "CodeGenerator.h" -#include "ExecState.h" +#include "BytecodeGenerator.h" +#include "CallFrame.h" #include "JSGlobalObject.h" #include "JSStaticScopeObject.h" #include "LabelScope.h" @@ -36,8 +36,8 @@ #include "RegExpObject.h" #include "SamplingTool.h" #include "Debugger.h" -#include "lexer.h" -#include "operations.h" +#include "Lexer.h" +#include "Operations.h" #include <math.h> #include <wtf/Assertions.h> #include <wtf/HashCountedSet.h> @@ -50,7 +50,73 @@ using namespace WTF; namespace JSC { -// ------------------------------ Node ----------------------------------------- +static void substitute(UString& string, const UString& substring) JSC_FAST_CALL; + +// ------------------------------ NodeReleaser -------------------------------- + +class NodeReleaser : Noncopyable { +public: + // Call this function inside the destructor of a class derived from Node. + // This will traverse the tree below this node, destroying all of those nodes, + // but without relying on recursion. + static void releaseAllNodes(ParserRefCounted* root); + + // Call this on each node in a the releaseNodes virtual function. + // It gives the node to the NodeReleaser, which will then release the + // node later at the end of the releaseAllNodes process. + template <typename T> void release(RefPtr<T>& node) { if (node) adopt(node.release()); } + void release(RefPtr<FunctionBodyNode>& node) { if (node) adoptFunctionBodyNode(node); } + +private: + NodeReleaser() { } + ~NodeReleaser() { } + + void adopt(PassRefPtr<ParserRefCounted>); + void adoptFunctionBodyNode(RefPtr<FunctionBodyNode>&); + + typedef Vector<RefPtr<ParserRefCounted> > NodeReleaseVector; + OwnPtr<NodeReleaseVector> m_vector; +}; + +void NodeReleaser::releaseAllNodes(ParserRefCounted* root) +{ + ASSERT(root); + NodeReleaser releaser; + root->releaseNodes(releaser); + if (!releaser.m_vector) + return; + // Note: The call to release.m_vector->size() is intentionally inside + // the loop, since calls to releaseNodes are expected to increase the size. + for (size_t i = 0; i < releaser.m_vector->size(); ++i) { + ParserRefCounted* node = (*releaser.m_vector)[i].get(); + if (node->hasOneRef()) + node->releaseNodes(releaser); + } +} + +void NodeReleaser::adopt(PassRefPtr<ParserRefCounted> node) +{ + ASSERT(node); + if (!node->hasOneRef()) + return; + if (!m_vector) + m_vector.set(new NodeReleaseVector); + m_vector->append(node); +} + +void NodeReleaser::adoptFunctionBodyNode(RefPtr<FunctionBodyNode>& functionBodyNode) +{ + // This sidesteps a problem where if you assign a PassRefPtr<FunctionBodyNode> + // to a PassRefPtr<Node> we leave the two reference counts (FunctionBodyNode + // and ParserRefCounted) unbalanced. It would be nice to fix this problem in + // a cleaner way -- perhaps we could remove the FunctionBodyNode reference + // count at some point. + RefPtr<Node> node = functionBodyNode; + functionBodyNode = 0; + adopt(node.release()); +} + +// ------------------------------ ParserRefCounted ----------------------------------------- #ifndef NDEBUG static RefCountedLeakCounter parserRefCountedCounter("JSC::Node"); @@ -75,6 +141,10 @@ ParserRefCounted::~ParserRefCounted() #endif } +void ParserRefCounted::releaseNodes(NodeReleaser&) +{ +} + void ParserRefCounted::ref() { // bumping from 0 to 1 is just removing from the new nodes set @@ -140,13 +210,16 @@ void ParserRefCounted::deleteNewObjects(JSGlobalData* globalData) globalData->newParserObjects = 0; } +// ------------------------------ Node -------------------------------- + Node::Node(JSGlobalData* globalData) : ParserRefCounted(globalData) { m_line = globalData->lexer->lineNo(); } -static void substitute(UString& string, const UString& substring) JSC_FAST_CALL; +// ------------------------------ ThrowableExpressionData -------------------------------- + static void substitute(UString& string, const UString& substring) { int position = string.find("%s"); @@ -157,19 +230,19 @@ static void substitute(UString& string, const UString& substring) string = newString; } -RegisterID* ThrowableExpressionData::emitThrowError(CodeGenerator& generator, ErrorType e, const char* msg) +RegisterID* ThrowableExpressionData::emitThrowError(BytecodeGenerator& generator, ErrorType e, const char* msg) { - generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset); + generator.emitExpressionInfo(divot(), startOffset(), endOffset()); RegisterID* exception = generator.emitNewError(generator.newTemporary(), e, jsString(generator.globalData(), msg)); generator.emitThrow(exception); return exception; } -RegisterID* ThrowableExpressionData::emitThrowError(CodeGenerator& generator, ErrorType e, const char* msg, const Identifier& label) +RegisterID* ThrowableExpressionData::emitThrowError(BytecodeGenerator& generator, ErrorType e, const char* msg, const Identifier& label) { UString message = msg; substitute(message, label.ustring()); - generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset); + generator.emitExpressionInfo(divot(), startOffset(), endOffset()); RegisterID* exception = generator.emitNewError(generator.newTemporary(), e, jsString(generator.globalData(), message)); generator.emitThrow(exception); return exception; @@ -201,72 +274,72 @@ void SourceElements::append(PassRefPtr<StatementNode> statement) // ------------------------------ NullNode ------------------------------------- -RegisterID* NullNode::emitCode(CodeGenerator& generator, RegisterID* dst) +RegisterID* NullNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - if (dst == ignoredResult()) + if (dst == generator.ignoredResult()) return 0; return generator.emitLoad(dst, jsNull()); } // ------------------------------ BooleanNode ---------------------------------- -RegisterID* BooleanNode::emitCode(CodeGenerator& generator, RegisterID* dst) +RegisterID* BooleanNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - if (dst == ignoredResult()) + if (dst == generator.ignoredResult()) return 0; return generator.emitLoad(dst, m_value); } // ------------------------------ NumberNode ----------------------------------- -RegisterID* NumberNode::emitCode(CodeGenerator& generator, RegisterID* dst) +RegisterID* NumberNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - if (dst == ignoredResult()) + if (dst == generator.ignoredResult()) return 0; return generator.emitLoad(dst, m_double); } // ------------------------------ StringNode ----------------------------------- -RegisterID* StringNode::emitCode(CodeGenerator& generator, RegisterID* dst) +RegisterID* StringNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - if (dst == ignoredResult()) + if (dst == generator.ignoredResult()) return 0; return generator.emitLoad(dst, m_value); } // ------------------------------ RegExpNode ----------------------------------- -RegisterID* RegExpNode::emitCode(CodeGenerator& generator, RegisterID* dst) +RegisterID* RegExpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { RefPtr<RegExp> regExp = RegExp::create(generator.globalData(), m_pattern, m_flags); if (!regExp->isValid()) return emitThrowError(generator, SyntaxError, ("Invalid regular expression: " + UString(regExp->errorMessage())).UTF8String().c_str()); - if (dst == ignoredResult()) + if (dst == generator.ignoredResult()) return 0; return generator.emitNewRegExp(generator.finalDestination(dst), regExp.get()); } // ------------------------------ ThisNode ------------------------------------- -RegisterID* ThisNode::emitCode(CodeGenerator& generator, RegisterID* dst) +RegisterID* ThisNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - if (dst == ignoredResult()) + if (dst == generator.ignoredResult()) return 0; return generator.moveToDestinationIfNeeded(dst, generator.thisRegister()); } // ------------------------------ ResolveNode ---------------------------------- -bool ResolveNode::isPure(CodeGenerator& generator) const +bool ResolveNode::isPure(BytecodeGenerator& generator) const { return generator.isLocal(m_ident); } -RegisterID* ResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst) +RegisterID* ResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { if (RegisterID* local = generator.registerFor(m_ident)) { - if (dst == ignoredResult()) + if (dst == generator.ignoredResult()) return 0; return generator.moveToDestinationIfNeeded(dst, local); } @@ -275,9 +348,32 @@ RegisterID* ResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst) return generator.emitResolve(generator.finalDestination(dst), m_ident); } +// ------------------------------ ElementNode ------------------------------------ + +ElementNode::~ElementNode() +{ + NodeReleaser::releaseAllNodes(this); +} + +void ElementNode::releaseNodes(NodeReleaser& releaser) +{ + releaser.release(m_next); + releaser.release(m_node); +} + // ------------------------------ ArrayNode ------------------------------------ -RegisterID* ArrayNode::emitCode(CodeGenerator& generator, RegisterID* dst) +ArrayNode::~ArrayNode() +{ + NodeReleaser::releaseAllNodes(this); +} + +void ArrayNode::releaseNodes(NodeReleaser& releaser) +{ + releaser.release(m_element); +} + +RegisterID* ArrayNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { // FIXME: Should we put all of this code into emitNewArray? @@ -308,12 +404,34 @@ RegisterID* ArrayNode::emitCode(CodeGenerator& generator, RegisterID* dst) return generator.moveToDestinationIfNeeded(dst, array.get()); } +// ------------------------------ PropertyNode ---------------------------- + +PropertyNode::~PropertyNode() +{ + NodeReleaser::releaseAllNodes(this); +} + +void PropertyNode::releaseNodes(NodeReleaser& releaser) +{ + releaser.release(m_assign); +} + // ------------------------------ ObjectLiteralNode ---------------------------- -RegisterID* ObjectLiteralNode::emitCode(CodeGenerator& generator, RegisterID* dst) +ObjectLiteralNode::~ObjectLiteralNode() +{ + NodeReleaser::releaseAllNodes(this); +} + +void ObjectLiteralNode::releaseNodes(NodeReleaser& releaser) +{ + releaser.release(m_list); +} + +RegisterID* ObjectLiteralNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { if (!m_list) { - if (dst == ignoredResult()) + if (dst == generator.ignoredResult()) return 0; return generator.emitNewObject(generator.finalDestination(dst)); } @@ -322,7 +440,18 @@ RegisterID* ObjectLiteralNode::emitCode(CodeGenerator& generator, RegisterID* ds // ------------------------------ PropertyListNode ----------------------------- -RegisterID* PropertyListNode::emitCode(CodeGenerator& generator, RegisterID* dst) +PropertyListNode::~PropertyListNode() +{ + NodeReleaser::releaseAllNodes(this); +} + +void PropertyListNode::releaseNodes(NodeReleaser& releaser) +{ + releaser.release(m_node); + releaser.release(m_next); +} + +RegisterID* PropertyListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { RefPtr<RegisterID> newObj = generator.tempDestination(dst); @@ -354,113 +483,239 @@ RegisterID* PropertyListNode::emitCode(CodeGenerator& generator, RegisterID* dst // ------------------------------ BracketAccessorNode -------------------------------- -RegisterID* BracketAccessorNode::emitCode(CodeGenerator& generator, RegisterID* dst) +BracketAccessorNode::~BracketAccessorNode() +{ + NodeReleaser::releaseAllNodes(this); +} + +void BracketAccessorNode::releaseNodes(NodeReleaser& releaser) +{ + releaser.release(m_base); + releaser.release(m_subscript); +} + +RegisterID* BracketAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_subscriptHasAssignments, m_subscript->isPure(generator)); RegisterID* property = generator.emitNode(m_subscript.get()); - generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset); + generator.emitExpressionInfo(divot(), startOffset(), endOffset()); return generator.emitGetByVal(generator.finalDestination(dst), base.get(), property); } // ------------------------------ DotAccessorNode -------------------------------- -RegisterID* DotAccessorNode::emitCode(CodeGenerator& generator, RegisterID* dst) +DotAccessorNode::~DotAccessorNode() +{ + NodeReleaser::releaseAllNodes(this); +} + +void DotAccessorNode::releaseNodes(NodeReleaser& releaser) +{ + releaser.release(m_base); +} + +RegisterID* DotAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { RegisterID* base = generator.emitNode(m_base.get()); - generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset); + generator.emitExpressionInfo(divot(), startOffset(), endOffset()); return generator.emitGetById(generator.finalDestination(dst), base, m_ident); } // ------------------------------ ArgumentListNode ----------------------------- -RegisterID* ArgumentListNode::emitCode(CodeGenerator& generator, RegisterID* dst) +ArgumentListNode::~ArgumentListNode() +{ + NodeReleaser::releaseAllNodes(this); +} + +void ArgumentListNode::releaseNodes(NodeReleaser& releaser) +{ + releaser.release(m_next); + releaser.release(m_expr); +} + +RegisterID* ArgumentListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { ASSERT(m_expr); return generator.emitNode(dst, m_expr.get()); } +// ------------------------------ ArgumentsNode ----------------------------- + +ArgumentsNode::~ArgumentsNode() +{ + NodeReleaser::releaseAllNodes(this); +} + +void ArgumentsNode::releaseNodes(NodeReleaser& releaser) +{ + releaser.release(m_listNode); +} + // ------------------------------ NewExprNode ---------------------------------- -RegisterID* NewExprNode::emitCode(CodeGenerator& generator, RegisterID* dst) +NewExprNode::~NewExprNode() +{ + NodeReleaser::releaseAllNodes(this); +} + +void NewExprNode::releaseNodes(NodeReleaser& releaser) +{ + releaser.release(m_expr); + releaser.release(m_args); +} + +RegisterID* NewExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { RefPtr<RegisterID> func = generator.emitNode(m_expr.get()); - return generator.emitConstruct(generator.finalDestination(dst), func.get(), m_args.get(), m_divot, m_startOffset, m_endOffset); + return generator.emitConstruct(generator.finalDestination(dst), func.get(), m_args.get(), divot(), startOffset(), endOffset()); +} + +// ------------------------------ EvalFunctionCallNode ---------------------------------- + +EvalFunctionCallNode::~EvalFunctionCallNode() +{ + NodeReleaser::releaseAllNodes(this); +} + +void EvalFunctionCallNode::releaseNodes(NodeReleaser& releaser) +{ + releaser.release(m_args); } -RegisterID* EvalFunctionCallNode::emitCode(CodeGenerator& generator, RegisterID* dst) +RegisterID* EvalFunctionCallNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - RefPtr<RegisterID> base = generator.tempDestination(dst); - RefPtr<RegisterID> func = generator.newTemporary(); - generator.emitResolveWithBase(base.get(), func.get(), generator.propertyNames().eval); - return generator.emitCallEval(generator.finalDestination(dst, base.get()), func.get(), base.get(), m_args.get(), m_divot, m_startOffset, m_endOffset); + RefPtr<RegisterID> func = generator.tempDestination(dst); + RefPtr<RegisterID> thisRegister = generator.newTemporary(); + generator.emitExpressionInfo(divot() - startOffset() + 4, 4, 0); + generator.emitResolveWithBase(thisRegister.get(), func.get(), generator.propertyNames().eval); + return generator.emitCallEval(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset()); } -RegisterID* FunctionCallValueNode::emitCode(CodeGenerator& generator, RegisterID* dst) +// ------------------------------ FunctionCallValueNode ---------------------------------- + +FunctionCallValueNode::~FunctionCallValueNode() +{ + NodeReleaser::releaseAllNodes(this); +} + +void FunctionCallValueNode::releaseNodes(NodeReleaser& releaser) +{ + releaser.release(m_expr); + releaser.release(m_args); +} + +RegisterID* FunctionCallValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { RefPtr<RegisterID> func = generator.emitNode(m_expr.get()); - return generator.emitCall(generator.finalDestination(dst), func.get(), 0, m_args.get(), m_divot, m_startOffset, m_endOffset); + RefPtr<RegisterID> thisRegister = generator.emitLoad(generator.newTemporary(), jsNull()); + return generator.emitCall(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset()); +} + +// ------------------------------ FunctionCallResolveNode ---------------------------------- + +FunctionCallResolveNode::~FunctionCallResolveNode() +{ + NodeReleaser::releaseAllNodes(this); +} + +void FunctionCallResolveNode::releaseNodes(NodeReleaser& releaser) +{ + releaser.release(m_args); } -RegisterID* FunctionCallResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst) +RegisterID* FunctionCallResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - if (RefPtr<RegisterID> local = generator.registerFor(m_ident)) - return generator.emitCall(generator.finalDestination(dst), local.get(), 0, m_args.get(), m_divot, m_startOffset, m_endOffset); + if (RefPtr<RegisterID> local = generator.registerFor(m_ident)) { + RefPtr<RegisterID> thisRegister = generator.emitLoad(generator.newTemporary(), jsNull()); + return generator.emitCall(generator.finalDestination(dst, thisRegister.get()), local.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset()); + } int index = 0; size_t depth = 0; JSObject* globalObject = 0; if (generator.findScopedProperty(m_ident, index, depth, false, globalObject) && index != missingSymbolMarker()) { RefPtr<RegisterID> func = generator.emitGetScopedVar(generator.newTemporary(), depth, index, globalObject); - return generator.emitCall(generator.finalDestination(dst), func.get(), 0, m_args.get(), m_divot, m_startOffset, m_endOffset); + RefPtr<RegisterID> thisRegister = generator.emitLoad(generator.newTemporary(), jsNull()); + return generator.emitCall(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset()); } - RefPtr<RegisterID> base = generator.tempDestination(dst); - RefPtr<RegisterID> func = generator.newTemporary(); - int identifierStart = m_divot - m_startOffset; + RefPtr<RegisterID> func = generator.tempDestination(dst); + RefPtr<RegisterID> thisRegister = generator.newTemporary(); + int identifierStart = divot() - startOffset(); generator.emitExpressionInfo(identifierStart + m_ident.size(), m_ident.size(), 0); - generator.emitResolveFunction(base.get(), func.get(), m_ident); - return generator.emitCall(generator.finalDestination(dst, base.get()), func.get(), base.get(), m_args.get(), m_divot, m_startOffset, m_endOffset); + generator.emitResolveFunction(thisRegister.get(), func.get(), m_ident); + return generator.emitCall(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset()); +} + +// ------------------------------ FunctionCallBracketNode ---------------------------------- + +FunctionCallBracketNode::~FunctionCallBracketNode() +{ + NodeReleaser::releaseAllNodes(this); +} + +void FunctionCallBracketNode::releaseNodes(NodeReleaser& releaser) +{ + releaser.release(m_base); + releaser.release(m_subscript); + releaser.release(m_args); } -RegisterID* FunctionCallBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst) +RegisterID* FunctionCallBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { RefPtr<RegisterID> base = generator.emitNode(m_base.get()); RegisterID* property = generator.emitNode(m_subscript.get()); - generator.emitExpressionInfo(m_divot - m_subexpressionDivotOffset, m_startOffset - m_subexpressionDivotOffset, m_subexpressionEndOffset); - RefPtr<RegisterID> function = generator.emitGetByVal(generator.newTemporary(), base.get(), property); - return generator.emitCall(generator.finalDestination(dst, base.get()), function.get(), base.get(), m_args.get(), m_divot, m_startOffset, m_endOffset); + generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset); + RefPtr<RegisterID> function = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property); + RefPtr<RegisterID> thisRegister = generator.emitMove(generator.newTemporary(), base.get()); + return generator.emitCall(generator.finalDestination(dst, function.get()), function.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset()); +} + +// ------------------------------ FunctionCallDotNode ---------------------------------- + +FunctionCallDotNode::~FunctionCallDotNode() +{ + NodeReleaser::releaseAllNodes(this); } -RegisterID* FunctionCallDotNode::emitCode(CodeGenerator& generator, RegisterID* dst) +void FunctionCallDotNode::releaseNodes(NodeReleaser& releaser) +{ + releaser.release(m_base); + releaser.release(m_args); +} + +RegisterID* FunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { RefPtr<RegisterID> base = generator.emitNode(m_base.get()); - generator.emitExpressionInfo(m_divot - m_subexpressionDivotOffset, m_startOffset - m_subexpressionDivotOffset, m_subexpressionEndOffset); - RefPtr<RegisterID> function = generator.emitGetById(generator.newTemporary(), base.get(), m_ident); - return generator.emitCall(generator.finalDestination(dst, base.get()), function.get(), base.get(), m_args.get(), m_divot, m_startOffset, m_endOffset); + generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset); + RefPtr<RegisterID> function = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident); + RefPtr<RegisterID> thisRegister = generator.emitMove(generator.newTemporary(), base.get()); + return generator.emitCall(generator.finalDestination(dst, function.get()), function.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset()); } // ------------------------------ PostfixResolveNode ---------------------------------- -static RegisterID* emitPreIncOrDec(CodeGenerator& generator, RegisterID* srcDst, Operator oper) +static RegisterID* emitPreIncOrDec(BytecodeGenerator& generator, RegisterID* srcDst, Operator oper) { return (oper == OpPlusPlus) ? generator.emitPreInc(srcDst) : generator.emitPreDec(srcDst); } -static RegisterID* emitPostIncOrDec(CodeGenerator& generator, RegisterID* dst, RegisterID* srcDst, Operator oper) +static RegisterID* emitPostIncOrDec(BytecodeGenerator& generator, RegisterID* dst, RegisterID* srcDst, Operator oper) { return (oper == OpPlusPlus) ? generator.emitPostInc(dst, srcDst) : generator.emitPostDec(dst, srcDst); } -RegisterID* PostfixResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst) +RegisterID* PostfixResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { if (RegisterID* local = generator.registerFor(m_ident)) { if (generator.isLocalConstant(m_ident)) { - if (dst == ignoredResult()) + if (dst == generator.ignoredResult()) return 0; return generator.emitToJSNumber(generator.finalDestination(dst), local); } - if (dst == ignoredResult()) + if (dst == generator.ignoredResult()) return emitPreIncOrDec(generator, local, m_operator); return emitPostIncOrDec(generator, generator.finalDestination(dst), local, m_operator); } @@ -471,7 +726,7 @@ RegisterID* PostfixResolveNode::emitCode(CodeGenerator& generator, RegisterID* d if (generator.findScopedProperty(m_ident, index, depth, true, globalObject) && index != missingSymbolMarker()) { RefPtr<RegisterID> value = generator.emitGetScopedVar(generator.newTemporary(), depth, index, globalObject); RegisterID* oldValue; - if (dst == ignoredResult()) { + if (dst == generator.ignoredResult()) { oldValue = 0; emitPreIncOrDec(generator, value.get(), m_operator); } else { @@ -481,11 +736,11 @@ RegisterID* PostfixResolveNode::emitCode(CodeGenerator& generator, RegisterID* d return oldValue; } - generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset); + generator.emitExpressionInfo(divot(), startOffset(), endOffset()); RefPtr<RegisterID> value = generator.newTemporary(); RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), value.get(), m_ident); RegisterID* oldValue; - if (dst == ignoredResult()) { + if (dst == generator.ignoredResult()) { oldValue = 0; emitPreIncOrDec(generator, value.get(), m_operator); } else { @@ -497,15 +752,26 @@ RegisterID* PostfixResolveNode::emitCode(CodeGenerator& generator, RegisterID* d // ------------------------------ PostfixBracketNode ---------------------------------- -RegisterID* PostfixBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst) +PostfixBracketNode::~PostfixBracketNode() +{ + NodeReleaser::releaseAllNodes(this); +} + +void PostfixBracketNode::releaseNodes(NodeReleaser& releaser) +{ + releaser.release(m_base); + releaser.release(m_subscript); +} + +RegisterID* PostfixBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { RefPtr<RegisterID> base = generator.emitNode(m_base.get()); RefPtr<RegisterID> property = generator.emitNode(m_subscript.get()); - generator.emitExpressionInfo(m_divot - m_subexpressionDivotOffset, m_startOffset - m_subexpressionDivotOffset, m_subexpressionEndOffset); + generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset); RefPtr<RegisterID> value = generator.emitGetByVal(generator.newTemporary(), base.get(), property.get()); RegisterID* oldValue; - if (dst == ignoredResult()) { + if (dst == generator.ignoredResult()) { oldValue = 0; if (m_operator == OpPlusPlus) generator.emitPreInc(value.get()); @@ -514,21 +780,31 @@ RegisterID* PostfixBracketNode::emitCode(CodeGenerator& generator, RegisterID* d } else { oldValue = (m_operator == OpPlusPlus) ? generator.emitPostInc(generator.finalDestination(dst), value.get()) : generator.emitPostDec(generator.finalDestination(dst), value.get()); } - generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset); + generator.emitExpressionInfo(divot(), startOffset(), endOffset()); generator.emitPutByVal(base.get(), property.get(), value.get()); return oldValue; } // ------------------------------ PostfixDotNode ---------------------------------- -RegisterID* PostfixDotNode::emitCode(CodeGenerator& generator, RegisterID* dst) +PostfixDotNode::~PostfixDotNode() +{ + NodeReleaser::releaseAllNodes(this); +} + +void PostfixDotNode::releaseNodes(NodeReleaser& releaser) +{ + releaser.release(m_base); +} + +RegisterID* PostfixDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { RefPtr<RegisterID> base = generator.emitNode(m_base.get()); - generator.emitExpressionInfo(m_divot - m_subexpressionDivotOffset, m_startOffset - m_subexpressionDivotOffset, m_subexpressionEndOffset); + generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset); RefPtr<RegisterID> value = generator.emitGetById(generator.newTemporary(), base.get(), m_ident); RegisterID* oldValue; - if (dst == ignoredResult()) { + if (dst == generator.ignoredResult()) { oldValue = 0; if (m_operator == OpPlusPlus) generator.emitPreInc(value.get()); @@ -537,56 +813,97 @@ RegisterID* PostfixDotNode::emitCode(CodeGenerator& generator, RegisterID* dst) } else { oldValue = (m_operator == OpPlusPlus) ? generator.emitPostInc(generator.finalDestination(dst), value.get()) : generator.emitPostDec(generator.finalDestination(dst), value.get()); } - generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset); + generator.emitExpressionInfo(divot(), startOffset(), endOffset()); generator.emitPutById(base.get(), m_ident, value.get()); return oldValue; } // ------------------------------ PostfixErrorNode ----------------------------------- -RegisterID* PostfixErrorNode::emitCode(CodeGenerator& generator, RegisterID*) +PostfixErrorNode::~PostfixErrorNode() +{ + NodeReleaser::releaseAllNodes(this); +} + +void PostfixErrorNode::releaseNodes(NodeReleaser& releaser) +{ + releaser.release(m_expr); +} + +RegisterID* PostfixErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) { return emitThrowError(generator, ReferenceError, m_operator == OpPlusPlus ? "Postfix ++ operator applied to value that is not a reference." : "Postfix -- operator applied to value that is not a reference."); } // ------------------------------ DeleteResolveNode ----------------------------------- -RegisterID* DeleteResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst) +RegisterID* DeleteResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { if (generator.registerFor(m_ident)) return generator.emitUnexpectedLoad(generator.finalDestination(dst), false); - generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset); + generator.emitExpressionInfo(divot(), startOffset(), endOffset()); RegisterID* base = generator.emitResolveBase(generator.tempDestination(dst), m_ident); return generator.emitDeleteById(generator.finalDestination(dst, base), base, m_ident); } // ------------------------------ DeleteBracketNode ----------------------------------- -RegisterID* DeleteBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst) +DeleteBracketNode::~DeleteBracketNode() +{ + NodeReleaser::releaseAllNodes(this); +} + +void DeleteBracketNode::releaseNodes(NodeReleaser& releaser) +{ + releaser.release(m_base); + releaser.release(m_subscript); +} + +RegisterID* DeleteBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { RefPtr<RegisterID> r0 = generator.emitNode(m_base.get()); RegisterID* r1 = generator.emitNode(m_subscript.get()); - generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset); + generator.emitExpressionInfo(divot(), startOffset(), endOffset()); return generator.emitDeleteByVal(generator.finalDestination(dst), r0.get(), r1); } // ------------------------------ DeleteDotNode ----------------------------------- -RegisterID* DeleteDotNode::emitCode(CodeGenerator& generator, RegisterID* dst) +DeleteDotNode::~DeleteDotNode() +{ + NodeReleaser::releaseAllNodes(this); +} + +void DeleteDotNode::releaseNodes(NodeReleaser& releaser) +{ + releaser.release(m_base); +} + +RegisterID* DeleteDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { RegisterID* r0 = generator.emitNode(m_base.get()); - generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset); + generator.emitExpressionInfo(divot(), startOffset(), endOffset()); return generator.emitDeleteById(generator.finalDestination(dst), r0, m_ident); } // ------------------------------ DeleteValueNode ----------------------------------- -RegisterID* DeleteValueNode::emitCode(CodeGenerator& generator, RegisterID* dst) +DeleteValueNode::~DeleteValueNode() { - generator.emitNode(ignoredResult(), m_expr.get()); + NodeReleaser::releaseAllNodes(this); +} + +void DeleteValueNode::releaseNodes(NodeReleaser& releaser) +{ + releaser.release(m_expr); +} + +RegisterID* DeleteValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + generator.emitNode(generator.ignoredResult(), m_expr.get()); // delete on a non-location expression ignores the value and returns true return generator.emitUnexpectedLoad(generator.finalDestination(dst), true); @@ -594,10 +911,20 @@ RegisterID* DeleteValueNode::emitCode(CodeGenerator& generator, RegisterID* dst) // ------------------------------ VoidNode ------------------------------------- -RegisterID* VoidNode::emitCode(CodeGenerator& generator, RegisterID* dst) +VoidNode::~VoidNode() { - if (dst == ignoredResult()) { - generator.emitNode(ignoredResult(), m_expr.get()); + NodeReleaser::releaseAllNodes(this); +} + +void VoidNode::releaseNodes(NodeReleaser& releaser) +{ + releaser.release(m_expr); +} + +RegisterID* VoidNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + if (dst == generator.ignoredResult()) { + generator.emitNode(generator.ignoredResult(), m_expr.get()); return 0; } RefPtr<RegisterID> r0 = generator.emitNode(m_expr.get()); @@ -606,27 +933,37 @@ RegisterID* VoidNode::emitCode(CodeGenerator& generator, RegisterID* dst) // ------------------------------ TypeOfValueNode ----------------------------------- -RegisterID* TypeOfResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst) +RegisterID* TypeOfResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { if (RegisterID* local = generator.registerFor(m_ident)) { - if (dst == ignoredResult()) + if (dst == generator.ignoredResult()) return 0; return generator.emitTypeOf(generator.finalDestination(dst), local); } RefPtr<RegisterID> scratch = generator.emitResolveBase(generator.tempDestination(dst), m_ident); generator.emitGetById(scratch.get(), scratch.get(), m_ident); - if (dst == ignoredResult()) + if (dst == generator.ignoredResult()) return 0; return generator.emitTypeOf(generator.finalDestination(dst, scratch.get()), scratch.get()); } // ------------------------------ TypeOfValueNode ----------------------------------- -RegisterID* TypeOfValueNode::emitCode(CodeGenerator& generator, RegisterID* dst) +TypeOfValueNode::~TypeOfValueNode() +{ + NodeReleaser::releaseAllNodes(this); +} + +void TypeOfValueNode::releaseNodes(NodeReleaser& releaser) +{ + releaser.release(m_expr); +} + +RegisterID* TypeOfValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - if (dst == ignoredResult()) { - generator.emitNode(ignoredResult(), m_expr.get()); + if (dst == generator.ignoredResult()) { + generator.emitNode(generator.ignoredResult(), m_expr.get()); return 0; } RefPtr<RegisterID> src = generator.emitNode(m_expr.get()); @@ -635,11 +972,11 @@ RegisterID* TypeOfValueNode::emitCode(CodeGenerator& generator, RegisterID* dst) // ------------------------------ PrefixResolveNode ---------------------------------- -RegisterID* PrefixResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst) +RegisterID* PrefixResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { if (RegisterID* local = generator.registerFor(m_ident)) { if (generator.isLocalConstant(m_ident)) { - if (dst == ignoredResult()) + if (dst == generator.ignoredResult()) return 0; RefPtr<RegisterID> r0 = generator.emitUnexpectedLoad(generator.finalDestination(dst), (m_operator == OpPlusPlus) ? 1.0 : -1.0); return generator.emitBinaryOp(op_add, r0.get(), local, r0.get(), OperandTypes()); @@ -659,7 +996,7 @@ RegisterID* PrefixResolveNode::emitCode(CodeGenerator& generator, RegisterID* ds return generator.moveToDestinationIfNeeded(dst, propDst.get()); } - generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset); + generator.emitExpressionInfo(divot(), startOffset(), endOffset()); RefPtr<RegisterID> propDst = generator.tempDestination(dst); RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), propDst.get(), m_ident); emitPreIncOrDec(generator, propDst.get(), m_operator); @@ -669,78 +1006,132 @@ RegisterID* PrefixResolveNode::emitCode(CodeGenerator& generator, RegisterID* ds // ------------------------------ PrefixBracketNode ---------------------------------- -RegisterID* PrefixBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst) +PrefixBracketNode::~PrefixBracketNode() +{ + NodeReleaser::releaseAllNodes(this); +} + +void PrefixBracketNode::releaseNodes(NodeReleaser& releaser) +{ + releaser.release(m_base); + releaser.release(m_subscript); +} + +RegisterID* PrefixBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { RefPtr<RegisterID> base = generator.emitNode(m_base.get()); RefPtr<RegisterID> property = generator.emitNode(m_subscript.get()); RefPtr<RegisterID> propDst = generator.tempDestination(dst); - generator.emitExpressionInfo(m_divot + m_subexpressionDivotOffset, m_subexpressionStartOffset, m_endOffset - m_subexpressionDivotOffset); + generator.emitExpressionInfo(divot() + m_subexpressionDivotOffset, m_subexpressionStartOffset, endOffset() - m_subexpressionDivotOffset); RegisterID* value = generator.emitGetByVal(propDst.get(), base.get(), property.get()); if (m_operator == OpPlusPlus) generator.emitPreInc(value); else generator.emitPreDec(value); - generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset); + generator.emitExpressionInfo(divot(), startOffset(), endOffset()); generator.emitPutByVal(base.get(), property.get(), value); return generator.moveToDestinationIfNeeded(dst, propDst.get()); } // ------------------------------ PrefixDotNode ---------------------------------- -RegisterID* PrefixDotNode::emitCode(CodeGenerator& generator, RegisterID* dst) +PrefixDotNode::~PrefixDotNode() +{ + NodeReleaser::releaseAllNodes(this); +} + +void PrefixDotNode::releaseNodes(NodeReleaser& releaser) +{ + releaser.release(m_base); +} + +RegisterID* PrefixDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { RefPtr<RegisterID> base = generator.emitNode(m_base.get()); RefPtr<RegisterID> propDst = generator.tempDestination(dst); - generator.emitExpressionInfo(m_divot + m_subexpressionDivotOffset, m_subexpressionStartOffset, m_endOffset - m_subexpressionDivotOffset); + generator.emitExpressionInfo(divot() + m_subexpressionDivotOffset, m_subexpressionStartOffset, endOffset() - m_subexpressionDivotOffset); RegisterID* value = generator.emitGetById(propDst.get(), base.get(), m_ident); if (m_operator == OpPlusPlus) generator.emitPreInc(value); else generator.emitPreDec(value); - generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset); + generator.emitExpressionInfo(divot(), startOffset(), endOffset()); generator.emitPutById(base.get(), m_ident, value); return generator.moveToDestinationIfNeeded(dst, propDst.get()); } // ------------------------------ PrefixErrorNode ----------------------------------- -RegisterID* PrefixErrorNode::emitCode(CodeGenerator& generator, RegisterID*) +PrefixErrorNode::~PrefixErrorNode() +{ + NodeReleaser::releaseAllNodes(this); +} + +void PrefixErrorNode::releaseNodes(NodeReleaser& releaser) +{ + releaser.release(m_expr); +} + +RegisterID* PrefixErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) { return emitThrowError(generator, ReferenceError, m_operator == OpPlusPlus ? "Prefix ++ operator applied to value that is not a reference." : "Prefix -- operator applied to value that is not a reference."); } // ------------------------------ Unary Operation Nodes ----------------------------------- -RegisterID* UnaryOpNode::emitCode(CodeGenerator& generator, RegisterID* dst) +UnaryOpNode::~UnaryOpNode() +{ + NodeReleaser::releaseAllNodes(this); +} + +void UnaryOpNode::releaseNodes(NodeReleaser& releaser) +{ + releaser.release(m_expr); +} + +RegisterID* UnaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { RegisterID* src = generator.emitNode(m_expr.get()); - return generator.emitUnaryOp(opcode(), generator.finalDestination(dst), src, m_expr->resultDescriptor()); + return generator.emitUnaryOp(opcodeID(), generator.finalDestination(dst), src); } // ------------------------------ Binary Operation Nodes ----------------------------------- -RegisterID* BinaryOpNode::emitCode(CodeGenerator& generator, RegisterID* dst) +BinaryOpNode::~BinaryOpNode() +{ + NodeReleaser::releaseAllNodes(this); +} + +void BinaryOpNode::releaseNodes(NodeReleaser& releaser) { - OpcodeID opcode = this->opcode(); - if (opcode == op_neq) { + releaser.release(m_expr1); + releaser.release(m_expr2); +} + +RegisterID* BinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + OpcodeID opcodeID = this->opcodeID(); + if (opcodeID == op_neq) { if (m_expr1->isNull() || m_expr2->isNull()) { - RefPtr<RegisterID> src = generator.emitNode(dst, m_expr1->isNull() ? m_expr2.get() : m_expr1.get()); - return generator.emitUnaryOp(op_neq_null, generator.finalDestination(dst, src.get()), src.get(), ResultType::unknown()); + RefPtr<RegisterID> src = generator.tempDestination(dst); + generator.emitNode(src.get(), m_expr1->isNull() ? m_expr2.get() : m_expr1.get()); + return generator.emitUnaryOp(op_neq_null, generator.finalDestination(dst, src.get()), src.get()); } } RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator)); RegisterID* src2 = generator.emitNode(m_expr2.get()); - return generator.emitBinaryOp(opcode, generator.finalDestination(dst, src1.get()), src1.get(), src2, OperandTypes(m_expr1->resultDescriptor(), m_expr2->resultDescriptor())); + return generator.emitBinaryOp(opcodeID, generator.finalDestination(dst, src1.get()), src1.get(), src2, OperandTypes(m_expr1->resultDescriptor(), m_expr2->resultDescriptor())); } -RegisterID* EqualNode::emitCode(CodeGenerator& generator, RegisterID* dst) +RegisterID* EqualNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { if (m_expr1->isNull() || m_expr2->isNull()) { - RefPtr<RegisterID> src = generator.emitNode(dst, m_expr1->isNull() ? m_expr2.get() : m_expr1.get()); - return generator.emitUnaryOp(op_eq_null, generator.finalDestination(dst, src.get()), src.get(), ResultType::unknown()); + RefPtr<RegisterID> src = generator.tempDestination(dst); + generator.emitNode(src.get(), m_expr1->isNull() ? m_expr2.get() : m_expr1.get()); + return generator.emitUnaryOp(op_eq_null, generator.finalDestination(dst, src.get()), src.get()); } RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator)); @@ -748,46 +1139,58 @@ RegisterID* EqualNode::emitCode(CodeGenerator& generator, RegisterID* dst) return generator.emitEqualityOp(op_eq, generator.finalDestination(dst, src1.get()), src1.get(), src2); } -RegisterID* StrictEqualNode::emitCode(CodeGenerator& generator, RegisterID* dst) +RegisterID* StrictEqualNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator)); RegisterID* src2 = generator.emitNode(m_expr2.get()); return generator.emitEqualityOp(op_stricteq, generator.finalDestination(dst, src1.get()), src1.get(), src2); } -RegisterID* ReverseBinaryOpNode::emitCode(CodeGenerator& generator, RegisterID* dst) +RegisterID* ReverseBinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator)); RegisterID* src2 = generator.emitNode(m_expr2.get()); - return generator.emitBinaryOp(opcode(), generator.finalDestination(dst, src1.get()), src2, src1.get(), OperandTypes(m_expr2->resultDescriptor(), m_expr1->resultDescriptor())); + return generator.emitBinaryOp(opcodeID(), generator.finalDestination(dst, src1.get()), src2, src1.get(), OperandTypes(m_expr2->resultDescriptor(), m_expr1->resultDescriptor())); } -RegisterID* ThrowableBinaryOpNode::emitCode(CodeGenerator& generator, RegisterID* dst) +RegisterID* ThrowableBinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator)); RegisterID* src2 = generator.emitNode(m_expr2.get()); - generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset); - return generator.emitBinaryOp(opcode(), generator.finalDestination(dst, src1.get()), src1.get(), src2, OperandTypes(m_expr1->resultDescriptor(), m_expr2->resultDescriptor())); + generator.emitExpressionInfo(divot(), startOffset(), endOffset()); + return generator.emitBinaryOp(opcodeID(), generator.finalDestination(dst, src1.get()), src1.get(), src2, OperandTypes(m_expr1->resultDescriptor(), m_expr2->resultDescriptor())); } -RegisterID* InstanceOfNode::emitCode(CodeGenerator& generator, RegisterID* dst) +RegisterID* InstanceOfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator)); RefPtr<RegisterID> src2 = generator.emitNode(m_expr2.get()); - generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset); + generator.emitExpressionInfo(divot(), startOffset(), endOffset()); + generator.emitGetByIdExceptionInfo(op_instanceof); RegisterID* src2Prototype = generator.emitGetById(generator.newTemporary(), src2.get(), generator.globalData()->propertyNames->prototype); - generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset); + generator.emitExpressionInfo(divot(), startOffset(), endOffset()); return generator.emitInstanceOf(generator.finalDestination(dst, src1.get()), src1.get(), src2.get(), src2Prototype); } -// ------------------------------ Binary Logical Nodes ---------------------------- +// ------------------------------ LogicalOpNode ---------------------------- -RegisterID* LogicalOpNode::emitCode(CodeGenerator& generator, RegisterID* dst) +LogicalOpNode::~LogicalOpNode() +{ + NodeReleaser::releaseAllNodes(this); +} + +void LogicalOpNode::releaseNodes(NodeReleaser& releaser) +{ + releaser.release(m_expr1); + releaser.release(m_expr2); +} + +RegisterID* LogicalOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { RefPtr<RegisterID> temp = generator.tempDestination(dst); - RefPtr<LabelID> target = generator.newLabel(); + RefPtr<Label> target = generator.newLabel(); generator.emitNode(temp.get(), m_expr1.get()); if (m_operator == OpLogicalAnd) @@ -802,11 +1205,23 @@ RegisterID* LogicalOpNode::emitCode(CodeGenerator& generator, RegisterID* dst) // ------------------------------ ConditionalNode ------------------------------ -RegisterID* ConditionalNode::emitCode(CodeGenerator& generator, RegisterID* dst) +ConditionalNode::~ConditionalNode() +{ + NodeReleaser::releaseAllNodes(this); +} + +void ConditionalNode::releaseNodes(NodeReleaser& releaser) +{ + releaser.release(m_logical); + releaser.release(m_expr1); + releaser.release(m_expr2); +} + +RegisterID* ConditionalNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { RefPtr<RegisterID> newDst = generator.finalDestination(dst); - RefPtr<LabelID> beforeElse = generator.newLabel(); - RefPtr<LabelID> afterElse = generator.newLabel(); + RefPtr<Label> beforeElse = generator.newLabel(); + RefPtr<Label> afterElse = generator.newLabel(); RegisterID* cond = generator.emitNode(m_logical.get()); generator.emitJumpIfFalse(cond, beforeElse.get()); @@ -824,71 +1239,81 @@ RegisterID* ConditionalNode::emitCode(CodeGenerator& generator, RegisterID* dst) // ------------------------------ ReadModifyResolveNode ----------------------------------- -// FIXME: should this be moved to be a method on CodeGenerator? -static ALWAYS_INLINE RegisterID* emitReadModifyAssignment(CodeGenerator& generator, RegisterID* dst, RegisterID* src1, RegisterID* src2, Operator oper, OperandTypes types) +ReadModifyResolveNode::~ReadModifyResolveNode() +{ + NodeReleaser::releaseAllNodes(this); +} + +void ReadModifyResolveNode::releaseNodes(NodeReleaser& releaser) +{ + releaser.release(m_right); +} + +// FIXME: should this be moved to be a method on BytecodeGenerator? +static ALWAYS_INLINE RegisterID* emitReadModifyAssignment(BytecodeGenerator& generator, RegisterID* dst, RegisterID* src1, RegisterID* src2, Operator oper, OperandTypes types) { - OpcodeID opcode; + OpcodeID opcodeID; switch (oper) { case OpMultEq: - opcode = op_mul; + opcodeID = op_mul; break; case OpDivEq: - opcode = op_div; + opcodeID = op_div; break; case OpPlusEq: - opcode = op_add; + opcodeID = op_add; break; case OpMinusEq: - opcode = op_sub; + opcodeID = op_sub; break; case OpLShift: - opcode = op_lshift; + opcodeID = op_lshift; break; case OpRShift: - opcode = op_rshift; + opcodeID = op_rshift; break; case OpURShift: - opcode = op_urshift; + opcodeID = op_urshift; break; case OpAndEq: - opcode = op_bitand; + opcodeID = op_bitand; break; case OpXOrEq: - opcode = op_bitxor; + opcodeID = op_bitxor; break; case OpOrEq: - opcode = op_bitor; + opcodeID = op_bitor; break; case OpModEq: - opcode = op_mod; + opcodeID = op_mod; break; default: ASSERT_NOT_REACHED(); return dst; } - return generator.emitBinaryOp(opcode, dst, src1, src2, types); + return generator.emitBinaryOp(opcodeID, dst, src1, src2, types); } -RegisterID* ReadModifyResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst) +RegisterID* ReadModifyResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { if (RegisterID* local = generator.registerFor(m_ident)) { if (generator.isLocalConstant(m_ident)) { RegisterID* src2 = generator.emitNode(m_right.get()); - return emitReadModifyAssignment(generator, generator.finalDestination(dst), local, src2, m_operator, OperandTypes(ResultType::unknown(), m_right->resultDescriptor())); + return emitReadModifyAssignment(generator, generator.finalDestination(dst), local, src2, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor())); } if (generator.leftHandSideNeedsCopy(m_rightHasAssignments, m_right->isPure(generator))) { RefPtr<RegisterID> result = generator.newTemporary(); generator.emitMove(result.get(), local); RegisterID* src2 = generator.emitNode(m_right.get()); - emitReadModifyAssignment(generator, result.get(), result.get(), src2, m_operator, OperandTypes(ResultType::unknown(), m_right->resultDescriptor())); + emitReadModifyAssignment(generator, result.get(), result.get(), src2, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor())); generator.emitMove(local, result.get()); return generator.moveToDestinationIfNeeded(dst, result.get()); } RegisterID* src2 = generator.emitNode(m_right.get()); - RegisterID* result = emitReadModifyAssignment(generator, local, local, src2, m_operator, OperandTypes(ResultType::unknown(), m_right->resultDescriptor())); + RegisterID* result = emitReadModifyAssignment(generator, local, local, src2, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor())); return generator.moveToDestinationIfNeeded(dst, result); } @@ -898,23 +1323,33 @@ RegisterID* ReadModifyResolveNode::emitCode(CodeGenerator& generator, RegisterID if (generator.findScopedProperty(m_ident, index, depth, true, globalObject) && index != missingSymbolMarker()) { RefPtr<RegisterID> src1 = generator.emitGetScopedVar(generator.tempDestination(dst), depth, index, globalObject); RegisterID* src2 = generator.emitNode(m_right.get()); - RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), src2, m_operator, OperandTypes(ResultType::unknown(), m_right->resultDescriptor())); + RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), src2, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor())); generator.emitPutScopedVar(depth, index, result, globalObject); return result; } RefPtr<RegisterID> src1 = generator.tempDestination(dst); - generator.emitExpressionInfo(m_divot - m_startOffset + m_ident.size(), m_ident.size(), 0); + generator.emitExpressionInfo(divot() - startOffset() + m_ident.size(), m_ident.size(), 0); RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), src1.get(), m_ident); RegisterID* src2 = generator.emitNode(m_right.get()); - generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset); - RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), src2, m_operator, OperandTypes(ResultType::unknown(), m_right->resultDescriptor())); + generator.emitExpressionInfo(divot(), startOffset(), endOffset()); + RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), src2, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor())); return generator.emitPutById(base.get(), m_ident, result); } // ------------------------------ AssignResolveNode ----------------------------------- -RegisterID* AssignResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst) +AssignResolveNode::~AssignResolveNode() +{ + NodeReleaser::releaseAllNodes(this); +} + +void AssignResolveNode::releaseNodes(NodeReleaser& releaser) +{ + releaser.release(m_right); +} + +RegisterID* AssignResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { if (RegisterID* local = generator.registerFor(m_ident)) { if (generator.isLocalConstant(m_ident)) @@ -928,7 +1363,7 @@ RegisterID* AssignResolveNode::emitCode(CodeGenerator& generator, RegisterID* ds size_t depth = 0; JSObject* globalObject = 0; if (generator.findScopedProperty(m_ident, index, depth, true, globalObject) && index != missingSymbolMarker()) { - if (dst == ignoredResult()) + if (dst == generator.ignoredResult()) dst = 0; RegisterID* value = generator.emitNode(dst, m_right.get()); generator.emitPutScopedVar(depth, index, value, globalObject); @@ -936,72 +1371,131 @@ RegisterID* AssignResolveNode::emitCode(CodeGenerator& generator, RegisterID* ds } RefPtr<RegisterID> base = generator.emitResolveBase(generator.newTemporary(), m_ident); - if (dst == ignoredResult()) + if (dst == generator.ignoredResult()) dst = 0; RegisterID* value = generator.emitNode(dst, m_right.get()); - generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset); + generator.emitExpressionInfo(divot(), startOffset(), endOffset()); return generator.emitPutById(base.get(), m_ident, value); } // ------------------------------ AssignDotNode ----------------------------------- -RegisterID* AssignDotNode::emitCode(CodeGenerator& generator, RegisterID* dst) +AssignDotNode::~AssignDotNode() +{ + NodeReleaser::releaseAllNodes(this); +} + +void AssignDotNode::releaseNodes(NodeReleaser& releaser) +{ + releaser.release(m_base); + releaser.release(m_right); +} + +RegisterID* AssignDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_rightHasAssignments, m_right->isPure(generator)); RefPtr<RegisterID> value = generator.destinationForAssignResult(dst); RegisterID* result = generator.emitNode(value.get(), m_right.get()); - generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset); + generator.emitExpressionInfo(divot(), startOffset(), endOffset()); generator.emitPutById(base.get(), m_ident, result); return generator.moveToDestinationIfNeeded(dst, result); } // ------------------------------ ReadModifyDotNode ----------------------------------- -RegisterID* ReadModifyDotNode::emitCode(CodeGenerator& generator, RegisterID* dst) +ReadModifyDotNode::~ReadModifyDotNode() +{ + NodeReleaser::releaseAllNodes(this); +} + +void ReadModifyDotNode::releaseNodes(NodeReleaser& releaser) +{ + releaser.release(m_base); + releaser.release(m_right); +} + +RegisterID* ReadModifyDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_rightHasAssignments, m_right->isPure(generator)); - generator.emitExpressionInfo(m_divot - m_subexpressionDivotOffset, m_startOffset - m_subexpressionDivotOffset, m_subexpressionEndOffset); + generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset); RefPtr<RegisterID> value = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident); RegisterID* change = generator.emitNode(m_right.get()); - RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), change, m_operator, OperandTypes(ResultType::unknown(), m_right->resultDescriptor())); + RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), change, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor())); - generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset); + generator.emitExpressionInfo(divot(), startOffset(), endOffset()); return generator.emitPutById(base.get(), m_ident, updatedValue); } // ------------------------------ AssignErrorNode ----------------------------------- -RegisterID* AssignErrorNode::emitCode(CodeGenerator& generator, RegisterID*) +AssignErrorNode::~AssignErrorNode() +{ + NodeReleaser::releaseAllNodes(this); +} + +void AssignErrorNode::releaseNodes(NodeReleaser& releaser) +{ + releaser.release(m_left); + releaser.release(m_right); +} + +RegisterID* AssignErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) { return emitThrowError(generator, ReferenceError, "Left side of assignment is not a reference."); } // ------------------------------ AssignBracketNode ----------------------------------- -RegisterID* AssignBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst) +AssignBracketNode::~AssignBracketNode() +{ + NodeReleaser::releaseAllNodes(this); +} + +void AssignBracketNode::releaseNodes(NodeReleaser& releaser) +{ + releaser.release(m_base); + releaser.release(m_subscript); + releaser.release(m_right); +} + +RegisterID* AssignBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator)); RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript.get(), m_rightHasAssignments, m_right->isPure(generator)); RefPtr<RegisterID> value = generator.destinationForAssignResult(dst); RegisterID* result = generator.emitNode(value.get(), m_right.get()); - generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset); + generator.emitExpressionInfo(divot(), startOffset(), endOffset()); generator.emitPutByVal(base.get(), property.get(), result); return generator.moveToDestinationIfNeeded(dst, result); } -RegisterID* ReadModifyBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst) +// ------------------------------ ReadModifyBracketNode ----------------------------------- + +ReadModifyBracketNode::~ReadModifyBracketNode() +{ + NodeReleaser::releaseAllNodes(this); +} + +void ReadModifyBracketNode::releaseNodes(NodeReleaser& releaser) +{ + releaser.release(m_base); + releaser.release(m_subscript); + releaser.release(m_right); +} + +RegisterID* ReadModifyBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator)); RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript.get(), m_rightHasAssignments, m_right->isPure(generator)); - generator.emitExpressionInfo(m_divot - m_subexpressionDivotOffset, m_startOffset - m_subexpressionDivotOffset, m_subexpressionEndOffset); + generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset); RefPtr<RegisterID> value = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property.get()); RegisterID* change = generator.emitNode(m_right.get()); - RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), change, m_operator, OperandTypes(ResultType::unknown(), m_right->resultDescriptor())); + RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), change, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor())); - generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset); + generator.emitExpressionInfo(divot(), startOffset(), endOffset()); generator.emitPutByVal(base.get(), property.get(), updatedValue); return updatedValue; @@ -1009,13 +1503,35 @@ RegisterID* ReadModifyBracketNode::emitCode(CodeGenerator& generator, RegisterID // ------------------------------ CommaNode ------------------------------------ -RegisterID* CommaNode::emitCode(CodeGenerator& generator, RegisterID* dst) +CommaNode::~CommaNode() { - generator.emitNode(ignoredResult(), m_expr1.get()); + NodeReleaser::releaseAllNodes(this); +} + +void CommaNode::releaseNodes(NodeReleaser& releaser) +{ + releaser.release(m_expr1); + releaser.release(m_expr2); +} + +RegisterID* CommaNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + generator.emitNode(generator.ignoredResult(), m_expr1.get()); return generator.emitNode(dst, m_expr2.get()); } -// ------------------------------ ConstDeclNode ---------------------------------- +// ------------------------------ ConstDeclNode ------------------------------------ + +ConstDeclNode::~ConstDeclNode() +{ + NodeReleaser::releaseAllNodes(this); +} + +void ConstDeclNode::releaseNodes(NodeReleaser& releaser) +{ + releaser.release(m_next); + releaser.release(m_init); +} ConstDeclNode::ConstDeclNode(JSGlobalData* globalData, const Identifier& ident, ExpressionNode* init) : ExpressionNode(globalData) @@ -1024,7 +1540,7 @@ ConstDeclNode::ConstDeclNode(JSGlobalData* globalData, const Identifier& ident, { } -RegisterID* ConstDeclNode::emitCodeSingle(CodeGenerator& generator) +RegisterID* ConstDeclNode::emitCodeSingle(BytecodeGenerator& generator) { if (RegisterID* local = generator.constRegisterFor(m_ident)) { if (!m_init) @@ -1040,7 +1556,7 @@ RegisterID* ConstDeclNode::emitCodeSingle(CodeGenerator& generator) return generator.emitPutById(base.get(), m_ident, value); } -RegisterID* ConstDeclNode::emitCode(CodeGenerator& generator, RegisterID*) +RegisterID* ConstDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) { RegisterID* result = 0; for (ConstDeclNode* n = this; n; n = n->m_next.get()) @@ -1051,17 +1567,27 @@ RegisterID* ConstDeclNode::emitCode(CodeGenerator& generator, RegisterID*) // ------------------------------ ConstStatementNode ----------------------------- -RegisterID* ConstStatementNode::emitCode(CodeGenerator& generator, RegisterID*) +ConstStatementNode::~ConstStatementNode() +{ + NodeReleaser::releaseAllNodes(this); +} + +void ConstStatementNode::releaseNodes(NodeReleaser& releaser) +{ + releaser.release(m_next); +} + +RegisterID* ConstStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) { return generator.emitNode(m_next.get()); } // ------------------------------ Helper functions for handling Vectors of StatementNode ------------------------------- -static inline RegisterID* statementListEmitCode(StatementVector& statements, CodeGenerator& generator, RegisterID* dst) +static inline RegisterID* statementListEmitCode(const StatementVector& statements, BytecodeGenerator& generator, RegisterID* dst) { - StatementVector::iterator end = statements.end(); - for (StatementVector::iterator it = statements.begin(); it != end; ++it) { + StatementVector::const_iterator end = statements.end(); + for (StatementVector::const_iterator it = statements.begin(); it != end; ++it) { StatementNode* n = it->get(); if (!n->isLoop()) generator.emitDebugHook(WillExecuteStatement, n->firstLine(), n->lastLine()); @@ -1070,17 +1596,19 @@ static inline RegisterID* statementListEmitCode(StatementVector& statements, Cod return 0; } -static inline void statementListPushFIFO(StatementVector& statements, DeclarationStacks::NodeStack& stack) +// ------------------------------ BlockNode ------------------------------------ + +BlockNode::~BlockNode() { - StatementVector::iterator it = statements.end(); - StatementVector::iterator begin = statements.begin(); - while (it != begin) { - --it; - stack.append((*it).get()); - } + NodeReleaser::releaseAllNodes(this); } -// ------------------------------ BlockNode ------------------------------------ +void BlockNode::releaseNodes(NodeReleaser& releaser) +{ + size_t size = m_children.size(); + for (size_t i = 0; i < size; ++i) + releaser.release(m_children[i]); +} BlockNode::BlockNode(JSGlobalData* globalData, SourceElements* children) : StatementNode(globalData) @@ -1089,21 +1617,21 @@ BlockNode::BlockNode(JSGlobalData* globalData, SourceElements* children) children->releaseContentsIntoVector(m_children); } -RegisterID* BlockNode::emitCode(CodeGenerator& generator, RegisterID* dst) +RegisterID* BlockNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { return statementListEmitCode(m_children, generator, dst); } // ------------------------------ EmptyStatementNode --------------------------- -RegisterID* EmptyStatementNode::emitCode(CodeGenerator&, RegisterID* dst) +RegisterID* EmptyStatementNode::emitBytecode(BytecodeGenerator&, RegisterID* dst) { return dst; } // ------------------------------ DebuggerStatementNode --------------------------- -RegisterID* DebuggerStatementNode::emitCode(CodeGenerator& generator, RegisterID* dst) +RegisterID* DebuggerStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { generator.emitDebugHook(DidReachBreakpoint, firstLine(), lastLine()); return dst; @@ -1111,7 +1639,7 @@ RegisterID* DebuggerStatementNode::emitCode(CodeGenerator& generator, RegisterID // ------------------------------ ExprStatementNode ---------------------------- -RegisterID* ExprStatementNode::emitCode(CodeGenerator& generator, RegisterID* dst) +RegisterID* ExprStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { ASSERT(m_expr); return generator.emitNode(dst, m_expr.get()); @@ -1119,7 +1647,17 @@ RegisterID* ExprStatementNode::emitCode(CodeGenerator& generator, RegisterID* ds // ------------------------------ VarStatementNode ---------------------------- -RegisterID* VarStatementNode::emitCode(CodeGenerator& generator, RegisterID*) +VarStatementNode::~VarStatementNode() +{ + NodeReleaser::releaseAllNodes(this); +} + +void VarStatementNode::releaseNodes(NodeReleaser& releaser) +{ + releaser.release(m_expr); +} + +RegisterID* VarStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) { ASSERT(m_expr); return generator.emitNode(m_expr.get()); @@ -1127,9 +1665,20 @@ RegisterID* VarStatementNode::emitCode(CodeGenerator& generator, RegisterID*) // ------------------------------ IfNode --------------------------------------- -RegisterID* IfNode::emitCode(CodeGenerator& generator, RegisterID* dst) +IfNode::~IfNode() +{ + NodeReleaser::releaseAllNodes(this); +} + +void IfNode::releaseNodes(NodeReleaser& releaser) { - RefPtr<LabelID> afterThen = generator.newLabel(); + releaser.release(m_condition); + releaser.release(m_ifBlock); +} + +RegisterID* IfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + RefPtr<Label> afterThen = generator.newLabel(); RegisterID* cond = generator.emitNode(m_condition.get()); generator.emitJumpIfFalse(cond, afterThen.get()); @@ -1140,14 +1689,27 @@ RegisterID* IfNode::emitCode(CodeGenerator& generator, RegisterID* dst) generator.emitNode(dst, m_ifBlock.get()); generator.emitLabel(afterThen.get()); - // FIXME: This should return the last statement exectuted so that it can be returned as a Completion + // FIXME: This should return the last statement executed so that it can be returned as a Completion. return 0; } -RegisterID* IfElseNode::emitCode(CodeGenerator& generator, RegisterID* dst) +// ------------------------------ IfElseNode --------------------------------------- + +IfElseNode::~IfElseNode() +{ + NodeReleaser::releaseAllNodes(this); +} + +void IfElseNode::releaseNodes(NodeReleaser& releaser) +{ + releaser.release(m_elseBlock); + IfNode::releaseNodes(releaser); +} + +RegisterID* IfElseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - RefPtr<LabelID> beforeElse = generator.newLabel(); - RefPtr<LabelID> afterElse = generator.newLabel(); + RefPtr<Label> beforeElse = generator.newLabel(); + RefPtr<Label> afterElse = generator.newLabel(); RegisterID* cond = generator.emitNode(m_condition.get()); generator.emitJumpIfFalse(cond, beforeElse.get()); @@ -1167,17 +1729,28 @@ RegisterID* IfElseNode::emitCode(CodeGenerator& generator, RegisterID* dst) generator.emitLabel(afterElse.get()); - // FIXME: This should return the last statement exectuted so that it can be returned as a Completion + // FIXME: This should return the last statement executed so that it can be returned as a Completion. return 0; } // ------------------------------ DoWhileNode ---------------------------------- -RegisterID* DoWhileNode::emitCode(CodeGenerator& generator, RegisterID* dst) +DoWhileNode::~DoWhileNode() +{ + NodeReleaser::releaseAllNodes(this); +} + +void DoWhileNode::releaseNodes(NodeReleaser& releaser) +{ + releaser.release(m_statement); + releaser.release(m_expr); +} + +RegisterID* DoWhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop); - RefPtr<LabelID> topOfLoop = generator.newLabel(); + RefPtr<Label> topOfLoop = generator.newLabel(); generator.emitLabel(topOfLoop.get()); generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); @@ -1198,13 +1771,24 @@ RegisterID* DoWhileNode::emitCode(CodeGenerator& generator, RegisterID* dst) // ------------------------------ WhileNode ------------------------------------ -RegisterID* WhileNode::emitCode(CodeGenerator& generator, RegisterID* dst) +WhileNode::~WhileNode() +{ + NodeReleaser::releaseAllNodes(this); +} + +void WhileNode::releaseNodes(NodeReleaser& releaser) +{ + releaser.release(m_expr); + releaser.release(m_statement); +} + +RegisterID* WhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop); generator.emitJump(scope->continueTarget()); - RefPtr<LabelID> topOfLoop = generator.newLabel(); + RefPtr<Label> topOfLoop = generator.newLabel(); generator.emitLabel(topOfLoop.get()); if (!m_statement->isBlock()) @@ -1225,9 +1809,22 @@ RegisterID* WhileNode::emitCode(CodeGenerator& generator, RegisterID* dst) // ------------------------------ ForNode -------------------------------------- -RegisterID* ForNode::emitCode(CodeGenerator& generator, RegisterID* dst) +ForNode::~ForNode() +{ + NodeReleaser::releaseAllNodes(this); +} + +void ForNode::releaseNodes(NodeReleaser& releaser) +{ + releaser.release(m_expr1); + releaser.release(m_expr2); + releaser.release(m_expr3); + releaser.release(m_statement); +} + +RegisterID* ForNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - if (dst == ignoredResult()) + if (dst == generator.ignoredResult()) dst = 0; RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop); @@ -1235,12 +1832,12 @@ RegisterID* ForNode::emitCode(CodeGenerator& generator, RegisterID* dst) generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); if (m_expr1) - generator.emitNode(ignoredResult(), m_expr1.get()); + generator.emitNode(generator.ignoredResult(), m_expr1.get()); - RefPtr<LabelID> condition = generator.newLabel(); + RefPtr<Label> condition = generator.newLabel(); generator.emitJump(condition.get()); - RefPtr<LabelID> topOfLoop = generator.newLabel(); + RefPtr<Label> topOfLoop = generator.newLabel(); generator.emitLabel(topOfLoop.get()); if (!m_statement->isBlock()) @@ -1249,7 +1846,7 @@ RegisterID* ForNode::emitCode(CodeGenerator& generator, RegisterID* dst) generator.emitLabel(scope->continueTarget()); if (m_expr3) - generator.emitNode(ignoredResult(), m_expr3.get()); + generator.emitNode(generator.ignoredResult(), m_expr3.get()); generator.emitLabel(condition.get()); if (m_expr2) { @@ -1264,6 +1861,19 @@ RegisterID* ForNode::emitCode(CodeGenerator& generator, RegisterID* dst) // ------------------------------ ForInNode ------------------------------------ +ForInNode::~ForInNode() +{ + NodeReleaser::releaseAllNodes(this); +} + +void ForInNode::releaseNodes(NodeReleaser& releaser) +{ + releaser.release(m_init); + releaser.release(m_lexpr); + releaser.release(m_expr); + releaser.release(m_statement); +} + ForInNode::ForInNode(JSGlobalData* globalData, ExpressionNode* l, ExpressionNode* expr, StatementNode* statement) : StatementNode(globalData) , m_init(0L) @@ -1290,24 +1900,24 @@ ForInNode::ForInNode(JSGlobalData* globalData, const Identifier& ident, Expressi // for( var foo = bar in baz ) } -RegisterID* ForInNode::emitCode(CodeGenerator& generator, RegisterID* dst) +RegisterID* ForInNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop); if (!m_lexpr->isLocation()) return emitThrowError(generator, ReferenceError, "Left side of for-in statement is not a reference."); - RefPtr<LabelID> continueTarget = generator.newLabel(); + RefPtr<Label> continueTarget = generator.newLabel(); generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); if (m_init) - generator.emitNode(ignoredResult(), m_init.get()); + generator.emitNode(generator.ignoredResult(), m_init.get()); RegisterID* forInBase = generator.emitNode(m_expr.get()); RefPtr<RegisterID> iter = generator.emitGetPropertyNames(generator.newTemporary(), forInBase); generator.emitJump(scope->continueTarget()); - RefPtr<LabelID> loopStart = generator.newLabel(); + RefPtr<Label> loopStart = generator.newLabel(); generator.emitLabel(loopStart.get()); RegisterID* propertyName; @@ -1319,7 +1929,7 @@ RegisterID* ForInNode::emitCode(CodeGenerator& generator, RegisterID* dst) RefPtr<RegisterID> protect = propertyName; RegisterID* base = generator.emitResolveBase(generator.newTemporary(), ident); - generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset); + generator.emitExpressionInfo(divot(), startOffset(), endOffset()); generator.emitPutById(base, ident, propertyName); } } else if (m_lexpr->isDotAccessorNode()) { @@ -1356,7 +1966,7 @@ RegisterID* ForInNode::emitCode(CodeGenerator& generator, RegisterID* dst) // ------------------------------ ContinueNode --------------------------------- // ECMA 12.7 -RegisterID* ContinueNode::emitCode(CodeGenerator& generator, RegisterID* dst) +RegisterID* ContinueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { LabelScope* scope = generator.continueTarget(m_ident); @@ -1372,7 +1982,7 @@ RegisterID* ContinueNode::emitCode(CodeGenerator& generator, RegisterID* dst) // ------------------------------ BreakNode ------------------------------------ // ECMA 12.8 -RegisterID* BreakNode::emitCode(CodeGenerator& generator, RegisterID* dst) +RegisterID* BreakNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { LabelScope* scope = generator.breakTarget(m_ident); @@ -1387,16 +1997,26 @@ RegisterID* BreakNode::emitCode(CodeGenerator& generator, RegisterID* dst) // ------------------------------ ReturnNode ----------------------------------- -RegisterID* ReturnNode::emitCode(CodeGenerator& generator, RegisterID* dst) +ReturnNode::~ReturnNode() +{ + NodeReleaser::releaseAllNodes(this); +} + +void ReturnNode::releaseNodes(NodeReleaser& releaser) +{ + releaser.release(m_value); +} + +RegisterID* ReturnNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { if (generator.codeType() != FunctionCode) return emitThrowError(generator, SyntaxError, "Invalid return statement."); - if (dst == ignoredResult()) + if (dst == generator.ignoredResult()) dst = 0; RegisterID* r0 = m_value ? generator.emitNode(dst, m_value.get()) : generator.emitLoad(dst, jsUndefined()); if (generator.scopeDepth()) { - RefPtr<LabelID> l0 = generator.newLabel(); + RefPtr<Label> l0 = generator.newLabel(); generator.emitJumpScopes(l0.get(), 0); generator.emitLabel(l0.get()); } @@ -1406,9 +2026,21 @@ RegisterID* ReturnNode::emitCode(CodeGenerator& generator, RegisterID* dst) // ------------------------------ WithNode ------------------------------------- -RegisterID* WithNode::emitCode(CodeGenerator& generator, RegisterID* dst) +WithNode::~WithNode() +{ + NodeReleaser::releaseAllNodes(this); +} + +void WithNode::releaseNodes(NodeReleaser& releaser) { - RefPtr<RegisterID> scope = generator.emitNode(m_expr.get()); // scope must be protected until popped + releaser.release(m_expr); + releaser.release(m_statement); +} + +RegisterID* WithNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + RefPtr<RegisterID> scope = generator.newTemporary(); + generator.emitNode(scope.get(), m_expr.get()); // scope must be protected until popped generator.emitExpressionInfo(m_divot, m_expressionLength, 0); generator.emitPushScope(scope.get()); RegisterID* result = generator.emitNode(dst, m_statement.get()); @@ -1416,7 +2048,45 @@ RegisterID* WithNode::emitCode(CodeGenerator& generator, RegisterID* dst) return result; } +// ------------------------------ CaseClauseNode -------------------------------- + +CaseClauseNode::~CaseClauseNode() +{ + NodeReleaser::releaseAllNodes(this); +} + +void CaseClauseNode::releaseNodes(NodeReleaser& releaser) +{ + releaser.release(m_expr); +} + +// ------------------------------ ClauseListNode -------------------------------- + +ClauseListNode::~ClauseListNode() +{ + NodeReleaser::releaseAllNodes(this); +} + +void ClauseListNode::releaseNodes(NodeReleaser& releaser) +{ + releaser.release(m_clause); + releaser.release(m_next); +} + // ------------------------------ CaseBlockNode -------------------------------- + +CaseBlockNode::~CaseBlockNode() +{ + NodeReleaser::releaseAllNodes(this); +} + +void CaseBlockNode::releaseNodes(NodeReleaser& releaser) +{ + releaser.release(m_list1); + releaser.release(m_defaultClause); + releaser.release(m_list2); +} + enum SwitchKind { SwitchUnset = 0, SwitchNumber = 1, @@ -1431,7 +2101,8 @@ static void processClauseList(ClauseListNode* list, Vector<ExpressionNode*, 8>& literalVector.append(clauseExpression); if (clauseExpression->isNumber()) { double value = static_cast<NumberNode*>(clauseExpression)->value(); - if ((typeForTable & ~SwitchNumber) || !JSImmediate::from(value)) { + JSValuePtr jsValue = JSValuePtr::makeInt32Fast(static_cast<int32_t>(value)); + if ((typeForTable & ~SwitchNumber) || !jsValue || (jsValue.getInt32Fast() != value)) { typeForTable = SwitchNeither; break; } @@ -1494,10 +2165,10 @@ SwitchInfo::SwitchType CaseBlockNode::tryOptimizedSwitch(Vector<ExpressionNode*, return SwitchInfo::SwitchString; } -RegisterID* CaseBlockNode::emitCodeForBlock(CodeGenerator& generator, RegisterID* switchExpression, RegisterID* dst) +RegisterID* CaseBlockNode::emitBytecodeForBlock(BytecodeGenerator& generator, RegisterID* switchExpression, RegisterID* dst) { - RefPtr<LabelID> defaultLabel; - Vector<RefPtr<LabelID>, 8> labelVector; + RefPtr<Label> defaultLabel; + Vector<RefPtr<Label>, 8> labelVector; Vector<ExpressionNode*, 8> literalVector; int32_t min_num = std::numeric_limits<int32_t>::max(); int32_t max_num = std::numeric_limits<int32_t>::min(); @@ -1560,12 +2231,23 @@ RegisterID* CaseBlockNode::emitCodeForBlock(CodeGenerator& generator, RegisterID // ------------------------------ SwitchNode ----------------------------------- -RegisterID* SwitchNode::emitCode(CodeGenerator& generator, RegisterID* dst) +SwitchNode::~SwitchNode() +{ + NodeReleaser::releaseAllNodes(this); +} + +void SwitchNode::releaseNodes(NodeReleaser& releaser) +{ + releaser.release(m_expr); + releaser.release(m_block); +} + +RegisterID* SwitchNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Switch); RefPtr<RegisterID> r0 = generator.emitNode(m_expr.get()); - RegisterID* r1 = m_block->emitCodeForBlock(generator, r0.get(), dst); + RegisterID* r1 = m_block->emitBytecodeForBlock(generator, r0.get(), dst); generator.emitLabel(scope->breakTarget()); return r1; @@ -1573,7 +2255,17 @@ RegisterID* SwitchNode::emitCode(CodeGenerator& generator, RegisterID* dst) // ------------------------------ LabelNode ------------------------------------ -RegisterID* LabelNode::emitCode(CodeGenerator& generator, RegisterID* dst) +LabelNode::~LabelNode() +{ + NodeReleaser::releaseAllNodes(this); +} + +void LabelNode::releaseNodes(NodeReleaser& releaser) +{ + releaser.release(m_statement); +} + +RegisterID* LabelNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { if (generator.breakTarget(m_name)) return emitThrowError(generator, SyntaxError, "Duplicate label: %s.", m_name); @@ -1587,23 +2279,45 @@ RegisterID* LabelNode::emitCode(CodeGenerator& generator, RegisterID* dst) // ------------------------------ ThrowNode ------------------------------------ -RegisterID* ThrowNode::emitCode(CodeGenerator& generator, RegisterID* dst) +ThrowNode::~ThrowNode() +{ + NodeReleaser::releaseAllNodes(this); +} + +void ThrowNode::releaseNodes(NodeReleaser& releaser) +{ + releaser.release(m_expr); +} + +RegisterID* ThrowNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - if (dst == ignoredResult()) + if (dst == generator.ignoredResult()) dst = 0; RefPtr<RegisterID> expr = generator.emitNode(dst, m_expr.get()); - generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset); + generator.emitExpressionInfo(divot(), startOffset(), endOffset()); generator.emitThrow(expr.get()); return dst; } // ------------------------------ TryNode -------------------------------------- -RegisterID* TryNode::emitCode(CodeGenerator& generator, RegisterID* dst) +TryNode::~TryNode() +{ + NodeReleaser::releaseAllNodes(this); +} + +void TryNode::releaseNodes(NodeReleaser& releaser) +{ + releaser.release(m_tryBlock); + releaser.release(m_catchBlock); + releaser.release(m_finallyBlock); +} + +RegisterID* TryNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - RefPtr<LabelID> tryStartLabel = generator.newLabel(); - RefPtr<LabelID> tryEndLabel = generator.newLabel(); - RefPtr<LabelID> finallyStart; + RefPtr<Label> tryStartLabel = generator.newLabel(); + RefPtr<Label> tryEndLabel = generator.newLabel(); + RefPtr<Label> finallyStart; RefPtr<RegisterID> finallyReturnAddr; if (m_finallyBlock) { finallyStart = generator.newLabel(); @@ -1615,10 +2329,16 @@ RegisterID* TryNode::emitCode(CodeGenerator& generator, RegisterID* dst) generator.emitLabel(tryEndLabel.get()); if (m_catchBlock) { - RefPtr<LabelID> handlerEndLabel = generator.newLabel(); + RefPtr<Label> handlerEndLabel = generator.newLabel(); generator.emitJump(handlerEndLabel.get()); RefPtr<RegisterID> exceptionRegister = generator.emitCatch(generator.newTemporary(), tryStartLabel.get(), tryEndLabel.get()); - generator.emitPushNewScope(exceptionRegister.get(), m_exceptionIdent, exceptionRegister.get()); + if (m_catchHasEval) { + RefPtr<RegisterID> dynamicScopeObject = generator.emitNewObject(generator.newTemporary()); + generator.emitPutById(dynamicScopeObject.get(), m_exceptionIdent, exceptionRegister.get()); + generator.emitMove(exceptionRegister.get(), dynamicScopeObject.get()); + generator.emitPushScope(exceptionRegister.get()); + } else + generator.emitPushNewScope(exceptionRegister.get(), m_exceptionIdent, exceptionRegister.get()); generator.emitNode(dst, m_catchBlock.get()); generator.emitPopScope(); generator.emitLabel(handlerEndLabel.get()); @@ -1631,7 +2351,7 @@ RegisterID* TryNode::emitCode(CodeGenerator& generator, RegisterID* dst) // ref the highest register ever used as a conservative // approach to not clobbering anything important RefPtr<RegisterID> highestUsedRegister = generator.highestUsedRegister(); - RefPtr<LabelID> finallyEndLabel = generator.newLabel(); + RefPtr<Label> finallyEndLabel = generator.newLabel(); generator.emitJumpSubroutine(finallyReturnAddr.get(), finallyStart.get()); // Use a label to record the subtle fact that sret will return to the // next instruction. sret is the only way to jump without an explicit label. @@ -1657,24 +2377,78 @@ RegisterID* TryNode::emitCode(CodeGenerator& generator, RegisterID* dst) return dst; } +// ------------------------------ ParameterNode ----------------------------- -// ------------------------------ ScopeNode ----------------------------- +ParameterNode::~ParameterNode() +{ + NodeReleaser::releaseAllNodes(this); +} -ScopeNode::ScopeNode(JSGlobalData* globalData, const SourceCode& source, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, CodeFeatures features, int numConstants) - : BlockNode(globalData, children) - , m_source(source) - , m_features(features) - , m_numConstants(numConstants) +void ParameterNode::releaseNodes(NodeReleaser& releaser) +{ + releaser.release(m_next); +} + +// -----------------------------ScopeNodeData --------------------------- + +ScopeNodeData::ScopeNodeData(SourceElements* children, VarStack* varStack, FunctionStack* funcStack, int numConstants) + : m_numConstants(numConstants) { if (varStack) m_varStack = *varStack; if (funcStack) m_functionStack = *funcStack; + if (children) + children->releaseContentsIntoVector(m_children); +} + +void ScopeNodeData::mark() +{ + FunctionStack::iterator end = m_functionStack.end(); + for (FunctionStack::iterator ptr = m_functionStack.begin(); ptr != end; ++ptr) { + FunctionBodyNode* body = (*ptr)->body(); + if (!body->isGenerated()) + continue; + body->generatedBytecode().mark(); + } +} + +// ------------------------------ ScopeNode ----------------------------- + +ScopeNode::ScopeNode(JSGlobalData* globalData) + : StatementNode(globalData) + , m_features(NoFeatures) +{ #if ENABLE(OPCODE_SAMPLING) - globalData->machine->sampler()->notifyOfScope(this); + globalData->interpreter->sampler()->notifyOfScope(this); #endif } +ScopeNode::ScopeNode(JSGlobalData* globalData, const SourceCode& source, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, CodeFeatures features, int numConstants) + : StatementNode(globalData) + , m_data(new ScopeNodeData(children, varStack, funcStack, numConstants)) + , m_features(features) + , m_source(source) +{ +#if ENABLE(OPCODE_SAMPLING) + globalData->interpreter->sampler()->notifyOfScope(this); +#endif +} + +ScopeNode::~ScopeNode() +{ + NodeReleaser::releaseAllNodes(this); +} + +void ScopeNode::releaseNodes(NodeReleaser& releaser) +{ + if (!m_data) + return; + size_t size = m_data->m_children.size(); + for (size_t i = 0; i < size; ++i) + releaser.release(m_data->m_children[i]); +} + // ------------------------------ ProgramNode ----------------------------- ProgramNode::ProgramNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants) @@ -1687,6 +2461,32 @@ ProgramNode* ProgramNode::create(JSGlobalData* globalData, SourceElements* child return new ProgramNode(globalData, children, varStack, funcStack, source, features, numConstants); } +RegisterID* ProgramNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) +{ + generator.emitDebugHook(WillExecuteProgram, firstLine(), lastLine()); + + RefPtr<RegisterID> dstRegister = generator.newTemporary(); + generator.emitLoad(dstRegister.get(), jsUndefined()); + statementListEmitCode(children(), generator, dstRegister.get()); + + generator.emitDebugHook(DidExecuteProgram, firstLine(), lastLine()); + generator.emitEnd(dstRegister.get()); + return 0; +} + +void ProgramNode::generateBytecode(ScopeChainNode* scopeChainNode) +{ + ScopeChain scopeChain(scopeChainNode); + JSGlobalObject* globalObject = scopeChain.globalObject(); + + m_code.set(new ProgramCodeBlock(this, GlobalCode, globalObject, source().provider())); + + BytecodeGenerator generator(this, globalObject->debugger(), scopeChain, &globalObject->symbolTable(), m_code.get()); + generator.generate(); + + destroyData(); +} + // ------------------------------ EvalNode ----------------------------- EvalNode::EvalNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants) @@ -1694,38 +2494,71 @@ EvalNode::EvalNode(JSGlobalData* globalData, SourceElements* children, VarStack* { } -RegisterID* EvalNode::emitCode(CodeGenerator& generator, RegisterID*) +EvalNode* EvalNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants) +{ + return new EvalNode(globalData, children, varStack, funcStack, source, features, numConstants); +} + +RegisterID* EvalNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) { generator.emitDebugHook(WillExecuteProgram, firstLine(), lastLine()); RefPtr<RegisterID> dstRegister = generator.newTemporary(); generator.emitLoad(dstRegister.get(), jsUndefined()); - statementListEmitCode(m_children, generator, dstRegister.get()); + statementListEmitCode(children(), generator, dstRegister.get()); generator.emitDebugHook(DidExecuteProgram, firstLine(), lastLine()); generator.emitEnd(dstRegister.get()); return 0; } -void EvalNode::generateCode(ScopeChainNode* scopeChainNode) +void EvalNode::generateBytecode(ScopeChainNode* scopeChainNode) { ScopeChain scopeChain(scopeChainNode); JSGlobalObject* globalObject = scopeChain.globalObject(); - SymbolTable symbolTable; - m_code.set(new EvalCodeBlock(this, globalObject, source().provider())); + m_code.set(new EvalCodeBlock(this, globalObject, source().provider(), scopeChain.localDepth())); - CodeGenerator generator(this, globalObject->debugger(), scopeChain, &symbolTable, m_code.get()); + BytecodeGenerator generator(this, globalObject->debugger(), scopeChain, &m_code->symbolTable(), m_code.get()); generator.generate(); + + // Eval code needs to hang on to its declaration stacks to keep declaration info alive until Interpreter::execute time, + // so the entire ScopeNodeData cannot be destoyed. + children().clear(); } -EvalNode* EvalNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants) +EvalCodeBlock& EvalNode::bytecodeForExceptionInfoReparse(ScopeChainNode* scopeChainNode, CodeBlock* codeBlockBeingRegeneratedFrom) { - return new EvalNode(globalData, children, varStack, funcStack, source, features, numConstants); + ASSERT(!m_code); + + ScopeChain scopeChain(scopeChainNode); + JSGlobalObject* globalObject = scopeChain.globalObject(); + + m_code.set(new EvalCodeBlock(this, globalObject, source().provider(), scopeChain.localDepth())); + + BytecodeGenerator generator(this, globalObject->debugger(), scopeChain, &m_code->symbolTable(), m_code.get()); + generator.setRegeneratingForExceptionInfo(codeBlockBeingRegeneratedFrom); + generator.generate(); + + return *m_code; +} + +void EvalNode::mark() +{ + // We don't need to mark our own CodeBlock as the JSGlobalObject takes care of that + data()->mark(); } // ------------------------------ FunctionBodyNode ----------------------------- +FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData) + : ScopeNode(globalData) + , m_parameters(0) + , m_parameterCount(0) + , m_refCount(0) +{ +} + FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& sourceCode, CodeFeatures features, int numConstants) : ScopeNode(globalData, sourceCode, children, varStack, funcStack, features, numConstants) , m_parameters(0) @@ -1736,8 +2569,10 @@ FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData, SourceElements* chi FunctionBodyNode::~FunctionBodyNode() { - if (m_parameters) - fastFree(m_parameters); + ASSERT(!m_refCount); + for (size_t i = 0; i < m_parameterCount; ++i) + m_parameters[i].~Identifier(); + fastFree(m_parameters); } void FunctionBodyNode::finishParsing(const SourceCode& source, ParameterNode* firstParameter) @@ -1764,9 +2599,9 @@ void FunctionBodyNode::mark() m_code->mark(); } -FunctionBodyNode* FunctionBodyNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, CodeFeatures features, int numConstants) +FunctionBodyNode* FunctionBodyNode::create(JSGlobalData* globalData) { - return new FunctionBodyNode(globalData, children, varStack, funcStack, SourceCode(), features, numConstants); + return new FunctionBodyNode(globalData); } FunctionBodyNode* FunctionBodyNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& sourceCode, CodeFeatures features, int numConstants) @@ -1774,51 +2609,55 @@ FunctionBodyNode* FunctionBodyNode::create(JSGlobalData* globalData, SourceEleme return new FunctionBodyNode(globalData, children, varStack, funcStack, sourceCode, features, numConstants); } -void FunctionBodyNode::generateCode(ScopeChainNode* scopeChainNode) +void FunctionBodyNode::generateBytecode(ScopeChainNode* scopeChainNode) { + // This branch is only necessary since you can still create a non-stub FunctionBodyNode by + // calling Parser::parse<FunctionBodyNode>(). + if (!data()) + scopeChainNode->globalData->parser->reparseInPlace(scopeChainNode->globalData, this); + ASSERT(data()); + ScopeChain scopeChain(scopeChainNode); JSGlobalObject* globalObject = scopeChain.globalObject(); m_code.set(new CodeBlock(this, FunctionCode, source().provider(), source().startOffset())); - CodeGenerator generator(this, globalObject->debugger(), scopeChain, &m_symbolTable, m_code.get()); + BytecodeGenerator generator(this, globalObject->debugger(), scopeChain, &m_code->symbolTable(), m_code.get()); generator.generate(); -} -RegisterID* FunctionBodyNode::emitCode(CodeGenerator& generator, RegisterID*) -{ - generator.emitDebugHook(DidEnterCallFrame, firstLine(), lastLine()); - statementListEmitCode(m_children, generator, ignoredResult()); - if (!m_children.size() || !m_children.last()->isReturnNode()) { - RegisterID* r0 = generator.emitLoad(0, jsUndefined()); - generator.emitDebugHook(WillLeaveCallFrame, firstLine(), lastLine()); - generator.emitReturn(r0); - } - return 0; + destroyData(); } -RegisterID* ProgramNode::emitCode(CodeGenerator& generator, RegisterID*) +CodeBlock& FunctionBodyNode::bytecodeForExceptionInfoReparse(ScopeChainNode* scopeChainNode, CodeBlock* codeBlockBeingRegeneratedFrom) { - generator.emitDebugHook(WillExecuteProgram, firstLine(), lastLine()); + ASSERT(!m_code); - RefPtr<RegisterID> dstRegister = generator.newTemporary(); - generator.emitLoad(dstRegister.get(), jsUndefined()); - statementListEmitCode(m_children, generator, dstRegister.get()); + ScopeChain scopeChain(scopeChainNode); + JSGlobalObject* globalObject = scopeChain.globalObject(); - generator.emitDebugHook(DidExecuteProgram, firstLine(), lastLine()); - generator.emitEnd(dstRegister.get()); - return 0; + m_code.set(new CodeBlock(this, FunctionCode, source().provider(), source().startOffset())); + + BytecodeGenerator generator(this, globalObject->debugger(), scopeChain, &m_code->symbolTable(), m_code.get()); + generator.setRegeneratingForExceptionInfo(codeBlockBeingRegeneratedFrom); + generator.generate(); + + return *m_code; } -void ProgramNode::generateCode(ScopeChainNode* scopeChainNode) +RegisterID* FunctionBodyNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) { - ScopeChain scopeChain(scopeChainNode); - JSGlobalObject* globalObject = scopeChain.globalObject(); - - m_code.set(new ProgramCodeBlock(this, GlobalCode, globalObject, source().provider())); - - CodeGenerator generator(this, globalObject->debugger(), scopeChain, &globalObject->symbolTable(), m_code.get(), m_varStack, m_functionStack); - generator.generate(); + generator.emitDebugHook(DidEnterCallFrame, firstLine(), lastLine()); + statementListEmitCode(children(), generator, generator.ignoredResult()); + if (children().size() && children().last()->isBlock()) { + BlockNode* blockNode = static_cast<BlockNode*>(children().last().get()); + if (blockNode->children().size() && blockNode->children().last()->isReturnNode()) + return 0; + } + + RegisterID* r0 = generator.emitLoad(0, jsUndefined()); + generator.emitDebugHook(WillLeaveCallFrame, firstLine(), lastLine()); + generator.emitReturn(r0); + return 0; } UString FunctionBodyNode::paramString() const @@ -1842,19 +2681,43 @@ Identifier* FunctionBodyNode::copyParameters() // ------------------------------ FuncDeclNode --------------------------------- +FuncDeclNode::~FuncDeclNode() +{ + NodeReleaser::releaseAllNodes(this); +} + +void FuncDeclNode::releaseNodes(NodeReleaser& releaser) +{ + releaser.release(m_parameter); + releaser.release(m_body); +} + JSFunction* FuncDeclNode::makeFunction(ExecState* exec, ScopeChainNode* scopeChain) { return new (exec) JSFunction(exec, m_ident, m_body.get(), scopeChain); } -RegisterID* FuncDeclNode::emitCode(CodeGenerator&, RegisterID* dst) +RegisterID* FuncDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { + if (dst == generator.ignoredResult()) + dst = 0; return dst; } // ------------------------------ FuncExprNode --------------------------------- -RegisterID* FuncExprNode::emitCode(CodeGenerator& generator, RegisterID* dst) +FuncExprNode::~FuncExprNode() +{ + NodeReleaser::releaseAllNodes(this); +} + +void FuncExprNode::releaseNodes(NodeReleaser& releaser) +{ + releaser.release(m_parameter); + releaser.release(m_body); +} + +RegisterID* FuncExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { return generator.emitNewFunctionExpression(generator.finalDestination(dst), this); } @@ -1879,4 +2742,25 @@ JSFunction* FuncExprNode::makeFunction(ExecState* exec, ScopeChainNode* scopeCha return func; } +#ifdef ANDROID_INSTRUMENT +static size_t nodesSize = 0; + +void* Node::operator new(size_t s) throw() +{ + nodesSize += s; + return ::operator new(s); +} + +void Node::operator delete(void* ptr, size_t s) +{ + nodesSize -= s; + ::operator delete(ptr); +} + +size_t Node::reportJavaScriptNodesSize() +{ + return nodesSize; +} +#endif + } // namespace JSC diff --git a/JavaScriptCore/kjs/nodes.h b/JavaScriptCore/parser/Nodes.h index a70d350..baa9984 100644 --- a/JavaScriptCore/kjs/nodes.h +++ b/JavaScriptCore/parser/Nodes.h @@ -1,7 +1,7 @@ /* * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) * Copyright (C) 2001 Peter Kelly (pmk@post.com) - * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca) * Copyright (C) 2007 Maks Orlovich * Copyright (C) 2007 Eric Seidel <eric@webkit.org> @@ -27,18 +27,12 @@ #define NODES_H_ #include "Error.h" -#include "JSString.h" -#include "JSType.h" #include "Opcode.h" -#include "RegisterID.h" #include "ResultType.h" #include "SourceCode.h" #include "SymbolTable.h" -#include "regexp.h" -#include <wtf/ListRefPtr.h> #include <wtf/MathExtras.h> #include <wtf/OwnPtr.h> -#include <wtf/UnusedParam.h> #include <wtf/Vector.h> #if PLATFORM(X86) && COMPILER(GCC) @@ -50,16 +44,17 @@ namespace JSC { class CodeBlock; - class CodeGenerator; + class BytecodeGenerator; class FuncDeclNode; - class Node; class EvalCodeBlock; class JSFunction; + class NodeReleaser; class ProgramCodeBlock; class PropertyListNode; - class SourceStream; + class RegisterID; + class ScopeChainNode; - typedef unsigned int CodeFeatures; + typedef unsigned CodeFeatures; const CodeFeatures NoFeatures = 0; const CodeFeatures EvalFeature = 1 << 0; @@ -93,38 +88,15 @@ namespace JSC { OpLogicalOr }; - enum Precedence { - PrecPrimary, - PrecMember, - PrecCall, - PrecLeftHandSide, - PrecPostfix, - PrecUnary, - PrecMultiplicative, - PrecAdditive, - PrecShift, - PrecRelational, - PrecEquality, - PrecBitwiseAnd, - PrecBitwiseXor, - PrecBitwiseOr, - PrecLogicalAnd, - PrecLogicalOr, - PrecConditional, - PrecAssignment, - PrecExpression - }; - namespace DeclarationStacks { - typedef Vector<Node*, 16> NodeStack; enum VarAttrs { IsConstant = 1, HasInitializer = 2 }; - typedef Vector<std::pair<Identifier, unsigned>, 16> VarStack; - typedef Vector<RefPtr<FuncDeclNode>, 16> FunctionStack; + typedef Vector<std::pair<Identifier, unsigned> > VarStack; + typedef Vector<RefPtr<FuncDeclNode> > FunctionStack; } struct SwitchInfo { enum SwitchType { SwitchNone, SwitchImmediate, SwitchCharacter, SwitchString }; - uint32_t opcodeOffset; + uint32_t bytecodeOffset; SwitchType switchType; }; @@ -132,24 +104,24 @@ namespace JSC { protected: ParserRefCounted(JSGlobalData*) JSC_FAST_CALL; - JSGlobalData* m_globalData; - public: + virtual ~ParserRefCounted(); + + // Nonrecursive destruction. + virtual void releaseNodes(NodeReleaser&); + void ref() JSC_FAST_CALL; void deref() JSC_FAST_CALL; bool hasOneRef() JSC_FAST_CALL; static void deleteNewObjects(JSGlobalData*) JSC_FAST_CALL; - virtual ~ParserRefCounted(); + private: + JSGlobalData* m_globalData; }; class Node : public ParserRefCounted { public: - typedef DeclarationStacks::NodeStack NodeStack; - typedef DeclarationStacks::VarStack VarStack; - typedef DeclarationStacks::FunctionStack FunctionStack; - Node(JSGlobalData*) JSC_FAST_CALL; /* @@ -174,30 +146,27 @@ namespace JSC { because the assignment node, "x =", passes r[x] as dst to the number node, "1". */ - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* dst = 0) JSC_FAST_CALL - { - ASSERT_WITH_MESSAGE(0, "Don't know how to generate code for:\n%s\n", toString().ascii()); - UNUSED_PARAM(dst); - return 0; - } // FIXME: Make this pure virtual. + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* dst = 0) JSC_FAST_CALL = 0; - UString toString() const JSC_FAST_CALL; int lineNo() const { return m_line; } - virtual bool isReturnNode() const JSC_FAST_CALL { return false; } +#ifdef ANDROID_INSTRUMENT + // Overridden to prevent the normal new from being called. + void* operator new(size_t) throw(); + + // Overridden to prevent the normal delete from being called. + void operator delete(void*, size_t); + + static size_t reportJavaScriptNodesSize(); +#endif - // Serialization. - virtual void streamTo(SourceStream&) const JSC_FAST_CALL = 0; - virtual Precedence precedence() const = 0; - virtual bool needsParensIfLeftmost() const { return false; } - protected: int m_line; }; class ExpressionNode : public Node { public: - ExpressionNode(JSGlobalData* globalData, ResultType resultDesc = ResultType::unknown()) JSC_FAST_CALL + ExpressionNode(JSGlobalData* globalData, ResultType resultDesc = ResultType::unknownType()) JSC_FAST_CALL : Node(globalData) , m_resultDesc(resultDesc) { @@ -206,11 +175,12 @@ namespace JSC { virtual bool isNumber() const JSC_FAST_CALL { return false; } virtual bool isString() const JSC_FAST_CALL { return false; } virtual bool isNull() const JSC_FAST_CALL { return false; } - virtual bool isPure(CodeGenerator&) const JSC_FAST_CALL { return false; } + virtual bool isPure(BytecodeGenerator&) const JSC_FAST_CALL { return false; } virtual bool isLocation() const JSC_FAST_CALL { return false; } virtual bool isResolveNode() const JSC_FAST_CALL { return false; } virtual bool isBracketAccessorNode() const JSC_FAST_CALL { return false; } virtual bool isDotAccessorNode() const JSC_FAST_CALL { return false; } + virtual bool isFuncExprNode() const JSC_FAST_CALL { return false; } virtual ExpressionNode* stripUnaryPlus() { return this; } @@ -230,8 +200,9 @@ namespace JSC { int firstLine() const JSC_FAST_CALL { return lineNo(); } int lastLine() const JSC_FAST_CALL { return m_lastLine; } - virtual Precedence precedence() const { ASSERT_NOT_REACHED(); return PrecExpression; } virtual bool isEmptyStatement() const JSC_FAST_CALL { return false; } + virtual bool isReturnNode() const JSC_FAST_CALL { return false; } + virtual bool isExprStatement() const JSC_FAST_CALL { return false; } virtual bool isBlock() const JSC_FAST_CALL { return false; } virtual bool isLoop() const JSC_FAST_CALL { return false; } @@ -249,82 +220,57 @@ namespace JSC { virtual bool isNull() const JSC_FAST_CALL { return true; } - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { return PrecPrimary; } + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; }; class BooleanNode : public ExpressionNode { public: BooleanNode(JSGlobalData* globalData, bool value) JSC_FAST_CALL - : ExpressionNode(globalData, ResultType::boolean()) + : ExpressionNode(globalData, ResultType::booleanType()) , m_value(value) { } - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - virtual bool isPure(CodeGenerator&) const JSC_FAST_CALL { return true; } - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { return PrecPrimary; } + virtual bool isPure(BytecodeGenerator&) const JSC_FAST_CALL { return true; } - protected: + private: bool m_value; }; class NumberNode : public ExpressionNode { public: NumberNode(JSGlobalData* globalData, double v) JSC_FAST_CALL - : ExpressionNode(globalData, ResultType::constNumber()) + : ExpressionNode(globalData, ResultType::numberType()) , m_double(v) { } - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { return signbit(m_double) ? PrecUnary : PrecPrimary; } + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; virtual bool isNumber() const JSC_FAST_CALL { return true; } - virtual bool isPure(CodeGenerator&) const JSC_FAST_CALL { return true; } + virtual bool isPure(BytecodeGenerator&) const JSC_FAST_CALL { return true; } double value() const JSC_FAST_CALL { return m_double; } - virtual void setValue(double d) JSC_FAST_CALL { m_double = d; } - - protected: - double m_double; - }; - - class ImmediateNumberNode : public NumberNode { - public: - ImmediateNumberNode(JSGlobalData* globalData, JSValue* v, double d) JSC_FAST_CALL - : NumberNode(globalData, d) - , m_value(v) - { - ASSERT(v == JSImmediate::from(d)); - } - - virtual void setValue(double d) JSC_FAST_CALL { m_double = d; m_value = JSImmediate::from(d); ASSERT(m_value); } + void setValue(double d) JSC_FAST_CALL { m_double = d; } private: - JSValue* m_value; // This is never a JSCell, only JSImmediate, thus no ProtectedPtr + double m_double; }; class StringNode : public ExpressionNode { public: StringNode(JSGlobalData* globalData, const Identifier& v) JSC_FAST_CALL - : ExpressionNode(globalData, ResultType::string()) + : ExpressionNode(globalData, ResultType::stringType()) , m_value(v) { } - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; virtual bool isString() const JSC_FAST_CALL { return true; } const Identifier& value() { return m_value; } - virtual bool isPure(CodeGenerator&) const JSC_FAST_CALL { return true; } - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { return PrecPrimary; } + virtual bool isPure(BytecodeGenerator&) const JSC_FAST_CALL { return true; } private: Identifier m_value; @@ -358,8 +304,10 @@ namespace JSC { uint16_t endOffset() const { return m_endOffset; } protected: - RegisterID* emitThrowError(CodeGenerator&, ErrorType, const char* msg); - RegisterID* emitThrowError(CodeGenerator&, ErrorType, const char* msg, const Identifier&); + RegisterID* emitThrowError(BytecodeGenerator&, ErrorType, const char* msg); + RegisterID* emitThrowError(BytecodeGenerator&, ErrorType, const char* msg, const Identifier&); + + private: uint32_t m_divot; uint16_t m_startOffset; uint16_t m_endOffset; @@ -381,11 +329,12 @@ namespace JSC { { } - void setSubexpressionInfo(uint32_t subexpressionDivot, uint16_t subexpressionOffset) { - ASSERT(subexpressionDivot <= m_divot); - if ((m_divot - subexpressionDivot) & ~0xFFFF) // Overflow means we can't do this safely, so just point at the primary divot + void setSubexpressionInfo(uint32_t subexpressionDivot, uint16_t subexpressionOffset) + { + ASSERT(subexpressionDivot <= divot()); + if ((divot() - subexpressionDivot) & ~0xFFFF) // Overflow means we can't do this safely, so just point at the primary divot return; - m_subexpressionDivotOffset = m_divot - subexpressionDivot; + m_subexpressionDivotOffset = divot() - subexpressionDivot; m_subexpressionEndOffset = subexpressionOffset; } @@ -410,11 +359,12 @@ namespace JSC { { } - void setSubexpressionInfo(uint32_t subexpressionDivot, uint16_t subexpressionOffset) { - ASSERT(subexpressionDivot >= m_divot); - if ((subexpressionDivot - m_divot) & ~0xFFFF) // Overflow means we can't do this safely, so just point at the primary divot + void setSubexpressionInfo(uint32_t subexpressionDivot, uint16_t subexpressionOffset) + { + ASSERT(subexpressionDivot >= divot()); + if ((subexpressionDivot - divot()) & ~0xFFFF) // Overflow means we can't do this safely, so just point at the primary divot return; - m_subexpressionDivotOffset = subexpressionDivot - m_divot; + m_subexpressionDivotOffset = subexpressionDivot - divot(); m_subexpressionStartOffset = subexpressionOffset; } @@ -432,10 +382,7 @@ namespace JSC { { } - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { return PrecPrimary; } + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; private: UString m_pattern; @@ -449,10 +396,7 @@ namespace JSC { { } - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { return PrecPrimary; } + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; }; class ResolveNode : public ExpressionNode { @@ -464,50 +408,45 @@ namespace JSC { { } - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { return PrecPrimary; } + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - virtual bool isPure(CodeGenerator&) const JSC_FAST_CALL; + virtual bool isPure(BytecodeGenerator&) const JSC_FAST_CALL; virtual bool isLocation() const JSC_FAST_CALL { return true; } virtual bool isResolveNode() const JSC_FAST_CALL { return true; } const Identifier& identifier() const JSC_FAST_CALL { return m_ident; } - protected: + private: Identifier m_ident; int32_t m_startOffset; - }; - class ElementNode : public Node { + class ElementNode : public ParserRefCounted { public: ElementNode(JSGlobalData* globalData, int elision, ExpressionNode* node) JSC_FAST_CALL - : Node(globalData) + : ParserRefCounted(globalData) , m_elision(elision) , m_node(node) { } ElementNode(JSGlobalData* globalData, ElementNode* l, int elision, ExpressionNode* node) JSC_FAST_CALL - : Node(globalData) + : ParserRefCounted(globalData) , m_elision(elision) , m_node(node) { l->m_next = this; } - virtual Precedence precedence() const { ASSERT_NOT_REACHED(); return PrecExpression; } - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; + virtual ~ElementNode(); + virtual void releaseNodes(NodeReleaser&); int elision() const { return m_elision; } ExpressionNode* value() { return m_node.get(); } ElementNode* next() { return m_next.get(); } - PassRefPtr<ElementNode> releaseNext() JSC_FAST_CALL { return m_next.release(); } private: - ListRefPtr<ElementNode> m_next; + RefPtr<ElementNode> m_next; int m_elision; RefPtr<ExpressionNode> m_node; }; @@ -537,10 +476,10 @@ namespace JSC { { } - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + virtual ~ArrayNode(); + virtual void releaseNodes(NodeReleaser&); - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { return PrecPrimary; } + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; private: RefPtr<ElementNode> m_element; @@ -548,20 +487,20 @@ namespace JSC { bool m_optional; }; - class PropertyNode : public Node { + class PropertyNode : public ParserRefCounted { public: enum Type { Constant, Getter, Setter }; PropertyNode(JSGlobalData* globalData, const Identifier& name, ExpressionNode* assign, Type type) JSC_FAST_CALL - : Node(globalData) + : ParserRefCounted(globalData) , m_name(name) , m_assign(assign) , m_type(type) { } - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { ASSERT_NOT_REACHED(); return PrecExpression; } + virtual ~PropertyNode(); + virtual void releaseNodes(NodeReleaser&); const Identifier& name() const { return m_name; } @@ -587,16 +526,14 @@ namespace JSC { list->m_next = this; } - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { ASSERT_NOT_REACHED(); return PrecExpression; } + virtual ~PropertyListNode(); + virtual void releaseNodes(NodeReleaser&); - PassRefPtr<PropertyListNode> releaseNext() JSC_FAST_CALL { return m_next.release(); } + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; private: - friend class ObjectLiteralNode; RefPtr<PropertyNode> m_node; - ListRefPtr<PropertyListNode> m_next; + RefPtr<PropertyListNode> m_next; }; class ObjectLiteralNode : public ExpressionNode { @@ -612,10 +549,10 @@ namespace JSC { { } - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { return PrecPrimary; } - virtual bool needsParensIfLeftmost() const { return true; } + virtual ~ObjectLiteralNode(); + virtual void releaseNodes(NodeReleaser&); + + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; private: RefPtr<PropertyListNode> m_list; @@ -631,10 +568,10 @@ namespace JSC { { } - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + virtual ~BracketAccessorNode(); + virtual void releaseNodes(NodeReleaser&); - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { return PrecMember; } + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; virtual bool isLocation() const JSC_FAST_CALL { return true; } virtual bool isBracketAccessorNode() const JSC_FAST_CALL { return true; } @@ -656,9 +593,10 @@ namespace JSC { { } - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { return PrecMember; } + virtual ~DotAccessorNode(); + virtual void releaseNodes(NodeReleaser&); + + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; virtual bool isLocation() const JSC_FAST_CALL { return true; } virtual bool isDotAccessorNode() const JSC_FAST_CALL { return true; } @@ -685,31 +623,30 @@ namespace JSC { listNode->m_next = this; } - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { ASSERT_NOT_REACHED(); return PrecExpression; } + virtual ~ArgumentListNode(); + virtual void releaseNodes(NodeReleaser&); - PassRefPtr<ArgumentListNode> releaseNext() JSC_FAST_CALL { return m_next.release(); } + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - ListRefPtr<ArgumentListNode> m_next; + RefPtr<ArgumentListNode> m_next; RefPtr<ExpressionNode> m_expr; }; - class ArgumentsNode : public Node { + class ArgumentsNode : public ParserRefCounted { public: ArgumentsNode(JSGlobalData* globalData) JSC_FAST_CALL - : Node(globalData) + : ParserRefCounted(globalData) { } ArgumentsNode(JSGlobalData* globalData, ArgumentListNode* listNode) JSC_FAST_CALL - : Node(globalData) + : ParserRefCounted(globalData) , m_listNode(listNode) { } - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { ASSERT_NOT_REACHED(); return PrecExpression; } + virtual ~ArgumentsNode(); + virtual void releaseNodes(NodeReleaser&); RefPtr<ArgumentListNode> m_listNode; }; @@ -729,10 +666,10 @@ namespace JSC { { } - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + virtual ~NewExprNode(); + virtual void releaseNodes(NodeReleaser&); - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { return PrecLeftHandSide; } + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; private: RefPtr<ExpressionNode> m_expr; @@ -748,9 +685,10 @@ namespace JSC { { } - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { return PrecCall; } + virtual ~EvalFunctionCallNode(); + virtual void releaseNodes(NodeReleaser&); + + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; private: RefPtr<ArgumentsNode> m_args; @@ -766,9 +704,10 @@ namespace JSC { { } - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { return PrecCall; } + virtual ~FunctionCallValueNode(); + virtual void releaseNodes(NodeReleaser&); + + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; private: RefPtr<ExpressionNode> m_expr; @@ -785,12 +724,12 @@ namespace JSC { { } - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + virtual ~FunctionCallResolveNode(); + virtual void releaseNodes(NodeReleaser&); - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { return PrecCall; } + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - protected: + private: Identifier m_ident; RefPtr<ArgumentsNode> m_args; size_t m_index; // Used by LocalVarFunctionCallNode. @@ -808,11 +747,12 @@ namespace JSC { { } - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { return PrecCall; } + virtual ~FunctionCallBracketNode(); + virtual void releaseNodes(NodeReleaser&); - protected: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + + private: RefPtr<ExpressionNode> m_base; RefPtr<ExpressionNode> m_subscript; RefPtr<ArgumentsNode> m_args; @@ -829,9 +769,10 @@ namespace JSC { { } - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { return PrecCall; } + virtual ~FunctionCallDotNode(); + virtual void releaseNodes(NodeReleaser&); + + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; private: RefPtr<ExpressionNode> m_base; @@ -842,7 +783,7 @@ namespace JSC { class PrePostResolveNode : public ExpressionNode, public ThrowableExpressionData { public: PrePostResolveNode(JSGlobalData* globalData, const Identifier& ident, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL - : ExpressionNode(globalData, ResultType::constNumber()) // could be reusable for pre? + : ExpressionNode(globalData, ResultType::numberType()) // could be reusable for pre? , ThrowableExpressionData(divot, startOffset, endOffset) , m_ident(ident) { @@ -860,11 +801,9 @@ namespace JSC { { } - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { return PrecPostfix; } + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - protected: + private: Operator m_operator; }; @@ -879,11 +818,12 @@ namespace JSC { { } - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { return PrecPostfix; } + virtual ~PostfixBracketNode(); + virtual void releaseNodes(NodeReleaser&); - protected: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + + private: RefPtr<ExpressionNode> m_base; RefPtr<ExpressionNode> m_subscript; Operator m_operator; @@ -900,11 +840,12 @@ namespace JSC { { } - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { return PrecPostfix; } + virtual ~PostfixDotNode(); + virtual void releaseNodes(NodeReleaser&); - protected: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + + private: RefPtr<ExpressionNode> m_base; Identifier m_ident; Operator m_operator; @@ -920,9 +861,10 @@ namespace JSC { { } - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { return PrecPostfix; } + virtual ~PostfixErrorNode(); + virtual void releaseNodes(NodeReleaser&); + + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; private: RefPtr<ExpressionNode> m_expr; @@ -938,10 +880,7 @@ namespace JSC { { } - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { return PrecUnary; } + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; private: Identifier m_ident; @@ -957,10 +896,10 @@ namespace JSC { { } - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + virtual ~DeleteBracketNode(); + virtual void releaseNodes(NodeReleaser&); - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { return PrecUnary; } + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; private: RefPtr<ExpressionNode> m_base; @@ -977,10 +916,10 @@ namespace JSC { { } - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + virtual ~DeleteDotNode(); + virtual void releaseNodes(NodeReleaser&); - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { return PrecUnary; } + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; private: RefPtr<ExpressionNode> m_base; @@ -995,10 +934,10 @@ namespace JSC { { } - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + virtual ~DeleteValueNode(); + virtual void releaseNodes(NodeReleaser&); - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { return PrecUnary; } + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; private: RefPtr<ExpressionNode> m_expr; @@ -1012,10 +951,10 @@ namespace JSC { { } - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + virtual ~VoidNode(); + virtual void releaseNodes(NodeReleaser&); - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { return PrecUnary; } + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; private: RefPtr<ExpressionNode> m_expr; @@ -1024,35 +963,31 @@ namespace JSC { class TypeOfResolveNode : public ExpressionNode { public: TypeOfResolveNode(JSGlobalData* globalData, const Identifier& ident) JSC_FAST_CALL - : ExpressionNode(globalData, ResultType::string()) + : ExpressionNode(globalData, ResultType::stringType()) , m_ident(ident) { } - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { return PrecUnary; } + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; const Identifier& identifier() const JSC_FAST_CALL { return m_ident; } - protected: + private: Identifier m_ident; - size_t m_index; // Used by LocalTypeOfNode. }; class TypeOfValueNode : public ExpressionNode { public: TypeOfValueNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL - : ExpressionNode(globalData, ResultType::string()) + : ExpressionNode(globalData, ResultType::stringType()) , m_expr(expr) { } - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + virtual ~TypeOfValueNode(); + virtual void releaseNodes(NodeReleaser&); - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { return PrecUnary; } + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; private: RefPtr<ExpressionNode> m_expr; @@ -1066,12 +1001,9 @@ namespace JSC { { } - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { return PrecUnary; } + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - protected: + private: Operator m_operator; }; @@ -1086,11 +1018,12 @@ namespace JSC { { } - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { return PrecUnary; } + virtual ~PrefixBracketNode(); + virtual void releaseNodes(NodeReleaser&); - protected: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + + private: RefPtr<ExpressionNode> m_base; RefPtr<ExpressionNode> m_subscript; Operator m_operator; @@ -1107,11 +1040,12 @@ namespace JSC { { } - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { return PrecPostfix; } + virtual ~PrefixDotNode(); + virtual void releaseNodes(NodeReleaser&); - protected: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + + private: RefPtr<ExpressionNode> m_base; Identifier m_ident; Operator m_operator; @@ -1127,9 +1061,10 @@ namespace JSC { { } - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { return PrecUnary; } + virtual ~PrefixErrorNode(); + virtual void releaseNodes(NodeReleaser&); + + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; private: RefPtr<ExpressionNode> m_expr; @@ -1150,8 +1085,11 @@ namespace JSC { { } - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - virtual OpcodeID opcode() const JSC_FAST_CALL = 0; + virtual ~UnaryOpNode(); + virtual void releaseNodes(NodeReleaser&); + + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + virtual OpcodeID opcodeID() const JSC_FAST_CALL = 0; protected: RefPtr<ExpressionNode> m_expr; @@ -1160,51 +1098,43 @@ namespace JSC { class UnaryPlusNode : public UnaryOpNode { public: UnaryPlusNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL - : UnaryOpNode(globalData, ResultType::constNumber(), expr) + : UnaryOpNode(globalData, ResultType::numberType(), expr) { } virtual ExpressionNode* stripUnaryPlus() { return m_expr.get(); } - virtual OpcodeID opcode() const JSC_FAST_CALL { return op_to_jsnumber; } - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { return PrecUnary; } + virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_to_jsnumber; } }; class NegateNode : public UnaryOpNode { public: NegateNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL - : UnaryOpNode(globalData, ResultType::reusableNumber(), expr) + : UnaryOpNode(globalData, ResultType::numberTypeCanReuse(), expr) { } - virtual OpcodeID opcode() const JSC_FAST_CALL { return op_negate; } - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { return PrecUnary; } + virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_negate; } }; class BitwiseNotNode : public UnaryOpNode { public: BitwiseNotNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL - : UnaryOpNode(globalData, ResultType::reusableNumber(), expr) + : UnaryOpNode(globalData, ResultType::forBitOp(), expr) { } - virtual OpcodeID opcode() const JSC_FAST_CALL { return op_bitnot; } - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { return PrecUnary; } + virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_bitnot; } }; class LogicalNotNode : public UnaryOpNode { public: LogicalNotNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL - : UnaryOpNode(globalData, ResultType::boolean(), expr) + : UnaryOpNode(globalData, ResultType::booleanType(), expr) { } - virtual OpcodeID opcode() const JSC_FAST_CALL { return op_not; } - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { return PrecUnary; } + virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_not; } }; class BinaryOpNode : public ExpressionNode { @@ -1225,8 +1155,11 @@ namespace JSC { { } - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - virtual OpcodeID opcode() const JSC_FAST_CALL = 0; + virtual ~BinaryOpNode(); + virtual void releaseNodes(NodeReleaser&); + + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + virtual OpcodeID opcodeID() const JSC_FAST_CALL = 0; protected: RefPtr<ExpressionNode> m_expr1; @@ -1234,67 +1167,49 @@ namespace JSC { bool m_rightHasAssignments; }; - class ReverseBinaryOpNode : public ExpressionNode { + class ReverseBinaryOpNode : public BinaryOpNode { public: ReverseBinaryOpNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) - : ExpressionNode(globalData) - , m_expr1(expr1) - , m_expr2(expr2) - , m_rightHasAssignments(rightHasAssignments) + : BinaryOpNode(globalData, expr1, expr2, rightHasAssignments) { } ReverseBinaryOpNode(JSGlobalData* globalData, ResultType type, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) - : ExpressionNode(globalData, type) - , m_expr1(expr1) - , m_expr2(expr2) - , m_rightHasAssignments(rightHasAssignments) + : BinaryOpNode(globalData, type, expr1, expr2, rightHasAssignments) { } - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - virtual OpcodeID opcode() const JSC_FAST_CALL = 0; - - protected: - RefPtr<ExpressionNode> m_expr1; - RefPtr<ExpressionNode> m_expr2; - bool m_rightHasAssignments; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; }; class MultNode : public BinaryOpNode { public: MultNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL - : BinaryOpNode(globalData, ResultType::reusableNumber(), expr1, expr2, rightHasAssignments) + : BinaryOpNode(globalData, ResultType::numberTypeCanReuse(), expr1, expr2, rightHasAssignments) { } - virtual OpcodeID opcode() const JSC_FAST_CALL { return op_mul; } - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { return PrecMultiplicative; } + virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_mul; } }; class DivNode : public BinaryOpNode { public: DivNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL - : BinaryOpNode(globalData, ResultType::reusableNumber(), expr1, expr2, rightHasAssignments) + : BinaryOpNode(globalData, ResultType::numberTypeCanReuse(), expr1, expr2, rightHasAssignments) { } - virtual OpcodeID opcode() const JSC_FAST_CALL { return op_div; } - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { return PrecMultiplicative; } + virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_div; } }; class ModNode : public BinaryOpNode { public: ModNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL - : BinaryOpNode(globalData, ResultType::reusableNumber(), expr1, expr2, rightHasAssignments) + : BinaryOpNode(globalData, ResultType::numberTypeCanReuse(), expr1, expr2, rightHasAssignments) { } - virtual OpcodeID opcode() const JSC_FAST_CALL { return op_mod; } - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { return PrecMultiplicative; } + virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_mod; } }; class AddNode : public BinaryOpNode { @@ -1304,105 +1219,87 @@ namespace JSC { { } - virtual OpcodeID opcode() const JSC_FAST_CALL { return op_add; } - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { return PrecAdditive; } + virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_add; } }; class SubNode : public BinaryOpNode { public: SubNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL - : BinaryOpNode(globalData, ResultType::reusableNumber(), expr1, expr2, rightHasAssignments) + : BinaryOpNode(globalData, ResultType::numberTypeCanReuse(), expr1, expr2, rightHasAssignments) { } - virtual OpcodeID opcode() const JSC_FAST_CALL { return op_sub; } - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { return PrecAdditive; } + virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_sub; } }; class LeftShiftNode : public BinaryOpNode { public: LeftShiftNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL - : BinaryOpNode(globalData, ResultType::reusableNumber(), expr1, expr2, rightHasAssignments) + : BinaryOpNode(globalData, ResultType::forBitOp(), expr1, expr2, rightHasAssignments) { } - virtual OpcodeID opcode() const JSC_FAST_CALL { return op_lshift; } - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { return PrecShift; } + virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_lshift; } }; class RightShiftNode : public BinaryOpNode { public: RightShiftNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL - : BinaryOpNode(globalData, ResultType::reusableNumber(), expr1, expr2, rightHasAssignments) + : BinaryOpNode(globalData, ResultType::forBitOp(), expr1, expr2, rightHasAssignments) { } - virtual OpcodeID opcode() const JSC_FAST_CALL { return op_rshift; } - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { return PrecShift; } + virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_rshift; } }; class UnsignedRightShiftNode : public BinaryOpNode { public: UnsignedRightShiftNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL - : BinaryOpNode(globalData, ResultType::reusableNumber(), expr1, expr2, rightHasAssignments) + : BinaryOpNode(globalData, ResultType::numberTypeCanReuse(), expr1, expr2, rightHasAssignments) { } - virtual OpcodeID opcode() const JSC_FAST_CALL { return op_urshift; } - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { return PrecShift; } + virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_urshift; } }; class LessNode : public BinaryOpNode { public: LessNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL - : BinaryOpNode(globalData, ResultType::boolean(), expr1, expr2, rightHasAssignments) + : BinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, rightHasAssignments) { } - virtual OpcodeID opcode() const JSC_FAST_CALL { return op_less; } - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { return PrecRelational; } + virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_less; } }; class GreaterNode : public ReverseBinaryOpNode { public: GreaterNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL - : ReverseBinaryOpNode(globalData, ResultType::boolean(), expr1, expr2, rightHasAssignments) + : ReverseBinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, rightHasAssignments) { } - virtual OpcodeID opcode() const JSC_FAST_CALL { return op_less; } - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { return PrecRelational; } + virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_less; } }; class LessEqNode : public BinaryOpNode { public: LessEqNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL - : BinaryOpNode(globalData, ResultType::boolean(), expr1, expr2, rightHasAssignments) + : BinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, rightHasAssignments) { } - virtual OpcodeID opcode() const JSC_FAST_CALL { return op_lesseq; } - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { return PrecRelational; } + virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_lesseq; } }; class GreaterEqNode : public ReverseBinaryOpNode { public: GreaterEqNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL - : ReverseBinaryOpNode(globalData, ResultType::boolean(), expr1, expr2, rightHasAssignments) + : ReverseBinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, rightHasAssignments) { } - virtual OpcodeID opcode() const JSC_FAST_CALL { return op_lesseq; } - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { return PrecRelational; } + virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_lesseq; } }; class ThrowableBinaryOpNode : public BinaryOpNode, public ThrowableExpressionData { @@ -1415,21 +1312,19 @@ namespace JSC { : BinaryOpNode(globalData, expr1, expr2, rightHasAssignments) { } - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; }; class InstanceOfNode : public ThrowableBinaryOpNode { public: InstanceOfNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL - : ThrowableBinaryOpNode(globalData, ResultType::boolean(), expr1, expr2, rightHasAssignments) + : ThrowableBinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, rightHasAssignments) { } - virtual OpcodeID opcode() const JSC_FAST_CALL { return op_instanceof; } - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { return PrecRelational; } + virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_instanceof; } - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; }; class InNode : public ThrowableBinaryOpNode { @@ -1439,95 +1334,79 @@ namespace JSC { { } - virtual OpcodeID opcode() const JSC_FAST_CALL { return op_in; } - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { return PrecRelational; } + virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_in; } }; class EqualNode : public BinaryOpNode { public: EqualNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL - : BinaryOpNode(globalData, ResultType::boolean(), expr1, expr2, rightHasAssignments) + : BinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, rightHasAssignments) { } - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - virtual OpcodeID opcode() const JSC_FAST_CALL { return op_eq; } - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { return PrecEquality; } + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_eq; } }; class NotEqualNode : public BinaryOpNode { public: NotEqualNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL - : BinaryOpNode(globalData, ResultType::boolean(), expr1, expr2, rightHasAssignments) + : BinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, rightHasAssignments) { } - virtual OpcodeID opcode() const JSC_FAST_CALL { return op_neq; } - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { return PrecEquality; } + virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_neq; } }; class StrictEqualNode : public BinaryOpNode { public: StrictEqualNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL - : BinaryOpNode(globalData, ResultType::boolean(), expr1, expr2, rightHasAssignments) + : BinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, rightHasAssignments) { } - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - virtual OpcodeID opcode() const JSC_FAST_CALL { return op_stricteq; } - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { return PrecEquality; } + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_stricteq; } }; class NotStrictEqualNode : public BinaryOpNode { public: NotStrictEqualNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL - : BinaryOpNode(globalData, ResultType::boolean(), expr1, expr2, rightHasAssignments) + : BinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, rightHasAssignments) { } - virtual OpcodeID opcode() const JSC_FAST_CALL { return op_nstricteq; } - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { return PrecEquality; } + virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_nstricteq; } }; class BitAndNode : public BinaryOpNode { public: BitAndNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL - : BinaryOpNode(globalData, ResultType::reusableNumber(), expr1, expr2, rightHasAssignments) + : BinaryOpNode(globalData, ResultType::forBitOp(), expr1, expr2, rightHasAssignments) { } - virtual OpcodeID opcode() const JSC_FAST_CALL { return op_bitand; } - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { return PrecBitwiseAnd; } + virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_bitand; } }; class BitOrNode : public BinaryOpNode { public: BitOrNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL - : BinaryOpNode(globalData, ResultType::reusableNumber(), expr1, expr2, rightHasAssignments) + : BinaryOpNode(globalData, ResultType::forBitOp(), expr1, expr2, rightHasAssignments) { } - virtual OpcodeID opcode() const JSC_FAST_CALL { return op_bitor; } - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { return PrecBitwiseOr; } + virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_bitor; } }; class BitXOrNode : public BinaryOpNode { public: BitXOrNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL - : BinaryOpNode(globalData, ResultType::reusableNumber(), expr1, expr2, rightHasAssignments) + : BinaryOpNode(globalData, ResultType::forBitOp(), expr1, expr2, rightHasAssignments) { } - virtual OpcodeID opcode() const JSC_FAST_CALL { return op_bitxor; } - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { return PrecBitwiseXor; } + virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_bitxor; } }; /** @@ -1536,16 +1415,17 @@ namespace JSC { class LogicalOpNode : public ExpressionNode { public: LogicalOpNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, LogicalOperator oper) JSC_FAST_CALL - : ExpressionNode(globalData, ResultType::boolean()) + : ExpressionNode(globalData, ResultType::booleanType()) , m_expr1(expr1) , m_expr2(expr2) , m_operator(oper) { } - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { return (m_operator == OpLogicalAnd) ? PrecLogicalAnd : PrecLogicalOr; } + virtual ~LogicalOpNode(); + virtual void releaseNodes(NodeReleaser&); + + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; private: RefPtr<ExpressionNode> m_expr1; @@ -1566,9 +1446,10 @@ namespace JSC { { } - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { return PrecConditional; } + virtual ~ConditionalNode(); + virtual void releaseNodes(NodeReleaser&); + + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; private: RefPtr<ExpressionNode> m_logical; @@ -1588,12 +1469,12 @@ namespace JSC { { } - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + virtual ~ReadModifyResolveNode(); + virtual void releaseNodes(NodeReleaser&); - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { return PrecAssignment; } + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - protected: + private: Identifier m_ident; RefPtr<ExpressionNode> m_right; size_t m_index; // Used by ReadModifyLocalVarNode. @@ -1611,12 +1492,12 @@ namespace JSC { { } - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + virtual ~AssignResolveNode(); + virtual void releaseNodes(NodeReleaser&); - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { return PrecAssignment; } + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - protected: + private: Identifier m_ident; RefPtr<ExpressionNode> m_right; size_t m_index; // Used by ReadModifyLocalVarNode. @@ -1637,12 +1518,12 @@ namespace JSC { { } - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + virtual ~ReadModifyBracketNode(); + virtual void releaseNodes(NodeReleaser&); - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { return PrecAssignment; } + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - protected: + private: RefPtr<ExpressionNode> m_base; RefPtr<ExpressionNode> m_subscript; RefPtr<ExpressionNode> m_right; @@ -1664,12 +1545,12 @@ namespace JSC { { } - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + virtual ~AssignBracketNode(); + virtual void releaseNodes(NodeReleaser&); - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { return PrecAssignment; } + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - protected: + private: RefPtr<ExpressionNode> m_base; RefPtr<ExpressionNode> m_subscript; RefPtr<ExpressionNode> m_right; @@ -1689,11 +1570,12 @@ namespace JSC { { } - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { return PrecAssignment; } + virtual ~AssignDotNode(); + virtual void releaseNodes(NodeReleaser&); - protected: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + + private: RefPtr<ExpressionNode> m_base; Identifier m_ident; RefPtr<ExpressionNode> m_right; @@ -1713,12 +1595,12 @@ namespace JSC { { } - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + virtual ~ReadModifyDotNode(); + virtual void releaseNodes(NodeReleaser&); - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { return PrecAssignment; } + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - protected: + private: RefPtr<ExpressionNode> m_base; Identifier m_ident; RefPtr<ExpressionNode> m_right; @@ -1737,11 +1619,12 @@ namespace JSC { { } - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { return PrecAssignment; } + virtual ~AssignErrorNode(); + virtual void releaseNodes(NodeReleaser&); - protected: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + + private: RefPtr<ExpressionNode> m_left; Operator m_operator; RefPtr<ExpressionNode> m_right; @@ -1756,9 +1639,10 @@ namespace JSC { { } - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { return PrecExpression; } + virtual ~CommaNode(); + virtual void releaseNodes(NodeReleaser&); + + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; private: RefPtr<ExpressionNode> m_expr1; @@ -1771,23 +1655,21 @@ namespace JSC { : CommaNode(globalData, expr1, expr2) { } - virtual Precedence precedence() const { return PrecAssignment; } }; class ConstDeclNode : public ExpressionNode { public: ConstDeclNode(JSGlobalData* globalData, const Identifier& ident, ExpressionNode* in) JSC_FAST_CALL; - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { ASSERT_NOT_REACHED(); return PrecExpression; } - PassRefPtr<ConstDeclNode> releaseNext() JSC_FAST_CALL { return m_next.release(); } + virtual ~ConstDeclNode(); + virtual void releaseNodes(NodeReleaser&); Identifier m_ident; - ListRefPtr<ConstDeclNode> m_next; + RefPtr<ConstDeclNode> m_next; RefPtr<ExpressionNode> m_init; - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - virtual RegisterID* emitCodeSingle(CodeGenerator&) JSC_FAST_CALL; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + virtual RegisterID* emitCodeSingle(BytecodeGenerator&) JSC_FAST_CALL; }; class ConstStatementNode : public StatementNode { @@ -1798,9 +1680,10 @@ namespace JSC { { } - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + virtual ~ConstStatementNode(); + virtual void releaseNodes(NodeReleaser&); + + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; private: RefPtr<ConstDeclNode> m_next; @@ -1817,6 +1700,7 @@ namespace JSC { { ASSERT(destination.isEmpty()); m_statements.swap(destination); + destination.shrinkToFit(); } private: @@ -1827,13 +1711,16 @@ namespace JSC { public: BlockNode(JSGlobalData*, SourceElements* children) JSC_FAST_CALL; - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; + virtual ~BlockNode(); + virtual void releaseNodes(NodeReleaser&); + + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; StatementVector& children() { return m_children; } virtual bool isBlock() const JSC_FAST_CALL { return true; } - protected: + + private: StatementVector m_children; }; @@ -1844,9 +1731,8 @@ namespace JSC { { } - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; virtual bool isEmptyStatement() const JSC_FAST_CALL { return true; } }; @@ -1857,9 +1743,7 @@ namespace JSC { { } - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; }; class ExprStatementNode : public StatementNode { @@ -1870,8 +1754,11 @@ namespace JSC { { } - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; + virtual bool isExprStatement() const JSC_FAST_CALL { return true; } + + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + + ExpressionNode* expr() const { return m_expr.get(); } private: RefPtr<ExpressionNode> m_expr; @@ -1885,9 +1772,10 @@ namespace JSC { { } - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + virtual ~VarStatementNode(); + virtual void releaseNodes(NodeReleaser&); - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; private: RefPtr<ExpressionNode> m_expr; @@ -1902,8 +1790,10 @@ namespace JSC { { } - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; + virtual ~IfNode(); + virtual void releaseNodes(NodeReleaser&); + + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; protected: RefPtr<ExpressionNode> m_condition; @@ -1918,8 +1808,10 @@ namespace JSC { { } - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; + virtual ~IfElseNode(); + virtual void releaseNodes(NodeReleaser&); + + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; private: RefPtr<StatementNode> m_elseBlock; @@ -1934,10 +1826,13 @@ namespace JSC { { } - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; + virtual ~DoWhileNode(); + virtual void releaseNodes(NodeReleaser&); + + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; virtual bool isLoop() const JSC_FAST_CALL { return true; } + private: RefPtr<StatementNode> m_statement; RefPtr<ExpressionNode> m_expr; @@ -1952,10 +1847,13 @@ namespace JSC { { } - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; + virtual ~WhileNode(); + virtual void releaseNodes(NodeReleaser&); + + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; virtual bool isLoop() const JSC_FAST_CALL { return true; } + private: RefPtr<ExpressionNode> m_expr; RefPtr<StatementNode> m_statement; @@ -1974,10 +1872,13 @@ namespace JSC { ASSERT(statement); } - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; + virtual ~ForNode(); + virtual void releaseNodes(NodeReleaser&); + + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; virtual bool isLoop() const JSC_FAST_CALL { return true; } + private: RefPtr<ExpressionNode> m_expr1; RefPtr<ExpressionNode> m_expr2; @@ -1991,10 +1892,13 @@ namespace JSC { ForInNode(JSGlobalData*, ExpressionNode*, ExpressionNode*, StatementNode*) JSC_FAST_CALL; ForInNode(JSGlobalData*, const Identifier&, ExpressionNode*, ExpressionNode*, StatementNode*, int divot, int startOffset, int endOffset) JSC_FAST_CALL; - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; + virtual ~ForInNode(); + virtual void releaseNodes(NodeReleaser&); + + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; virtual bool isLoop() const JSC_FAST_CALL { return true; } + private: Identifier m_ident; RefPtr<ExpressionNode> m_init; @@ -2017,8 +1921,7 @@ namespace JSC { { } - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; private: Identifier m_ident; @@ -2037,8 +1940,7 @@ namespace JSC { { } - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; private: Identifier m_ident; @@ -2052,8 +1954,10 @@ namespace JSC { { } - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; + virtual ~ReturnNode(); + virtual void releaseNodes(NodeReleaser&); + + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; virtual bool isReturnNode() const JSC_FAST_CALL { return true; } private: @@ -2071,8 +1975,10 @@ namespace JSC { { } - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; + virtual ~WithNode(); + virtual void releaseNodes(NodeReleaser&); + + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; private: RefPtr<ExpressionNode> m_expr; @@ -2090,8 +1996,10 @@ namespace JSC { { } - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; + virtual ~LabelNode(); + virtual void releaseNodes(NodeReleaser&); + + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; private: Identifier m_name; @@ -2106,8 +2014,10 @@ namespace JSC { { } - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; + virtual ~ThrowNode(); + virtual void releaseNodes(NodeReleaser&); + + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; private: RefPtr<ExpressionNode> m_expr; @@ -2115,111 +2025,136 @@ namespace JSC { class TryNode : public StatementNode { public: - TryNode(JSGlobalData* globalData, StatementNode* tryBlock, const Identifier& exceptionIdent, StatementNode* catchBlock, StatementNode* finallyBlock) JSC_FAST_CALL + TryNode(JSGlobalData* globalData, StatementNode* tryBlock, const Identifier& exceptionIdent, bool catchHasEval, StatementNode* catchBlock, StatementNode* finallyBlock) JSC_FAST_CALL : StatementNode(globalData) , m_tryBlock(tryBlock) , m_exceptionIdent(exceptionIdent) , m_catchBlock(catchBlock) , m_finallyBlock(finallyBlock) + , m_catchHasEval(catchHasEval) { } - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; + virtual ~TryNode(); + virtual void releaseNodes(NodeReleaser&); - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* dst = 0) JSC_FAST_CALL; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* dst = 0) JSC_FAST_CALL; private: RefPtr<StatementNode> m_tryBlock; Identifier m_exceptionIdent; RefPtr<StatementNode> m_catchBlock; RefPtr<StatementNode> m_finallyBlock; + bool m_catchHasEval; }; - class ParameterNode : public Node { + class ParameterNode : public ParserRefCounted { public: ParameterNode(JSGlobalData* globalData, const Identifier& ident) JSC_FAST_CALL - : Node(globalData) + : ParserRefCounted(globalData) , m_ident(ident) { } ParameterNode(JSGlobalData* globalData, ParameterNode* l, const Identifier& ident) JSC_FAST_CALL - : Node(globalData) + : ParserRefCounted(globalData) , m_ident(ident) { l->m_next = this; } - Identifier ident() JSC_FAST_CALL { return m_ident; } - ParameterNode *nextParam() JSC_FAST_CALL { return m_next.get(); } - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - PassRefPtr<ParameterNode> releaseNext() JSC_FAST_CALL { return m_next.release(); } - virtual Precedence precedence() const { ASSERT_NOT_REACHED(); return PrecExpression; } + virtual ~ParameterNode(); + virtual void releaseNodes(NodeReleaser&); + + const Identifier& ident() const JSC_FAST_CALL { return m_ident; } + ParameterNode* nextParam() const JSC_FAST_CALL { return m_next.get(); } private: - friend class FuncDeclNode; - friend class FuncExprNode; Identifier m_ident; - ListRefPtr<ParameterNode> m_next; + RefPtr<ParameterNode> m_next; + }; + + struct ScopeNodeData { + typedef DeclarationStacks::VarStack VarStack; + typedef DeclarationStacks::FunctionStack FunctionStack; + + ScopeNodeData(SourceElements*, VarStack*, FunctionStack*, int numConstants); + + VarStack m_varStack; + FunctionStack m_functionStack; + int m_numConstants; + StatementVector m_children; + + void mark(); }; - class ScopeNode : public BlockNode { + class ScopeNode : public StatementNode { public: + typedef DeclarationStacks::VarStack VarStack; + typedef DeclarationStacks::FunctionStack FunctionStack; + + ScopeNode(JSGlobalData*) JSC_FAST_CALL; ScopeNode(JSGlobalData*, const SourceCode&, SourceElements*, VarStack*, FunctionStack*, CodeFeatures, int numConstants) JSC_FAST_CALL; + virtual ~ScopeNode(); + virtual void releaseNodes(NodeReleaser&); + + void adoptData(std::auto_ptr<ScopeNodeData> data) { m_data.adopt(data); } + ScopeNodeData* data() const { return m_data.get(); } + void destroyData() { m_data.clear(); } - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - const SourceCode& source() const { return m_source; } const UString& sourceURL() const JSC_FAST_CALL { return m_source.provider()->url(); } intptr_t sourceID() const { return m_source.provider()->asID(); } + void setFeatures(CodeFeatures features) { m_features = features; } + CodeFeatures features() { return m_features; } + bool usesEval() const { return m_features & EvalFeature; } bool usesArguments() const { return m_features & ArgumentsFeature; } void setUsesArguments() { m_features |= ArgumentsFeature; } bool usesThis() const { return m_features & ThisFeature; } bool needsActivation() const { return m_features & (EvalFeature | ClosureFeature | WithFeature | CatchFeature); } - VarStack& varStack() { return m_varStack; } - FunctionStack& functionStack() { return m_functionStack; } + VarStack& varStack() { ASSERT(m_data); return m_data->m_varStack; } + FunctionStack& functionStack() { ASSERT(m_data); return m_data->m_functionStack; } + + StatementVector& children() { ASSERT(m_data); return m_data->m_children; } int neededConstants() { - // We may need 1 more constant than the count given by the parser, - // because of the various uses of jsUndefined(). - return m_numConstants + 1; + ASSERT(m_data); + // We may need 2 more constants than the count given by the parser, + // because of the various uses of jsUndefined() and jsNull(). + return m_data->m_numConstants + 2; } + virtual void mark() { } + protected: void setSource(const SourceCode& source) { m_source = source; } - VarStack m_varStack; - FunctionStack m_functionStack; - private: - SourceCode m_source; + OwnPtr<ScopeNodeData> m_data; CodeFeatures m_features; - int m_numConstants; + SourceCode m_source; }; class ProgramNode : public ScopeNode { public: static ProgramNode* create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants) JSC_FAST_CALL; - ProgramCodeBlock& byteCode(ScopeChainNode* scopeChain) JSC_FAST_CALL + ProgramCodeBlock& bytecode(ScopeChainNode* scopeChain) JSC_FAST_CALL { if (!m_code) - generateCode(scopeChain); + generateBytecode(scopeChain); return *m_code; } private: ProgramNode(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants) JSC_FAST_CALL; - void generateCode(ScopeChainNode*) JSC_FAST_CALL; - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - - Vector<size_t> m_varIndexes; // Storage indexes belonging to the nodes in m_varStack. (Recorded to avoid double lookup.) - Vector<size_t> m_functionIndexes; // Storage indexes belonging to the nodes in m_functionStack. (Recorded to avoid double lookup.) + void generateBytecode(ScopeChainNode*) JSC_FAST_CALL; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; OwnPtr<ProgramCodeBlock> m_code; }; @@ -2228,46 +2163,49 @@ namespace JSC { public: static EvalNode* create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants) JSC_FAST_CALL; - EvalCodeBlock& byteCode(ScopeChainNode* scopeChain) JSC_FAST_CALL + EvalCodeBlock& bytecode(ScopeChainNode* scopeChain) JSC_FAST_CALL { if (!m_code) - generateCode(scopeChain); + generateBytecode(scopeChain); return *m_code; } + EvalCodeBlock& bytecodeForExceptionInfoReparse(ScopeChainNode*, CodeBlock*) JSC_FAST_CALL; + + virtual void mark(); + private: EvalNode(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants) JSC_FAST_CALL; - void generateCode(ScopeChainNode*) JSC_FAST_CALL; - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + void generateBytecode(ScopeChainNode*) JSC_FAST_CALL; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; OwnPtr<EvalCodeBlock> m_code; }; class FunctionBodyNode : public ScopeNode { + friend class JIT; public: + static FunctionBodyNode* create(JSGlobalData*) JSC_FAST_CALL; static FunctionBodyNode* create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants) JSC_FAST_CALL; - static FunctionBodyNode* create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, CodeFeatures, int numConstants) JSC_FAST_CALL; - ~FunctionBodyNode(); + virtual ~FunctionBodyNode(); const Identifier* parameters() const JSC_FAST_CALL { return m_parameters; } size_t parameterCount() const { return m_parameterCount; } UString paramString() const JSC_FAST_CALL; Identifier* copyParameters(); - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - - SymbolTable& symbolTable() { return m_symbolTable; } // FIXME: Remove this + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - CodeBlock& byteCode(ScopeChainNode* scopeChain) JSC_FAST_CALL + CodeBlock& bytecode(ScopeChainNode* scopeChain) JSC_FAST_CALL { ASSERT(scopeChain); if (!m_code) - generateCode(scopeChain); + generateBytecode(scopeChain); return *m_code; } - CodeBlock& generatedByteCode() JSC_FAST_CALL + CodeBlock& generatedBytecode() JSC_FAST_CALL { ASSERT(m_code); return *m_code; @@ -2278,12 +2216,12 @@ namespace JSC { return m_code; } - void mark(); + virtual void mark(); void finishParsing(const SourceCode&, ParameterNode*); void finishParsing(Identifier* parameters, size_t parameterCount); - UString toSourceString() const JSC_FAST_CALL { return UString("{") + source().toString() + UString("}"); } + UString toSourceString() const JSC_FAST_CALL { return source().toString(); } // These objects are ref/deref'd a lot in the scope chain, so this is a faster ref/deref. // If the virtual machine changes so this doesn't happen as much we can change back. @@ -2299,15 +2237,16 @@ namespace JSC { ScopeNode::deref(); } - protected: - FunctionBodyNode(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants) JSC_FAST_CALL; + CodeBlock& bytecodeForExceptionInfoReparse(ScopeChainNode*, CodeBlock*) JSC_FAST_CALL; private: - void generateCode(ScopeChainNode*) JSC_FAST_CALL; + FunctionBodyNode(JSGlobalData*) JSC_FAST_CALL; + FunctionBodyNode(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants) JSC_FAST_CALL; + + void generateBytecode(ScopeChainNode*) JSC_FAST_CALL; Identifier* m_parameters; size_t m_parameterCount; - SymbolTable m_symbolTable; OwnPtr<CodeBlock> m_code; unsigned m_refCount; }; @@ -2323,17 +2262,17 @@ namespace JSC { m_body->finishParsing(source, m_parameter.get()); } - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + virtual ~FuncExprNode(); + virtual void releaseNodes(NodeReleaser&); + + virtual bool isFuncExprNode() const JSC_FAST_CALL { return true; } + + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; JSFunction* makeFunction(ExecState*, ScopeChainNode*) JSC_FAST_CALL; - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { return PrecMember; } - virtual bool needsParensIfLeftmost() const { return true; } FunctionBodyNode* body() { return m_body.get(); } private: - // Used for streamTo - friend class PropertyNode; Identifier m_ident; RefPtr<ParameterNode> m_parameter; RefPtr<FunctionBodyNode> m_body; @@ -2350,9 +2289,11 @@ namespace JSC { m_body->finishParsing(source, m_parameter.get()); } - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + virtual ~FuncDeclNode(); + virtual void releaseNodes(NodeReleaser&); + + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; JSFunction* makeFunction(ExecState*, ScopeChainNode*) JSC_FAST_CALL; Identifier m_ident; @@ -2364,24 +2305,24 @@ namespace JSC { RefPtr<FunctionBodyNode> m_body; }; - class CaseClauseNode : public Node { + class CaseClauseNode : public ParserRefCounted { public: CaseClauseNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL - : Node(globalData) + : ParserRefCounted(globalData) , m_expr(expr) { } CaseClauseNode(JSGlobalData* globalData, ExpressionNode* expr, SourceElements* children) JSC_FAST_CALL - : Node(globalData) + : ParserRefCounted(globalData) , m_expr(expr) { if (children) children->releaseContentsIntoVector(m_children); } - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { ASSERT_NOT_REACHED(); return PrecExpression; } + virtual ~CaseClauseNode(); + virtual void releaseNodes(NodeReleaser&); ExpressionNode* expr() const { return m_expr.get(); } StatementVector& children() { return m_children; } @@ -2391,47 +2332,46 @@ namespace JSC { StatementVector m_children; }; - class ClauseListNode : public Node { + class ClauseListNode : public ParserRefCounted { public: ClauseListNode(JSGlobalData* globalData, CaseClauseNode* clause) JSC_FAST_CALL - : Node(globalData) + : ParserRefCounted(globalData) , m_clause(clause) { } ClauseListNode(JSGlobalData* globalData, ClauseListNode* clauseList, CaseClauseNode* clause) JSC_FAST_CALL - : Node(globalData) + : ParserRefCounted(globalData) , m_clause(clause) { clauseList->m_next = this; } + virtual ~ClauseListNode(); + virtual void releaseNodes(NodeReleaser&); + CaseClauseNode* getClause() const JSC_FAST_CALL { return m_clause.get(); } ClauseListNode* getNext() const JSC_FAST_CALL { return m_next.get(); } - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - PassRefPtr<ClauseListNode> releaseNext() JSC_FAST_CALL { return m_next.release(); } - virtual Precedence precedence() const { ASSERT_NOT_REACHED(); return PrecExpression; } private: - friend class CaseBlockNode; RefPtr<CaseClauseNode> m_clause; - ListRefPtr<ClauseListNode> m_next; + RefPtr<ClauseListNode> m_next; }; - class CaseBlockNode : public Node { + class CaseBlockNode : public ParserRefCounted { public: CaseBlockNode(JSGlobalData* globalData, ClauseListNode* list1, CaseClauseNode* defaultClause, ClauseListNode* list2) JSC_FAST_CALL - : Node(globalData) + : ParserRefCounted(globalData) , m_list1(list1) , m_defaultClause(defaultClause) , m_list2(list2) { } - RegisterID* emitCodeForBlock(CodeGenerator&, RegisterID* input, RegisterID* dst = 0) JSC_FAST_CALL; + virtual ~CaseBlockNode(); + virtual void releaseNodes(NodeReleaser&); - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; - virtual Precedence precedence() const { ASSERT_NOT_REACHED(); return PrecExpression; } + RegisterID* emitBytecodeForBlock(BytecodeGenerator&, RegisterID* input, RegisterID* dst = 0) JSC_FAST_CALL; private: SwitchInfo::SwitchType tryOptimizedSwitch(Vector<ExpressionNode*, 8>& literalVector, int32_t& min_num, int32_t& max_num); @@ -2449,9 +2389,10 @@ namespace JSC { { } - virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + virtual ~SwitchNode(); + virtual void releaseNodes(NodeReleaser&); - virtual void streamTo(SourceStream&) const JSC_FAST_CALL; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; private: RefPtr<ExpressionNode> m_expr; diff --git a/JavaScriptCore/kjs/Parser.cpp b/JavaScriptCore/parser/Parser.cpp index 26773e8..886a513 100644 --- a/JavaScriptCore/kjs/Parser.cpp +++ b/JavaScriptCore/parser/Parser.cpp @@ -1,7 +1,7 @@ /* * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) * Copyright (C) 2001 Peter Kelly (pmk@post.com) - * Copyright (C) 2003, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2003, 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 @@ -24,11 +24,16 @@ #include "Parser.h" #include "Debugger.h" -#include "lexer.h" +#include "Lexer.h" #include <wtf/HashSet.h> #include <wtf/Vector.h> +#include <memory> -extern int kjsyyparse(void*); +using std::auto_ptr; + +#ifndef yyparse +extern int jscyyparse(void*); +#endif namespace JSC { @@ -50,7 +55,7 @@ void Parser::parse(JSGlobalData* globalData, int* errLine, UString* errMsg) Lexer& lexer = *globalData->lexer; lexer.setCode(*m_source); - int parseError = kjsyyparse(globalData); + int parseError = jscyyparse(globalData); bool lexError = lexer.sawError(); lexer.clear(); @@ -63,6 +68,30 @@ void Parser::parse(JSGlobalData* globalData, int* errLine, UString* errMsg) } } +void Parser::reparseInPlace(JSGlobalData* globalData, FunctionBodyNode* functionBodyNode) +{ + ASSERT(!functionBodyNode->data()); + + m_source = &functionBodyNode->source(); + globalData->lexer->setIsReparsing(); + parse(globalData, 0, 0); + ASSERT(m_sourceElements); + + functionBodyNode->adoptData(std::auto_ptr<ScopeNodeData>(new ScopeNodeData(m_sourceElements.get(), + m_varDeclarations ? &m_varDeclarations->data : 0, + m_funcDeclarations ? &m_funcDeclarations->data : 0, + m_numConstants))); + bool usesArguments = functionBodyNode->usesArguments(); + functionBodyNode->setFeatures(m_features); + if (usesArguments && !functionBodyNode->usesArguments()) + functionBodyNode->setUsesArguments(); + + m_source = 0; + m_sourceElements = 0; + m_varDeclarations = 0; + m_funcDeclarations = 0; +} + void Parser::didFinishParsing(SourceElements* sourceElements, ParserRefCountedData<DeclarationStacks::VarStack>* varStack, ParserRefCountedData<DeclarationStacks::FunctionStack>* funcStack, CodeFeatures features, int lastLine, int numConstants) { diff --git a/JavaScriptCore/kjs/Parser.h b/JavaScriptCore/parser/Parser.h index c2f55d7..6191ccb 100644 --- a/JavaScriptCore/kjs/Parser.h +++ b/JavaScriptCore/parser/Parser.h @@ -1,7 +1,7 @@ /* * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) * Copyright (C) 2001 Peter Kelly (pmk@post.com) - * Copyright (C) 2003, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2003, 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 @@ -25,7 +25,7 @@ #include "SourceProvider.h" #include "Debugger.h" -#include "nodes.h" +#include "Nodes.h" #include <wtf/Forward.h> #include <wtf/Noncopyable.h> #include <wtf/OwnPtr.h> @@ -50,6 +50,8 @@ namespace JSC { class Parser : Noncopyable { public: template <class ParsedNode> PassRefPtr<ParsedNode> parse(ExecState*, Debugger*, const SourceCode&, int* errLine = 0, UString* errMsg = 0); + template <class ParsedNode> PassRefPtr<ParsedNode> reparse(JSGlobalData*, ParsedNode*); + void reparseInPlace(JSGlobalData*, FunctionBodyNode*); void didFinishParsing(SourceElements*, ParserRefCountedData<DeclarationStacks::VarStack>*, ParserRefCountedData<DeclarationStacks::FunctionStack>*, CodeFeatures features, int lastLine, int numConstants); @@ -92,6 +94,30 @@ namespace JSC { return result.release(); } + template <class ParsedNode> PassRefPtr<ParsedNode> Parser::reparse(JSGlobalData* globalData, ParsedNode* oldParsedNode) + { + m_source = &oldParsedNode->source(); + parse(globalData, 0, 0); + RefPtr<ParsedNode> result; + if (m_sourceElements) { + result = ParsedNode::create(globalData, + m_sourceElements.get(), + m_varDeclarations ? &m_varDeclarations->data : 0, + m_funcDeclarations ? &m_funcDeclarations->data : 0, + *m_source, + oldParsedNode->features(), + m_numConstants); + result->setLoc(m_source->firstLine(), m_lastLine); + } + + m_source = 0; + m_sourceElements = 0; + m_varDeclarations = 0; + m_funcDeclarations = 0; + + return result.release(); + } + } // namespace JSC #endif // Parser_h diff --git a/JavaScriptCore/kjs/ResultType.h b/JavaScriptCore/parser/ResultType.h index f838ce0..3e7fddb 100644 --- a/JavaScriptCore/kjs/ResultType.h +++ b/JavaScriptCore/parser/ResultType.h @@ -33,16 +33,16 @@ namespace JSC { typedef char Type; static const Type TypeReusable = 1; + static const Type TypeInt32 = 2; - static const Type TypeMaybeNumber = 2; - static const Type TypeMaybeString = 4; - static const Type TypeMaybeNull = 8; - static const Type TypeMaybeBool = 16; - static const Type TypeMaybeOther = 32; + static const Type TypeMaybeNumber = 0x04; + static const Type TypeMaybeString = 0x08; + static const Type TypeMaybeNull = 0x10; + static const Type TypeMaybeBool = 0x20; + static const Type TypeMaybeOther = 0x40; + + static const Type TypeBits = TypeMaybeNumber | TypeMaybeString | TypeMaybeNull | TypeMaybeBool | TypeMaybeOther; - static const Type TypeReusableNumber = 3; - static const Type TypeStringOrReusableNumber = 4; - explicit ResultType(Type type) : m_type(type) { @@ -50,76 +50,81 @@ namespace JSC { bool isReusable() { - return (m_type & TypeReusable); + return m_type & TypeReusable; } - - bool isReusableNumber() + + bool isInt32() { - return isReusable() && definitelyIsNumber(); + return m_type & TypeInt32; } bool definitelyIsNumber() { - return ((m_type & ~TypeReusable) == TypeMaybeNumber); - } - - bool isNotNumber() - { - return ((m_type & TypeMaybeNumber) == 0); + return (m_type & TypeBits) == TypeMaybeNumber; } bool mightBeNumber() { - return !isNotNumber(); + return m_type & TypeMaybeNumber; } - - int toInt() + + bool isNotNumber() { - return static_cast<int>(m_type); + return !mightBeNumber(); } - + static ResultType nullType() { return ResultType(TypeMaybeNull); } - static ResultType boolean() + static ResultType booleanType() { return ResultType(TypeMaybeBool); } - static ResultType constNumber() + static ResultType numberType() { return ResultType(TypeMaybeNumber); } - static ResultType reusableNumber() + static ResultType numberTypeCanReuse() { return ResultType(TypeReusable | TypeMaybeNumber); } - static ResultType reusableNumberOrString() + static ResultType numberTypeCanReuseIsInt32() + { + return ResultType(TypeReusable | TypeInt32 | TypeMaybeNumber); + } + + static ResultType stringOrNumberTypeCanReuse() { return ResultType(TypeReusable | TypeMaybeNumber | TypeMaybeString); } - static ResultType string() + static ResultType stringType() { return ResultType(TypeMaybeString); } - static ResultType unknown() + static ResultType unknownType() { - return ResultType(TypeMaybeNumber | TypeMaybeString | TypeMaybeNull | TypeMaybeBool | TypeMaybeOther); + return ResultType(TypeBits); } static ResultType forAdd(ResultType op1, ResultType op2) { if (op1.definitelyIsNumber() && op2.definitelyIsNumber()) - return reusableNumber(); + return numberTypeCanReuse(); if (op1.isNotNumber() || op2.isNotNumber()) - return string(); - return reusableNumberOrString(); + return stringType(); + return stringOrNumberTypeCanReuse(); + } + + static ResultType forBitOp() + { + return numberTypeCanReuseIsInt32(); } private: @@ -128,8 +133,11 @@ namespace JSC { struct OperandTypes { - OperandTypes(ResultType first = ResultType::unknown(), ResultType second = ResultType::unknown()) + OperandTypes(ResultType first = ResultType::unknownType(), ResultType second = ResultType::unknownType()) { + // We have to initialize one of the int to ensure that + // the entire struct is initialized. + m_u.i = 0; m_u.rds.first = first.m_type; m_u.rds.second = second.m_type; } diff --git a/JavaScriptCore/kjs/SourceCode.h b/JavaScriptCore/parser/SourceCode.h index 2840161..84360b8 100644 --- a/JavaScriptCore/kjs/SourceCode.h +++ b/JavaScriptCore/parser/SourceCode.h @@ -70,6 +70,7 @@ namespace JSC { SourceProvider* provider() const { return m_provider.get(); } int firstLine() const { return m_firstLine; } int startOffset() const { return m_startChar; } + int endOffset() const { return m_endChar; } const UChar* data() const { return m_provider->data() + m_startChar; } int length() const { return m_endChar - m_startChar; } diff --git a/JavaScriptCore/kjs/SourceProvider.h b/JavaScriptCore/parser/SourceProvider.h index 755a10f..07da9e0 100644 --- a/JavaScriptCore/kjs/SourceProvider.h +++ b/JavaScriptCore/parser/SourceProvider.h @@ -29,7 +29,7 @@ #ifndef SourceProvider_h #define SourceProvider_h -#include "ustring.h" +#include "UString.h" #include <wtf/RefCounted.h> namespace JSC { diff --git a/JavaScriptCore/pcre/dftables b/JavaScriptCore/pcre/dftables index 9268f19..de2f5bb 100755 --- a/JavaScriptCore/pcre/dftables +++ b/JavaScriptCore/pcre/dftables @@ -8,7 +8,7 @@ # # Originally written by Philip Hazel # Copyright (c) 1997-2006 University of Cambridge -# Copyright (C) 2002, 2004, 2006, 2007, 2008 Apple Inc. All rights reserved. +# Copyright (C) 2002, 2004, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. # # ----------------------------------------------------------------------------- # Redistribution and use in source and binary forms, with or without @@ -84,7 +84,7 @@ printf(OUT "This file contains the default tables for characters with codes less than\n" . "128 (ASCII characters). These tables are used when no external tables are\n" . "passed to PCRE. */\n\n" . - "const unsigned char kjs_pcre_default_tables[%d] = {\n\n" . + "const unsigned char jsc_pcre_default_tables[%d] = {\n\n" . "/* This table is a lower casing table. */\n\n", $pcre_internal{tables_length}); if ($pcre_internal{lcc_offset} != 0) { diff --git a/JavaScriptCore/pcre/pcre.pri b/JavaScriptCore/pcre/pcre.pri index ec5c0d5..c33c67c 100644 --- a/JavaScriptCore/pcre/pcre.pri +++ b/JavaScriptCore/pcre/pcre.pri @@ -1,6 +1,6 @@ # Perl Compatible Regular Expressions - Qt4 build info VPATH += $$PWD -INCLUDEPATH += $$PWD $$OUTPUT_DIR/JavaScriptCore/kjs/tmp +INCLUDEPATH += $$PWD $$OUTPUT_DIR/JavaScriptCore/tmp DEPENDPATH += $$PWD isEmpty(GENERATED_SOURCES_DIR):GENERATED_SOURCES_DIR = tmp diff --git a/JavaScriptCore/pcre/pcre_compile.cpp b/JavaScriptCore/pcre/pcre_compile.cpp index fdd90af..18c54ff 100644 --- a/JavaScriptCore/pcre/pcre_compile.cpp +++ b/JavaScriptCore/pcre/pcre_compile.cpp @@ -6,7 +6,7 @@ needed by JavaScriptCore and the rest of WebKit. Originally written by Philip Hazel Copyright (c) 1997-2006 University of Cambridge - Copyright (C) 2002, 2004, 2006, 2007 Apple Inc. All rights reserved. + Copyright (C) 2002, 2004, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. Copyright (C) 2007 Eric Seidel <eric@webkit.org> ----------------------------------------------------------------------------- @@ -236,8 +236,11 @@ static int checkEscape(const UChar** ptrPtr, const UChar* patternEnd, ErrorCode* /* Handle an octal number following \. If the first digit is 8 or 9, this is not octal. */ - if ((c = *ptr) >= '8') + if ((c = *ptr) >= '8') { + c = '\\'; + ptr -= 1; break; + } /* \0 always starts an octal number, but we may drop through to here with a larger first octal digit. */ @@ -298,8 +301,17 @@ static int checkEscape(const UChar** ptrPtr, const UChar* patternEnd, ErrorCode* *errorCodePtr = ERR2; return 0; } - c = *ptr; + c = *ptr; + + /* To match Firefox, inside a character class, we also accept + numbers and '_' as control characters */ + if ((!isClass && !isASCIIAlpha(c)) || (!isASCIIAlphanumeric(c) && c != '_')) { + c = '\\'; + ptr -= 2; + break; + } + /* A letter is upper-cased; then the 0x40 bit is flipped. This coding is ASCII-specific, but then the whole concept of \cx is ASCII-specific. */ c = toASCIIUpper(c) ^ 0x40; @@ -477,7 +489,7 @@ static bool getOthercaseRange(int* cptr, int d, int* ocptr, int* odptr) int c, othercase = 0; for (c = *cptr; c <= d; c++) { - if ((othercase = kjs_pcre_ucp_othercase(c)) >= 0) + if ((othercase = jsc_pcre_ucp_othercase(c)) >= 0) break; } @@ -488,7 +500,7 @@ static bool getOthercaseRange(int* cptr, int d, int* ocptr, int* odptr) int next = othercase + 1; for (++c; c <= d; c++) { - if (kjs_pcre_ucp_othercase(c) != next) + if (jsc_pcre_ucp_othercase(c) != next) break; next++; } @@ -516,15 +528,15 @@ static bool getOthercaseRange(int* cptr, int d, int* ocptr, int* odptr) static int encodeUTF8(int cvalue, unsigned char *buffer) { int i; - for (i = 0; i < kjs_pcre_utf8_table1_size; i++) - if (cvalue <= kjs_pcre_utf8_table1[i]) + for (i = 0; i < jsc_pcre_utf8_table1_size; i++) + if (cvalue <= jsc_pcre_utf8_table1[i]) break; buffer += i; for (int j = i; j > 0; j--) { *buffer-- = 0x80 | (cvalue & 0x3f); cvalue >>= 6; } - *buffer = kjs_pcre_utf8_table2[i] | cvalue; + *buffer = jsc_pcre_utf8_table2[i] | cvalue; return i + 1; } @@ -900,7 +912,7 @@ compileBranch(int options, int* brackets, unsigned char** codePtr, if (options & IgnoreCaseOption) { int othercase; - if ((othercase = kjs_pcre_ucp_othercase(c)) >= 0) { + if ((othercase = jsc_pcre_ucp_othercase(c)) >= 0) { *class_utf8data++ = XCL_SINGLE; class_utf8data += encodeUTF8(othercase, class_utf8data); } @@ -1402,6 +1414,15 @@ compileBranch(int options, int* brackets, unsigned char** codePtr, code[-ketoffset] = OP_KETRMAX + repeatType; } + // A quantifier after an assertion is mostly meaningless, but it + // can nullify the assertion if it has a 0 minimum. + else if (*previous == OP_ASSERT || *previous == OP_ASSERT_NOT) { + if (repeatMin == 0) { + code = previous; + goto END_REPEAT; + } + } + /* Else there's some kind of shambles */ else { @@ -1468,12 +1489,12 @@ compileBranch(int options, int* brackets, unsigned char** codePtr, bravalue = OP_BRA + *brackets; } - /* Process nested bracketed re. Assertions may not be repeated, but other - kinds can be. We copy code into a non-variable in order to be able - to pass its address because some compilers complain otherwise. Pass in a - new setting for the ims options if they have changed. */ + /* Process nested bracketed re. We copy code into a non-variable + in order to be able to pass its address because some compilers + complain otherwise. Pass in a new setting for the ims options + if they have changed. */ - previous = (bravalue >= OP_BRAZERO) ? code : 0; + previous = code; *code = bravalue; tempcode = code; tempreqvary = cd.reqVaryOpt; /* Save value before bracket */ @@ -2041,8 +2062,8 @@ static int calculateCompiledPatternLength(const UChar* pattern, int patternLengt if (c > 127) { int i; - for (i = 0; i < kjs_pcre_utf8_table1_size; i++) - if (c <= kjs_pcre_utf8_table1[i]) break; + for (i = 0; i < jsc_pcre_utf8_table1_size; i++) + if (c <= jsc_pcre_utf8_table1[i]) break; length += i; lastitemlength += i; } @@ -2495,8 +2516,8 @@ static int calculateCompiledPatternLength(const UChar* pattern, int patternLengt if (c > 127) { int i; - for (i = 0; i < kjs_pcre_utf8_table1_size; i++) - if (c <= kjs_pcre_utf8_table1[i]) + for (i = 0; i < jsc_pcre_utf8_table1_size; i++) + if (c <= jsc_pcre_utf8_table1[i]) break; length += i; lastitemlength += i; @@ -2586,7 +2607,7 @@ JSRegExp* jsRegExpCompile(const UChar* pattern, int patternLength, const UChar* ptr = (const UChar*)pattern; const UChar* patternEnd = pattern + patternLength; - unsigned char* code = (unsigned char*)codeStart; + unsigned char* code = const_cast<unsigned char*>(codeStart); int firstByte, reqByte; int bracketCount = 0; if (!cd.needOuterBracket) diff --git a/JavaScriptCore/pcre/pcre_exec.cpp b/JavaScriptCore/pcre/pcre_exec.cpp index 36d81e2..34e2786 100644 --- a/JavaScriptCore/pcre/pcre_exec.cpp +++ b/JavaScriptCore/pcre/pcre_exec.cpp @@ -6,7 +6,7 @@ needed by JavaScriptCore and the rest of WebKit. Originally written by Philip Hazel Copyright (c) 1997-2006 University of Cambridge - Copyright (C) 2002, 2004, 2006, 2007 Apple Inc. All rights reserved. + Copyright (C) 2002, 2004, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. Copyright (C) 2007 Eric Seidel <eric@webkit.org> ----------------------------------------------------------------------------- @@ -50,8 +50,8 @@ the JavaScript specification. There are also some supporting functions. */ #include <wtf/Vector.h> #if REGEXP_HISTOGRAM -#include <kjs/DateMath.h> -#include <kjs/ustring.h> +#include <parser/DateMath.h> +#include <runtime/UString.h> #endif using namespace WTF; @@ -250,7 +250,7 @@ static bool matchRef(int offset, const UChar* subjectPtr, int length, const Matc if (md.ignoreCase) { while (length-- > 0) { UChar c = *p++; - int othercase = kjs_pcre_ucp_othercase(c); + int othercase = jsc_pcre_ucp_othercase(c); UChar d = *subjectPtr++; if (c != d && othercase != d) return false; @@ -403,9 +403,9 @@ static inline void getUTF8CharAndIncrementLength(int& c, const unsigned char* su { c = *subjectPtr; if ((c & 0xc0) == 0xc0) { - int gcaa = kjs_pcre_utf8_table4[c & 0x3f]; /* Number of additional bytes */ + int gcaa = jsc_pcre_utf8_table4[c & 0x3f]; /* Number of additional bytes */ int gcss = 6 * gcaa; - c = (c & kjs_pcre_utf8_table3[gcaa]) << gcss; + c = (c & jsc_pcre_utf8_table3[gcaa]) << gcss; for (int gcii = 1; gcii <= gcaa; gcii++) { gcss -= 6; c |= (subjectPtr[gcii] & 0x3f) << gcss; @@ -1048,7 +1048,7 @@ RECURSE: if (stack.currentFrame->args.subjectPtr >= md.endSubject) RRETURN_NO_MATCH; int c = *stack.currentFrame->args.subjectPtr++; - if (!kjs_pcre_xclass(c, stack.currentFrame->locals.data)) + if (!jsc_pcre_xclass(c, stack.currentFrame->locals.data)) RRETURN_NO_MATCH; } @@ -1069,7 +1069,7 @@ RECURSE: if (stack.currentFrame->locals.fi >= stack.currentFrame->locals.max || stack.currentFrame->args.subjectPtr >= md.endSubject) RRETURN; int c = *stack.currentFrame->args.subjectPtr++; - if (!kjs_pcre_xclass(c, stack.currentFrame->locals.data)) + if (!jsc_pcre_xclass(c, stack.currentFrame->locals.data)) RRETURN; } /* Control never reaches here */ @@ -1083,7 +1083,7 @@ RECURSE: if (stack.currentFrame->args.subjectPtr >= md.endSubject) break; int c = *stack.currentFrame->args.subjectPtr; - if (!kjs_pcre_xclass(c, stack.currentFrame->locals.data)) + if (!jsc_pcre_xclass(c, stack.currentFrame->locals.data)) break; ++stack.currentFrame->args.subjectPtr; } @@ -1122,7 +1122,7 @@ RECURSE: if (stack.currentFrame->args.subjectPtr >= md.endSubject) RRETURN_NO_MATCH; int dc = *stack.currentFrame->args.subjectPtr++; - if (stack.currentFrame->locals.fc != dc && kjs_pcre_ucp_othercase(stack.currentFrame->locals.fc) != dc) + if (stack.currentFrame->locals.fc != dc && jsc_pcre_ucp_othercase(stack.currentFrame->locals.fc) != dc) RRETURN_NO_MATCH; NEXT_OPCODE; } @@ -1186,7 +1186,7 @@ RECURSE: stack.currentFrame->args.instructionPtr += stack.currentFrame->locals.length; if (stack.currentFrame->locals.fc <= 0xFFFF) { - int othercase = md.ignoreCase ? kjs_pcre_ucp_othercase(stack.currentFrame->locals.fc) : -1; + int othercase = md.ignoreCase ? jsc_pcre_ucp_othercase(stack.currentFrame->locals.fc) : -1; for (int i = 1; i <= min; i++) { if (*stack.currentFrame->args.subjectPtr != stack.currentFrame->locals.fc && *stack.currentFrame->args.subjectPtr != othercase) diff --git a/JavaScriptCore/pcre/pcre_internal.h b/JavaScriptCore/pcre/pcre_internal.h index 06c3e9d..2916765 100644 --- a/JavaScriptCore/pcre/pcre_internal.h +++ b/JavaScriptCore/pcre/pcre_internal.h @@ -6,7 +6,7 @@ needed by JavaScriptCore and the rest of WebKit. Originally written by Philip Hazel Copyright (c) 1997-2006 University of Cambridge - Copyright (C) 2002, 2004, 2006, 2007 Apple Inc. All rights reserved. + Copyright (C) 2002, 2004, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without @@ -340,36 +340,36 @@ struct JSRegExp { but are not part of the PCRE public API. The data for these tables is in the pcre_tables.c module. */ -#define kjs_pcre_utf8_table1_size 6 +#define jsc_pcre_utf8_table1_size 6 -extern const int kjs_pcre_utf8_table1[6]; -extern const int kjs_pcre_utf8_table2[6]; -extern const int kjs_pcre_utf8_table3[6]; -extern const unsigned char kjs_pcre_utf8_table4[0x40]; +extern const int jsc_pcre_utf8_table1[6]; +extern const int jsc_pcre_utf8_table2[6]; +extern const int jsc_pcre_utf8_table3[6]; +extern const unsigned char jsc_pcre_utf8_table4[0x40]; -extern const unsigned char kjs_pcre_default_tables[tables_length]; +extern const unsigned char jsc_pcre_default_tables[tables_length]; static inline unsigned char toLowerCase(unsigned char c) { - static const unsigned char* lowerCaseChars = kjs_pcre_default_tables + lcc_offset; + static const unsigned char* lowerCaseChars = jsc_pcre_default_tables + lcc_offset; return lowerCaseChars[c]; } static inline unsigned char flipCase(unsigned char c) { - static const unsigned char* flippedCaseChars = kjs_pcre_default_tables + fcc_offset; + static const unsigned char* flippedCaseChars = jsc_pcre_default_tables + fcc_offset; return flippedCaseChars[c]; } static inline unsigned char classBitmapForChar(unsigned char c) { - static const unsigned char* charClassBitmaps = kjs_pcre_default_tables + cbits_offset; + static const unsigned char* charClassBitmaps = jsc_pcre_default_tables + cbits_offset; return charClassBitmaps[c]; } static inline unsigned char charTypeForChar(unsigned char c) { - const unsigned char* charTypeMap = kjs_pcre_default_tables + ctypes_offset; + const unsigned char* charTypeMap = jsc_pcre_default_tables + ctypes_offset; return charTypeMap[c]; } @@ -413,8 +413,8 @@ static inline void advanceToEndOfBracket(const unsigned char*& opcodePtr) that one of the source files. They have to have external linkage, but but are not part of the public API and so not exported from the library. */ -extern int kjs_pcre_ucp_othercase(unsigned); -extern bool kjs_pcre_xclass(int, const unsigned char*); +extern int jsc_pcre_ucp_othercase(unsigned); +extern bool jsc_pcre_xclass(int, const unsigned char*); #endif diff --git a/JavaScriptCore/pcre/pcre_tables.cpp b/JavaScriptCore/pcre/pcre_tables.cpp index d306233..8696879 100644 --- a/JavaScriptCore/pcre/pcre_tables.cpp +++ b/JavaScriptCore/pcre/pcre_tables.cpp @@ -6,7 +6,7 @@ needed by JavaScriptCore and the rest of WebKit. Originally written by Philip Hazel Copyright (c) 1997-2006 University of Cambridge - Copyright (C) 2002, 2004, 2006, 2007 Apple Inc. All rights reserved. + Copyright (C) 2002, 2004, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without @@ -50,20 +50,20 @@ PCRE code modules. */ /* These are the breakpoints for different numbers of bytes in a UTF-8 character. */ -const int kjs_pcre_utf8_table1[6] = +const int jsc_pcre_utf8_table1[6] = { 0x7f, 0x7ff, 0xffff, 0x1fffff, 0x3ffffff, 0x7fffffff}; /* These are the indicator bits and the mask for the data bits to set in the first byte of a character, indexed by the number of additional bytes. */ -const int kjs_pcre_utf8_table2[6] = { 0, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc}; -const int kjs_pcre_utf8_table3[6] = { 0xff, 0x1f, 0x0f, 0x07, 0x03, 0x01}; +const int jsc_pcre_utf8_table2[6] = { 0, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc}; +const int jsc_pcre_utf8_table3[6] = { 0xff, 0x1f, 0x0f, 0x07, 0x03, 0x01}; /* Table of the number of extra characters, indexed by the first character masked with 0x3f. The highest number for a valid UTF-8 character is in fact 0x3d. */ -const unsigned char kjs_pcre_utf8_table4[0x40] = { +const unsigned char jsc_pcre_utf8_table4[0x40] = { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, diff --git a/JavaScriptCore/pcre/pcre_ucp_searchfuncs.cpp b/JavaScriptCore/pcre/pcre_ucp_searchfuncs.cpp index 6e1d0e4..5592865 100644 --- a/JavaScriptCore/pcre/pcre_ucp_searchfuncs.cpp +++ b/JavaScriptCore/pcre/pcre_ucp_searchfuncs.cpp @@ -6,7 +6,7 @@ needed by JavaScriptCore and the rest of WebKit. Originally written by Philip Hazel Copyright (c) 1997-2006 University of Cambridge - Copyright (C) 2002, 2004, 2006, 2007 Apple Inc. All rights reserved. + Copyright (C) 2002, 2004, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without @@ -60,7 +60,7 @@ Arguments: Returns: the other case or -1 if none */ -int kjs_pcre_ucp_othercase(unsigned c) +int jsc_pcre_ucp_othercase(unsigned c) { int bot = 0; int top = sizeof(ucp_table) / sizeof(cnode); diff --git a/JavaScriptCore/pcre/pcre_xclass.cpp b/JavaScriptCore/pcre/pcre_xclass.cpp index 2fb36d7..a32edd4 100644 --- a/JavaScriptCore/pcre/pcre_xclass.cpp +++ b/JavaScriptCore/pcre/pcre_xclass.cpp @@ -6,7 +6,7 @@ needed by JavaScriptCore and the rest of WebKit. Originally written by Philip Hazel Copyright (c) 1997-2006 University of Cambridge - Copyright (C) 2002, 2004, 2006, 2007 Apple Inc. All rights reserved. + Copyright (C) 2002, 2004, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without @@ -64,9 +64,9 @@ static inline void getUTF8CharAndAdvancePointer(int& c, const unsigned char*& su { c = *subjectPtr++; if ((c & 0xc0) == 0xc0) { - int gcaa = kjs_pcre_utf8_table4[c & 0x3f]; /* Number of additional bytes */ + int gcaa = jsc_pcre_utf8_table4[c & 0x3f]; /* Number of additional bytes */ int gcss = 6 * gcaa; - c = (c & kjs_pcre_utf8_table3[gcaa]) << gcss; + c = (c & jsc_pcre_utf8_table3[gcaa]) << gcss; while (gcaa-- > 0) { gcss -= 6; c |= (*subjectPtr++ & 0x3f) << gcss; @@ -74,7 +74,7 @@ static inline void getUTF8CharAndAdvancePointer(int& c, const unsigned char*& su } } -bool kjs_pcre_xclass(int c, const unsigned char* data) +bool jsc_pcre_xclass(int c, const unsigned char* data) { bool negated = (*data & XCL_NOT); diff --git a/JavaScriptCore/profiler/CallIdentifier.h b/JavaScriptCore/profiler/CallIdentifier.h index c24c44b..6ceef13 100644 --- a/JavaScriptCore/profiler/CallIdentifier.h +++ b/JavaScriptCore/profiler/CallIdentifier.h @@ -27,7 +27,7 @@ #ifndef CallIdentifier_h #define CallIdentifier_h -#include <kjs/ustring.h> +#include <runtime/UString.h> namespace JSC { diff --git a/JavaScriptCore/profiler/Profile.h b/JavaScriptCore/profiler/Profile.h index c232c55..dd96f77 100644 --- a/JavaScriptCore/profiler/Profile.h +++ b/JavaScriptCore/profiler/Profile.h @@ -27,7 +27,7 @@ #define Profile_h #include "ProfileNode.h" -#include <kjs/ustring.h> +#include <runtime/UString.h> #include <wtf/RefCounted.h> #include <wtf/RefPtr.h> diff --git a/JavaScriptCore/profiler/ProfileGenerator.cpp b/JavaScriptCore/profiler/ProfileGenerator.cpp index 1506788..b1d5d48 100644 --- a/JavaScriptCore/profiler/ProfileGenerator.cpp +++ b/JavaScriptCore/profiler/ProfileGenerator.cpp @@ -26,11 +26,11 @@ #include "config.h" #include "ProfileGenerator.h" -#include "ExecState.h" +#include "CallFrame.h" #include "JSGlobalObject.h" #include "JSStringRef.h" #include "JSFunction.h" -#include "Machine.h" +#include "Interpreter.h" #include "Profile.h" #include "Profiler.h" #include "Tracing.h" @@ -59,10 +59,10 @@ void ProfileGenerator::addParentForConsoleStart(ExecState* exec) int lineNumber; intptr_t sourceID; UString sourceURL; - JSValue* function; + JSValuePtr function; - exec->machine()->retrieveLastCaller(exec, lineNumber, sourceID, sourceURL, function); - m_currentNode = ProfileNode::create(Profiler::createCallIdentifier(&exec->globalData(), function ? function->toThisObject(exec) : 0, sourceURL, lineNumber), m_head.get(), m_head.get()); + exec->interpreter()->retrieveLastCaller(exec, lineNumber, sourceID, sourceURL, function); + m_currentNode = ProfileNode::create(Profiler::createCallIdentifier(&exec->globalData(), function ? function.toThisObject(exec) : 0, sourceURL, lineNumber), m_head.get(), m_head.get()); m_head->insertNode(m_currentNode.get()); } diff --git a/JavaScriptCore/profiler/Profiler.cpp b/JavaScriptCore/profiler/Profiler.cpp index c68fa1a..2de8f84 100644 --- a/JavaScriptCore/profiler/Profiler.cpp +++ b/JavaScriptCore/profiler/Profiler.cpp @@ -30,7 +30,7 @@ #include "Profiler.h" #include "CommonIdentifiers.h" -#include "ExecState.h" +#include "CallFrame.h" #include "JSFunction.h" #include "JSGlobalObject.h" #include "Profile.h" @@ -101,7 +101,7 @@ static inline void dispatchFunctionToProfiles(const Vector<RefPtr<ProfileGenerat } } -void Profiler::willExecute(ExecState* exec, JSValue* function) +void Profiler::willExecute(ExecState* exec, JSValuePtr function) { ASSERT(!m_currentProfiles.isEmpty()); @@ -117,7 +117,7 @@ void Profiler::willExecute(ExecState* exec, const UString& sourceURL, int starti dispatchFunctionToProfiles(m_currentProfiles, &ProfileGenerator::willExecute, callIdentifier, exec->lexicalGlobalObject()->profileGroup()); } -void Profiler::didExecute(ExecState* exec, JSValue* function) +void Profiler::didExecute(ExecState* exec, JSValuePtr function) { ASSERT(!m_currentProfiles.isEmpty()); @@ -131,11 +131,11 @@ void Profiler::didExecute(ExecState* exec, const UString& sourceURL, int startin dispatchFunctionToProfiles(m_currentProfiles, &ProfileGenerator::didExecute, createCallIdentifier(&exec->globalData(), noValue(), sourceURL, startingLineNumber), exec->lexicalGlobalObject()->profileGroup()); } -CallIdentifier Profiler::createCallIdentifier(JSGlobalData* globalData, JSValue* function, const UString& defaultSourceURL, int defaultLineNumber) +CallIdentifier Profiler::createCallIdentifier(JSGlobalData* globalData, JSValuePtr function, const UString& defaultSourceURL, int defaultLineNumber) { if (!function) return CallIdentifier(GlobalCodeExecution, defaultSourceURL, defaultLineNumber); - if (!function->isObject()) + if (!function.isObject()) return CallIdentifier("(unknown)", defaultSourceURL, defaultLineNumber); if (asObject(function)->inherits(&JSFunction::info)) return createCallIdentifierFromFunctionImp(globalData, asFunction(function)); @@ -147,7 +147,7 @@ CallIdentifier Profiler::createCallIdentifier(JSGlobalData* globalData, JSValue* CallIdentifier createCallIdentifierFromFunctionImp(JSGlobalData* globalData, JSFunction* function) { const UString& name = function->name(globalData); - return CallIdentifier(name.isEmpty() ? AnonymousFunction : name, function->m_body->sourceURL(), function->m_body->lineNo()); + return CallIdentifier(name.isEmpty() ? AnonymousFunction : name, function->body()->sourceURL(), function->body()->lineNo()); } } // namespace JSC diff --git a/JavaScriptCore/profiler/Profiler.h b/JavaScriptCore/profiler/Profiler.h index b622fb2..d00bccf 100644 --- a/JavaScriptCore/profiler/Profiler.h +++ b/JavaScriptCore/profiler/Profiler.h @@ -40,6 +40,7 @@ namespace JSC { class ExecState; class JSGlobalData; class JSObject; + class JSValuePtr; class ProfileGenerator; class UString; @@ -51,14 +52,14 @@ namespace JSC { } static Profiler* profiler(); - static CallIdentifier createCallIdentifier(JSGlobalData*, JSValue*, const UString& sourceURL, int lineNumber); + static CallIdentifier createCallIdentifier(JSGlobalData*, JSValuePtr, const UString& sourceURL, int lineNumber); void startProfiling(ExecState*, const UString& title); PassRefPtr<Profile> stopProfiling(ExecState*, const UString& title); - void willExecute(ExecState*, JSValue* function); + void willExecute(ExecState*, JSValuePtr function); void willExecute(ExecState*, const UString& sourceURL, int startingLineNumber); - void didExecute(ExecState*, JSValue* function); + void didExecute(ExecState*, JSValuePtr function); void didExecute(ExecState*, const UString& sourceURL, int startingLineNumber); const Vector<RefPtr<ProfileGenerator> >& currentProfiles() { return m_currentProfiles; }; diff --git a/JavaScriptCore/runtime/ArgList.cpp b/JavaScriptCore/runtime/ArgList.cpp index 7675b20..5ead733 100644 --- a/JavaScriptCore/runtime/ArgList.cpp +++ b/JavaScriptCore/runtime/ArgList.cpp @@ -51,7 +51,7 @@ void ArgList::markLists(ListSet& markSet) } } -void ArgList::slowAppend(JSValue* v) +void ArgList::slowAppend(JSValuePtr v) { // As long as our size stays within our Vector's inline // capacity, all our values are allocated on the stack, and diff --git a/JavaScriptCore/runtime/ArgList.h b/JavaScriptCore/runtime/ArgList.h index 44446aa..a1763e0 100644 --- a/JavaScriptCore/runtime/ArgList.h +++ b/JavaScriptCore/runtime/ArgList.h @@ -85,7 +85,7 @@ namespace JSC { size_t size() const { return m_size; } bool isEmpty() const { return !m_size; } - JSValue* at(ExecState* exec, size_t i) const + JSValuePtr at(ExecState* exec, size_t i) const { if (i < m_size) return m_buffer[i].jsValue(exec); @@ -99,7 +99,7 @@ namespace JSC { m_size = 0; } - void append(JSValue* v) + void append(JSValuePtr v) { ASSERT(!m_isReadOnly); @@ -125,7 +125,7 @@ namespace JSC { static void markLists(ListSet&); private: - void slowAppend(JSValue*); + void slowAppend(JSValuePtr); Register* m_buffer; size_t m_size; diff --git a/JavaScriptCore/runtime/Arguments.cpp b/JavaScriptCore/runtime/Arguments.cpp index fe1de62..b0429a9 100644 --- a/JavaScriptCore/runtime/Arguments.cpp +++ b/JavaScriptCore/runtime/Arguments.cpp @@ -145,28 +145,28 @@ bool Arguments::getOwnPropertySlot(ExecState* exec, const Identifier& propertyNa return JSObject::getOwnPropertySlot(exec, propertyName, slot); } -void Arguments::put(ExecState* exec, unsigned i, JSValue* value, PutPropertySlot& slot) +void Arguments::put(ExecState* exec, unsigned i, JSValuePtr value, PutPropertySlot& slot) { if (i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) { if (i < d->numParameters) - d->registers[d->firstParameterIndex + i] = value; + d->registers[d->firstParameterIndex + i] = JSValuePtr(value); else - d->extraArguments[i - d->numParameters] = value; + d->extraArguments[i - d->numParameters] = JSValuePtr(value); return; } JSObject::put(exec, Identifier(exec, UString::from(i)), value, slot); } -void Arguments::put(ExecState* exec, const Identifier& propertyName, JSValue* value, PutPropertySlot& slot) +void Arguments::put(ExecState* exec, const Identifier& propertyName, JSValuePtr value, PutPropertySlot& slot) { bool isArrayIndex; unsigned i = propertyName.toArrayIndex(&isArrayIndex); if (isArrayIndex && i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) { if (i < d->numParameters) - d->registers[d->firstParameterIndex + i] = value; + d->registers[d->firstParameterIndex + i] = JSValuePtr(value); else - d->extraArguments[i - d->numParameters] = value; + d->extraArguments[i - d->numParameters] = JSValuePtr(value); return; } diff --git a/JavaScriptCore/runtime/Arguments.h b/JavaScriptCore/runtime/Arguments.h index 93cc64f..ebea6ad 100644 --- a/JavaScriptCore/runtime/Arguments.h +++ b/JavaScriptCore/runtime/Arguments.h @@ -27,7 +27,7 @@ #include "JSActivation.h" #include "JSFunction.h" #include "JSGlobalObject.h" -#include "Machine.h" +#include "Interpreter.h" namespace JSC { @@ -73,17 +73,17 @@ namespace JSC { d->registers = &activation->registerAt(0); } - static PassRefPtr<StructureID> createStructureID(JSValue* prototype) + static PassRefPtr<Structure> createStructure(JSValuePtr prototype) { - return StructureID::create(prototype, TypeInfo(ObjectType)); + return Structure::create(prototype, TypeInfo(ObjectType)); } private: void getArgumentsData(CallFrame*, JSFunction*&, ptrdiff_t& firstParameterIndex, Register*& argv, int& argc); virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&); - virtual void put(ExecState*, const Identifier& propertyName, JSValue*, PutPropertySlot&); - virtual void put(ExecState*, unsigned propertyName, JSValue*, PutPropertySlot&); + virtual void put(ExecState*, const Identifier& propertyName, JSValuePtr, PutPropertySlot&); + virtual void put(ExecState*, unsigned propertyName, JSValuePtr, PutPropertySlot&); virtual bool deleteProperty(ExecState*, const Identifier& propertyName); virtual bool deleteProperty(ExecState*, unsigned propertyName); @@ -94,9 +94,9 @@ namespace JSC { OwnPtr<ArgumentsData> d; }; - Arguments* asArguments(JSValue*); + Arguments* asArguments(JSValuePtr); - inline Arguments* asArguments(JSValue* value) + inline Arguments* asArguments(JSValuePtr value) { ASSERT(asObject(value)->inherits(&Arguments::info)); return static_cast<Arguments*>(asObject(value)); @@ -106,8 +106,8 @@ namespace JSC { { function = callFrame->callee(); - CodeBlock* codeBlock = &function->m_body->generatedByteCode(); - int numParameters = codeBlock->numParameters; + CodeBlock* codeBlock = &function->body()->generatedBytecode(); + int numParameters = codeBlock->m_numParameters; argc = callFrame->argumentCount(); if (argc <= numParameters) @@ -129,7 +129,7 @@ namespace JSC { int numArguments; getArgumentsData(callFrame, callee, firstParameterIndex, argv, numArguments); - d->numParameters = callee->m_body->parameterCount(); + d->numParameters = callee->body()->parameterCount(); d->firstParameterIndex = firstParameterIndex; d->numArguments = numArguments; @@ -160,7 +160,7 @@ namespace JSC { : JSObject(callFrame->lexicalGlobalObject()->argumentsStructure()) , d(new ArgumentsData) { - ASSERT(!callFrame->callee()->m_body->parameterCount()); + ASSERT(!callFrame->callee()->body()->parameterCount()); unsigned numArguments = callFrame->argumentCount() - 1; @@ -206,8 +206,8 @@ namespace JSC { { ASSERT(!d()->registerArray); - size_t numParametersMinusThis = d()->functionBody->generatedByteCode().numParameters - 1; - size_t numVars = d()->functionBody->generatedByteCode().numVars; + size_t numParametersMinusThis = d()->functionBody->generatedBytecode().m_numParameters - 1; + size_t numVars = d()->functionBody->generatedBytecode().m_numVars; size_t numLocals = numVars + numParametersMinusThis; if (!numLocals) diff --git a/JavaScriptCore/runtime/ArrayConstructor.cpp b/JavaScriptCore/runtime/ArrayConstructor.cpp index 5784af0..dd3ff4b 100644 --- a/JavaScriptCore/runtime/ArrayConstructor.cpp +++ b/JavaScriptCore/runtime/ArrayConstructor.cpp @@ -26,13 +26,13 @@ #include "ArrayPrototype.h" #include "JSArray.h" -#include "lookup.h" +#include "Lookup.h" namespace JSC { ASSERT_CLASS_FITS_IN_CELL(ArrayConstructor); -ArrayConstructor::ArrayConstructor(ExecState* exec, PassRefPtr<StructureID> structure, ArrayPrototype* arrayPrototype) +ArrayConstructor::ArrayConstructor(ExecState* exec, PassRefPtr<Structure> structure, ArrayPrototype* arrayPrototype) : InternalFunction(&exec->globalData(), structure, Identifier(exec, arrayPrototype->classInfo()->className)) { // ECMA 15.4.3.1 Array.prototype @@ -45,9 +45,9 @@ ArrayConstructor::ArrayConstructor(ExecState* exec, PassRefPtr<StructureID> stru static JSObject* constructArrayWithSizeQuirk(ExecState* exec, const ArgList& args) { // a single numeric argument denotes the array size (!) - if (args.size() == 1 && args.at(exec, 0)->isNumber()) { - uint32_t n = args.at(exec, 0)->toUInt32(exec); - if (n != args.at(exec, 0)->toNumber(exec)) + if (args.size() == 1 && args.at(exec, 0).isNumber()) { + uint32_t n = args.at(exec, 0).toUInt32(exec); + if (n != args.at(exec, 0).toNumber(exec)) return throwError(exec, RangeError, "Array size is not a small enough positive integer."); return new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure(), n); } @@ -68,7 +68,7 @@ ConstructType ArrayConstructor::getConstructData(ConstructData& constructData) return ConstructTypeHost; } -static JSValue* callArrayConstructor(ExecState* exec, JSObject*, JSValue*, const ArgList& args) +static JSValuePtr callArrayConstructor(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) { return constructArrayWithSizeQuirk(exec, args); } diff --git a/JavaScriptCore/runtime/ArrayConstructor.h b/JavaScriptCore/runtime/ArrayConstructor.h index 6f0f866..8300d8c 100644 --- a/JavaScriptCore/runtime/ArrayConstructor.h +++ b/JavaScriptCore/runtime/ArrayConstructor.h @@ -29,7 +29,7 @@ namespace JSC { class ArrayConstructor : public InternalFunction { public: - ArrayConstructor(ExecState*, PassRefPtr<StructureID>, ArrayPrototype*); + ArrayConstructor(ExecState*, PassRefPtr<Structure>, ArrayPrototype*); virtual ConstructType getConstructData(ConstructData&); virtual CallType getCallData(CallData&); diff --git a/JavaScriptCore/runtime/ArrayPrototype.cpp b/JavaScriptCore/runtime/ArrayPrototype.cpp index 5280784..4cd229a 100644 --- a/JavaScriptCore/runtime/ArrayPrototype.cpp +++ b/JavaScriptCore/runtime/ArrayPrototype.cpp @@ -24,10 +24,11 @@ #include "config.h" #include "ArrayPrototype.h" -#include "Machine.h" +#include "CodeBlock.h" +#include "Interpreter.h" #include "ObjectPrototype.h" -#include "lookup.h" -#include "operations.h" +#include "Lookup.h" +#include "Operations.h" #include <algorithm> #include <wtf/Assertions.h> #include <wtf/HashSet.h> @@ -36,25 +37,25 @@ namespace JSC { ASSERT_CLASS_FITS_IN_CELL(ArrayPrototype); -static JSValue* arrayProtoFuncToString(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* arrayProtoFuncToLocaleString(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* arrayProtoFuncConcat(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* arrayProtoFuncJoin(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* arrayProtoFuncPop(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* arrayProtoFuncPush(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* arrayProtoFuncReverse(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* arrayProtoFuncShift(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* arrayProtoFuncSlice(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* arrayProtoFuncSort(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* arrayProtoFuncSplice(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* arrayProtoFuncUnShift(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* arrayProtoFuncEvery(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* arrayProtoFuncForEach(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* arrayProtoFuncSome(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* arrayProtoFuncIndexOf(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* arrayProtoFuncFilter(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* arrayProtoFuncMap(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* arrayProtoFuncLastIndexOf(ExecState*, JSObject*, JSValue*, const ArgList&); +static JSValuePtr arrayProtoFuncToString(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr arrayProtoFuncToLocaleString(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr arrayProtoFuncConcat(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr arrayProtoFuncJoin(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr arrayProtoFuncPop(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr arrayProtoFuncPush(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr arrayProtoFuncReverse(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr arrayProtoFuncShift(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr arrayProtoFuncSlice(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr arrayProtoFuncSort(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr arrayProtoFuncSplice(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr arrayProtoFuncUnShift(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr arrayProtoFuncEvery(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr arrayProtoFuncForEach(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr arrayProtoFuncSome(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr arrayProtoFuncIndexOf(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr arrayProtoFuncFilter(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr arrayProtoFuncMap(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr arrayProtoFuncLastIndexOf(ExecState*, JSObject*, JSValuePtr, const ArgList&); } @@ -62,6 +63,14 @@ static JSValue* arrayProtoFuncLastIndexOf(ExecState*, JSObject*, JSValue*, const namespace JSC { +static inline bool isNumericCompareFunction(CallType callType, const CallData& callData) +{ + if (callType != CallTypeJS) + return false; + + return callData.js.functionBody->bytecode(callData.js.scopeChain).isNumericCompareFunction(); +} + // ------------------------------ ArrayPrototype ---------------------------- const ClassInfo ArrayPrototype::info = {"Array", &JSArray::info, 0, ExecState::arrayTable}; @@ -91,7 +100,7 @@ const ClassInfo ArrayPrototype::info = {"Array", &JSArray::info, 0, ExecState::a */ // ECMA 15.4.4 -ArrayPrototype::ArrayPrototype(PassRefPtr<StructureID> structure) +ArrayPrototype::ArrayPrototype(PassRefPtr<Structure> structure) : JSArray(structure) { } @@ -104,7 +113,7 @@ bool ArrayPrototype::getOwnPropertySlot(ExecState* exec, const Identifier& prope // ------------------------------ Array Functions ---------------------------- // Helper function -static JSValue* getProperty(ExecState* exec, JSObject* obj, unsigned index) +static JSValuePtr getProperty(ExecState* exec, JSObject* obj, unsigned index) { PropertySlot slot(obj); if (!obj->getPropertySlot(exec, index, slot)) @@ -112,15 +121,15 @@ static JSValue* getProperty(ExecState* exec, JSObject* obj, unsigned index) return slot.getValue(exec, index); } -static void putProperty(ExecState* exec, JSObject* obj, const Identifier& propertyName, JSValue* value) +static void putProperty(ExecState* exec, JSObject* obj, const Identifier& propertyName, JSValuePtr value) { PutPropertySlot slot; obj->put(exec, propertyName, value, slot); } -JSValue* arrayProtoFuncToString(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&) +JSValuePtr arrayProtoFuncToString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) { - if (!thisValue->isObject(&JSArray::info)) + if (!thisValue.isObject(&JSArray::info)) return throwError(exec, TypeError); JSObject* thisObj = asArray(thisValue); @@ -133,7 +142,7 @@ JSValue* arrayProtoFuncToString(ExecState* exec, JSObject*, JSValue* thisValue, return jsEmptyString(exec); // return an empty string, avoiding infinite recursion. Vector<UChar, 256> strBuffer; - unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec); + unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); for (unsigned k = 0; k < length; k++) { if (k >= 1) strBuffer.append(','); @@ -143,11 +152,11 @@ JSValue* arrayProtoFuncToString(ExecState* exec, JSObject*, JSValue* thisValue, break; } - JSValue* element = thisObj->get(exec, k); - if (element->isUndefinedOrNull()) + JSValuePtr element = thisObj->get(exec, k); + if (element.isUndefinedOrNull()) continue; - UString str = element->toString(exec); + UString str = element.toString(exec); strBuffer.append(str.data(), str.size()); if (!strBuffer.data()) { @@ -162,9 +171,9 @@ JSValue* arrayProtoFuncToString(ExecState* exec, JSObject*, JSValue* thisValue, return jsString(exec, UString(strBuffer.data(), strBuffer.data() ? strBuffer.size() : 0)); } -JSValue* arrayProtoFuncToLocaleString(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&) +JSValuePtr arrayProtoFuncToLocaleString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) { - if (!thisValue->isObject(&JSArray::info)) + if (!thisValue.isObject(&JSArray::info)) return throwError(exec, TypeError); JSObject* thisObj = asArray(thisValue); @@ -177,7 +186,7 @@ JSValue* arrayProtoFuncToLocaleString(ExecState* exec, JSObject*, JSValue* thisV return jsEmptyString(exec); // return an empty string, avoding infinite recursion. Vector<UChar, 256> strBuffer; - unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec); + unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); for (unsigned k = 0; k < length; k++) { if (k >= 1) strBuffer.append(','); @@ -187,19 +196,19 @@ JSValue* arrayProtoFuncToLocaleString(ExecState* exec, JSObject*, JSValue* thisV break; } - JSValue* element = thisObj->get(exec, k); - if (element->isUndefinedOrNull()) + JSValuePtr element = thisObj->get(exec, k); + if (element.isUndefinedOrNull()) continue; - JSObject* o = element->toObject(exec); - JSValue* conversionFunction = o->get(exec, exec->propertyNames().toLocaleString); + JSObject* o = element.toObject(exec); + JSValuePtr conversionFunction = o->get(exec, exec->propertyNames().toLocaleString); UString str; CallData callData; - CallType callType = conversionFunction->getCallData(callData); + CallType callType = conversionFunction.getCallData(callData); if (callType != CallTypeNone) - str = call(exec, conversionFunction, callType, callData, element, exec->emptyList())->toString(exec); + str = call(exec, conversionFunction, callType, callData, element, exec->emptyList()).toString(exec); else - str = element->toString(exec); + str = element.toString(exec); strBuffer.append(str.data(), str.size()); if (!strBuffer.data()) { @@ -214,9 +223,9 @@ JSValue* arrayProtoFuncToLocaleString(ExecState* exec, JSObject*, JSValue* thisV return jsString(exec, UString(strBuffer.data(), strBuffer.data() ? strBuffer.size() : 0)); } -JSValue* arrayProtoFuncJoin(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) +JSValuePtr arrayProtoFuncJoin(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) { - JSObject* thisObj = thisValue->toThisObject(exec); + JSObject* thisObj = thisValue.toThisObject(exec); HashSet<JSObject*>& arrayVisitedElements = exec->globalData().arrayVisitedElements; if (arrayVisitedElements.size() > MaxReentryDepth) @@ -229,9 +238,9 @@ JSValue* arrayProtoFuncJoin(ExecState* exec, JSObject*, JSValue* thisValue, cons Vector<UChar, 256> strBuffer; UChar comma = ','; - UString separator = args.at(exec, 0)->isUndefined() ? UString(&comma, 1) : args.at(exec, 0)->toString(exec); + UString separator = args.at(exec, 0).isUndefined() ? UString(&comma, 1) : args.at(exec, 0).toString(exec); - unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec); + unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); for (unsigned k = 0; k < length; k++) { if (k >= 1) strBuffer.append(separator.data(), separator.size()); @@ -241,11 +250,11 @@ JSValue* arrayProtoFuncJoin(ExecState* exec, JSObject*, JSValue* thisValue, cons break; } - JSValue* element = thisObj->get(exec, k); - if (element->isUndefinedOrNull()) + JSValuePtr element = thisObj->get(exec, k); + if (element.isUndefinedOrNull()) continue; - UString str = element->toString(exec); + UString str = element.toString(exec); strBuffer.append(str.data(), str.size()); if (!strBuffer.data()) { @@ -260,19 +269,19 @@ JSValue* arrayProtoFuncJoin(ExecState* exec, JSObject*, JSValue* thisValue, cons return jsString(exec, UString(strBuffer.data(), strBuffer.data() ? strBuffer.size() : 0)); } -JSValue* arrayProtoFuncConcat(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) +JSValuePtr arrayProtoFuncConcat(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) { JSArray* arr = constructEmptyArray(exec); int n = 0; - JSValue* curArg = thisValue->toThisObject(exec); + JSValuePtr curArg = thisValue.toThisObject(exec); ArgList::const_iterator it = args.begin(); ArgList::const_iterator end = args.end(); while (1) { - if (curArg->isObject(&JSArray::info)) { + if (curArg.isObject(&JSArray::info)) { JSArray* curArray = asArray(curArg); unsigned length = curArray->length(); for (unsigned k = 0; k < length; ++k) { - if (JSValue* v = getProperty(exec, curArray, k)) + if (JSValuePtr v = getProperty(exec, curArray, k)) arr->put(exec, n, v); n++; } @@ -289,14 +298,14 @@ JSValue* arrayProtoFuncConcat(ExecState* exec, JSObject*, JSValue* thisValue, co return arr; } -JSValue* arrayProtoFuncPop(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&) +JSValuePtr arrayProtoFuncPop(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) { - if (exec->machine()->isJSArray(thisValue)) + if (exec->interpreter()->isJSArray(thisValue)) return asArray(thisValue)->pop(); - JSObject* thisObj = thisValue->toThisObject(exec); - JSValue* result; - unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec); + JSObject* thisObj = thisValue.toThisObject(exec); + JSValuePtr result; + unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); if (length == 0) { putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(exec, length)); result = jsUndefined(); @@ -308,16 +317,16 @@ JSValue* arrayProtoFuncPop(ExecState* exec, JSObject*, JSValue* thisValue, const return result; } -JSValue* arrayProtoFuncPush(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) +JSValuePtr arrayProtoFuncPush(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) { - if (exec->machine()->isJSArray(thisValue) && args.size() == 1) { + if (exec->interpreter()->isJSArray(thisValue) && args.size() == 1) { JSArray* array = asArray(thisValue); array->push(exec, args.begin()->jsValue(exec)); return jsNumber(exec, array->length()); } - JSObject* thisObj = thisValue->toThisObject(exec); - unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec); + JSObject* thisObj = thisValue.toThisObject(exec); + unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); for (unsigned n = 0; n < args.size(); n++) thisObj->put(exec, length + n, args.at(exec, n)); length += args.size(); @@ -325,16 +334,16 @@ JSValue* arrayProtoFuncPush(ExecState* exec, JSObject*, JSValue* thisValue, cons return jsNumber(exec, length); } -JSValue* arrayProtoFuncReverse(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&) +JSValuePtr arrayProtoFuncReverse(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) { - JSObject* thisObj = thisValue->toThisObject(exec); - unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec); + JSObject* thisObj = thisValue.toThisObject(exec); + unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); unsigned middle = length / 2; for (unsigned k = 0; k < middle; k++) { unsigned lk1 = length - k - 1; - JSValue* obj2 = getProperty(exec, thisObj, lk1); - JSValue* obj = getProperty(exec, thisObj, k); + JSValuePtr obj2 = getProperty(exec, thisObj, lk1); + JSValuePtr obj = getProperty(exec, thisObj, k); if (obj2) thisObj->put(exec, k, obj2); @@ -349,19 +358,19 @@ JSValue* arrayProtoFuncReverse(ExecState* exec, JSObject*, JSValue* thisValue, c return thisObj; } -JSValue* arrayProtoFuncShift(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&) +JSValuePtr arrayProtoFuncShift(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) { - JSObject* thisObj = thisValue->toThisObject(exec); - JSValue* result; + JSObject* thisObj = thisValue.toThisObject(exec); + JSValuePtr result; - unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec); + unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); if (length == 0) { putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(exec, length)); result = jsUndefined(); } else { result = thisObj->get(exec, 0); for (unsigned k = 1; k < length; k++) { - if (JSValue* obj = getProperty(exec, thisObj, k)) + if (JSValuePtr obj = getProperty(exec, thisObj, k)) thisObj->put(exec, k - 1, obj); else thisObj->deleteProperty(exec, k - 1); @@ -372,17 +381,17 @@ JSValue* arrayProtoFuncShift(ExecState* exec, JSObject*, JSValue* thisValue, con return result; } -JSValue* arrayProtoFuncSlice(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) +JSValuePtr arrayProtoFuncSlice(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) { // http://developer.netscape.com/docs/manuals/js/client/jsref/array.htm#1193713 or 15.4.4.10 - JSObject* thisObj = thisValue->toThisObject(exec); + JSObject* thisObj = thisValue.toThisObject(exec); // We return a new array JSArray* resObj = constructEmptyArray(exec); - JSValue* result = resObj; - double begin = args.at(exec, 0)->toInteger(exec); - unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec); + JSValuePtr result = resObj; + double begin = args.at(exec, 0).toInteger(exec); + unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); if (begin >= 0) { if (begin > length) begin = length; @@ -392,10 +401,10 @@ JSValue* arrayProtoFuncSlice(ExecState* exec, JSObject*, JSValue* thisValue, con begin = 0; } double end; - if (args.at(exec, 1)->isUndefined()) + if (args.at(exec, 1).isUndefined()) end = length; else { - end = args.at(exec, 1)->toInteger(exec); + end = args.at(exec, 1).toInteger(exec); if (end < 0) { end += length; if (end < 0) @@ -410,30 +419,32 @@ JSValue* arrayProtoFuncSlice(ExecState* exec, JSObject*, JSValue* thisValue, con int b = static_cast<int>(begin); int e = static_cast<int>(end); for (int k = b; k < e; k++, n++) { - if (JSValue* v = getProperty(exec, thisObj, k)) + if (JSValuePtr v = getProperty(exec, thisObj, k)) resObj->put(exec, n, v); } resObj->setLength(n); return result; } -JSValue* arrayProtoFuncSort(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) +JSValuePtr arrayProtoFuncSort(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) { - JSObject* thisObj = thisValue->toThisObject(exec); + JSObject* thisObj = thisValue.toThisObject(exec); - JSValue* function = args.at(exec, 0); + JSValuePtr function = args.at(exec, 0); CallData callData; - CallType callType = function->getCallData(callData); + CallType callType = function.getCallData(callData); if (thisObj->classInfo() == &JSArray::info) { - if (callType != CallTypeNone) + if (isNumericCompareFunction(callType, callData)) + asArray(thisObj)->sortNumeric(exec, function, callType, callData); + else if (callType != CallTypeNone) asArray(thisObj)->sort(exec, function, callType, callData); else asArray(thisObj)->sort(exec); return thisObj; } - unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec); + unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); if (!length) return thisObj; @@ -441,23 +452,23 @@ JSValue* arrayProtoFuncSort(ExecState* exec, JSObject*, JSValue* thisValue, cons // "Min" sort. Not the fastest, but definitely less code than heapsort // or quicksort, and much less swapping than bubblesort/insertionsort. for (unsigned i = 0; i < length - 1; ++i) { - JSValue* iObj = thisObj->get(exec, i); + JSValuePtr iObj = thisObj->get(exec, i); unsigned themin = i; - JSValue* minObj = iObj; + JSValuePtr minObj = iObj; for (unsigned j = i + 1; j < length; ++j) { - JSValue* jObj = thisObj->get(exec, j); + JSValuePtr jObj = thisObj->get(exec, j); double compareResult; - if (jObj->isUndefined()) + if (jObj.isUndefined()) compareResult = 1; // don't check minObj because there's no need to differentiate == (0) from > (1) - else if (minObj->isUndefined()) + else if (minObj.isUndefined()) compareResult = -1; else if (callType != CallTypeNone) { ArgList l; l.append(jObj); l.append(minObj); - compareResult = call(exec, function, callType, callData, exec->globalThisValue(), l)->toNumber(exec); + compareResult = call(exec, function, callType, callData, exec->globalThisValue(), l).toNumber(exec); } else - compareResult = (jObj->toString(exec) < minObj->toString(exec)) ? -1 : 1; + compareResult = (jObj.toString(exec) < minObj.toString(exec)) ? -1 : 1; if (compareResult < 0) { themin = j; @@ -473,17 +484,17 @@ JSValue* arrayProtoFuncSort(ExecState* exec, JSObject*, JSValue* thisValue, cons return thisObj; } -JSValue* arrayProtoFuncSplice(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) +JSValuePtr arrayProtoFuncSplice(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) { - JSObject* thisObj = thisValue->toThisObject(exec); + JSObject* thisObj = thisValue.toThisObject(exec); // 15.4.4.12 JSArray* resObj = constructEmptyArray(exec); - JSValue* result = resObj; - unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec); + JSValuePtr result = resObj; + unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); if (!args.size()) return jsUndefined(); - int begin = args.at(exec, 0)->toUInt32(exec); + int begin = args.at(exec, 0).toUInt32(exec); if (begin < 0) begin = std::max<int>(begin + length, 0); else @@ -491,12 +502,12 @@ JSValue* arrayProtoFuncSplice(ExecState* exec, JSObject*, JSValue* thisValue, co unsigned deleteCount; if (args.size() > 1) - deleteCount = std::min<int>(std::max<int>(args.at(exec, 1)->toUInt32(exec), 0), length - begin); + deleteCount = std::min<int>(std::max<int>(args.at(exec, 1).toUInt32(exec), 0), length - begin); else deleteCount = length - begin; for (unsigned k = 0; k < deleteCount; k++) { - if (JSValue* v = getProperty(exec, thisObj, k + begin)) + if (JSValuePtr v = getProperty(exec, thisObj, k + begin)) resObj->put(exec, k, v); } resObj->setLength(deleteCount); @@ -505,7 +516,7 @@ JSValue* arrayProtoFuncSplice(ExecState* exec, JSObject*, JSValue* thisValue, co if (additionalArgs != deleteCount) { if (additionalArgs < deleteCount) { for (unsigned k = begin; k < length - deleteCount; ++k) { - if (JSValue* v = getProperty(exec, thisObj, k + deleteCount)) + if (JSValuePtr v = getProperty(exec, thisObj, k + deleteCount)) thisObj->put(exec, k + additionalArgs, v); else thisObj->deleteProperty(exec, k + additionalArgs); @@ -514,7 +525,7 @@ JSValue* arrayProtoFuncSplice(ExecState* exec, JSObject*, JSValue* thisValue, co thisObj->deleteProperty(exec, k - 1); } else { for (unsigned k = length - deleteCount; (int)k > begin; --k) { - if (JSValue* obj = getProperty(exec, thisObj, k + deleteCount - 1)) + if (JSValuePtr obj = getProperty(exec, thisObj, k + deleteCount - 1)) thisObj->put(exec, k + additionalArgs - 1, obj); else thisObj->deleteProperty(exec, k + additionalArgs - 1); @@ -528,16 +539,16 @@ JSValue* arrayProtoFuncSplice(ExecState* exec, JSObject*, JSValue* thisValue, co return result; } -JSValue* arrayProtoFuncUnShift(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) +JSValuePtr arrayProtoFuncUnShift(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) { - JSObject* thisObj = thisValue->toThisObject(exec); + JSObject* thisObj = thisValue.toThisObject(exec); // 15.4.4.13 - unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec); + unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); unsigned nrArgs = args.size(); if (nrArgs) { for (unsigned k = length; k > 0; --k) { - if (JSValue* v = getProperty(exec, thisObj, k - 1)) + if (JSValuePtr v = getProperty(exec, thisObj, k - 1)) thisObj->put(exec, k + nrArgs - 1, v); else thisObj->deleteProperty(exec, k + nrArgs - 1); @@ -545,33 +556,33 @@ JSValue* arrayProtoFuncUnShift(ExecState* exec, JSObject*, JSValue* thisValue, c } for (unsigned k = 0; k < nrArgs; ++k) thisObj->put(exec, k, args.at(exec, k)); - JSValue* result = jsNumber(exec, length + nrArgs); + JSValuePtr result = jsNumber(exec, length + nrArgs); putProperty(exec, thisObj, exec->propertyNames().length, result); return result; } -JSValue* arrayProtoFuncFilter(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) +JSValuePtr arrayProtoFuncFilter(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) { - JSObject* thisObj = thisValue->toThisObject(exec); + JSObject* thisObj = thisValue.toThisObject(exec); - JSValue* function = args.at(exec, 0); + JSValuePtr function = args.at(exec, 0); CallData callData; - CallType callType = function->getCallData(callData); + CallType callType = function.getCallData(callData); if (callType == CallTypeNone) return throwError(exec, TypeError); - JSObject* applyThis = args.at(exec, 1)->isUndefinedOrNull() ? exec->globalThisValue() : args.at(exec, 1)->toObject(exec); + JSObject* applyThis = args.at(exec, 1).isUndefinedOrNull() ? exec->globalThisValue() : args.at(exec, 1).toObject(exec); JSArray* resultArray = constructEmptyArray(exec); unsigned filterIndex = 0; - unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec); + unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); for (unsigned k = 0; k < length && !exec->hadException(); ++k) { PropertySlot slot(thisObj); if (!thisObj->getPropertySlot(exec, k, slot)) continue; - JSValue* v = slot.getValue(exec, k); + JSValuePtr v = slot.getValue(exec, k); ArgList eachArguments; @@ -579,27 +590,27 @@ JSValue* arrayProtoFuncFilter(ExecState* exec, JSObject*, JSValue* thisValue, co eachArguments.append(jsNumber(exec, k)); eachArguments.append(thisObj); - JSValue* result = call(exec, function, callType, callData, applyThis, eachArguments); + JSValuePtr result = call(exec, function, callType, callData, applyThis, eachArguments); - if (result->toBoolean(exec)) + if (result.toBoolean(exec)) resultArray->put(exec, filterIndex++, v); } return resultArray; } -JSValue* arrayProtoFuncMap(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) +JSValuePtr arrayProtoFuncMap(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) { - JSObject* thisObj = thisValue->toThisObject(exec); + JSObject* thisObj = thisValue.toThisObject(exec); - JSValue* function = args.at(exec, 0); + JSValuePtr function = args.at(exec, 0); CallData callData; - CallType callType = function->getCallData(callData); + CallType callType = function.getCallData(callData); if (callType == CallTypeNone) return throwError(exec, TypeError); - JSObject* applyThis = args.at(exec, 1)->isUndefinedOrNull() ? exec->globalThisValue() : args.at(exec, 1)->toObject(exec); + JSObject* applyThis = args.at(exec, 1).isUndefinedOrNull() ? exec->globalThisValue() : args.at(exec, 1).toObject(exec); - unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec); + unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); JSArray* resultArray = constructEmptyArray(exec, length); @@ -608,7 +619,7 @@ JSValue* arrayProtoFuncMap(ExecState* exec, JSObject*, JSValue* thisValue, const if (!thisObj->getPropertySlot(exec, k, slot)) continue; - JSValue* v = slot.getValue(exec, k); + JSValuePtr v = slot.getValue(exec, k); ArgList eachArguments; @@ -616,7 +627,7 @@ JSValue* arrayProtoFuncMap(ExecState* exec, JSObject*, JSValue* thisValue, const eachArguments.append(jsNumber(exec, k)); eachArguments.append(thisObj); - JSValue* result = call(exec, function, callType, callData, applyThis, eachArguments); + JSValuePtr result = call(exec, function, callType, callData, applyThis, eachArguments); resultArray->put(exec, k, result); } @@ -628,21 +639,21 @@ JSValue* arrayProtoFuncMap(ExecState* exec, JSObject*, JSValue* thisValue, const // http://developer-test.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:forEach // http://developer-test.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:some -JSValue* arrayProtoFuncEvery(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) +JSValuePtr arrayProtoFuncEvery(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) { - JSObject* thisObj = thisValue->toThisObject(exec); + JSObject* thisObj = thisValue.toThisObject(exec); - JSValue* function = args.at(exec, 0); + JSValuePtr function = args.at(exec, 0); CallData callData; - CallType callType = function->getCallData(callData); + CallType callType = function.getCallData(callData); if (callType == CallTypeNone) return throwError(exec, TypeError); - JSObject* applyThis = args.at(exec, 1)->isUndefinedOrNull() ? exec->globalThisValue() : args.at(exec, 1)->toObject(exec); + JSObject* applyThis = args.at(exec, 1).isUndefinedOrNull() ? exec->globalThisValue() : args.at(exec, 1).toObject(exec); - JSValue* result = jsBoolean(true); + JSValuePtr result = jsBoolean(true); - unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec); + unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); for (unsigned k = 0; k < length && !exec->hadException(); ++k) { PropertySlot slot(thisObj); @@ -655,7 +666,7 @@ JSValue* arrayProtoFuncEvery(ExecState* exec, JSObject*, JSValue* thisValue, con eachArguments.append(jsNumber(exec, k)); eachArguments.append(thisObj); - bool predicateResult = call(exec, function, callType, callData, applyThis, eachArguments)->toBoolean(exec); + bool predicateResult = call(exec, function, callType, callData, applyThis, eachArguments).toBoolean(exec); if (!predicateResult) { result = jsBoolean(false); @@ -666,19 +677,19 @@ JSValue* arrayProtoFuncEvery(ExecState* exec, JSObject*, JSValue* thisValue, con return result; } -JSValue* arrayProtoFuncForEach(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) +JSValuePtr arrayProtoFuncForEach(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) { - JSObject* thisObj = thisValue->toThisObject(exec); + JSObject* thisObj = thisValue.toThisObject(exec); - JSValue* function = args.at(exec, 0); + JSValuePtr function = args.at(exec, 0); CallData callData; - CallType callType = function->getCallData(callData); + CallType callType = function.getCallData(callData); if (callType == CallTypeNone) return throwError(exec, TypeError); - JSObject* applyThis = args.at(exec, 1)->isUndefinedOrNull() ? exec->globalThisValue() : args.at(exec, 1)->toObject(exec); + JSObject* applyThis = args.at(exec, 1).isUndefinedOrNull() ? exec->globalThisValue() : args.at(exec, 1).toObject(exec); - unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec); + unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); for (unsigned k = 0; k < length && !exec->hadException(); ++k) { PropertySlot slot(thisObj); if (!thisObj->getPropertySlot(exec, k, slot)) @@ -694,21 +705,21 @@ JSValue* arrayProtoFuncForEach(ExecState* exec, JSObject*, JSValue* thisValue, c return jsUndefined(); } -JSValue* arrayProtoFuncSome(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) +JSValuePtr arrayProtoFuncSome(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) { - JSObject* thisObj = thisValue->toThisObject(exec); + JSObject* thisObj = thisValue.toThisObject(exec); - JSValue* function = args.at(exec, 0); + JSValuePtr function = args.at(exec, 0); CallData callData; - CallType callType = function->getCallData(callData); + CallType callType = function.getCallData(callData); if (callType == CallTypeNone) return throwError(exec, TypeError); - JSObject* applyThis = args.at(exec, 1)->isUndefinedOrNull() ? exec->globalThisValue() : args.at(exec, 1)->toObject(exec); + JSObject* applyThis = args.at(exec, 1).isUndefinedOrNull() ? exec->globalThisValue() : args.at(exec, 1).toObject(exec); - JSValue* result = jsBoolean(false); + JSValuePtr result = jsBoolean(false); - unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec); + unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); for (unsigned k = 0; k < length && !exec->hadException(); ++k) { PropertySlot slot(thisObj); if (!thisObj->getPropertySlot(exec, k, slot)) @@ -719,7 +730,7 @@ JSValue* arrayProtoFuncSome(ExecState* exec, JSObject*, JSValue* thisValue, cons eachArguments.append(jsNumber(exec, k)); eachArguments.append(thisObj); - bool predicateResult = call(exec, function, callType, callData, applyThis, eachArguments)->toBoolean(exec); + bool predicateResult = call(exec, function, callType, callData, applyThis, eachArguments).toBoolean(exec); if (predicateResult) { result = jsBoolean(true); @@ -729,16 +740,16 @@ JSValue* arrayProtoFuncSome(ExecState* exec, JSObject*, JSValue* thisValue, cons return result; } -JSValue* arrayProtoFuncIndexOf(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) +JSValuePtr arrayProtoFuncIndexOf(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) { // JavaScript 1.5 Extension by Mozilla // Documentation: http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:indexOf - JSObject* thisObj = thisValue->toThisObject(exec); + JSObject* thisObj = thisValue.toThisObject(exec); unsigned index = 0; - double d = args.at(exec, 1)->toInteger(exec); - unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec); + double d = args.at(exec, 1).toInteger(exec); + unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); if (d < 0) d += length; if (d > 0) { @@ -748,28 +759,28 @@ JSValue* arrayProtoFuncIndexOf(ExecState* exec, JSObject*, JSValue* thisValue, c index = static_cast<unsigned>(d); } - JSValue* searchElement = args.at(exec, 0); + JSValuePtr searchElement = args.at(exec, 0); for (; index < length; ++index) { - JSValue* e = getProperty(exec, thisObj, index); + JSValuePtr e = getProperty(exec, thisObj, index); if (!e) continue; - if (strictEqual(searchElement, e)) + if (JSValuePtr::strictEqual(searchElement, e)) return jsNumber(exec, index); } return jsNumber(exec, -1); } -JSValue* arrayProtoFuncLastIndexOf(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) +JSValuePtr arrayProtoFuncLastIndexOf(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) { // JavaScript 1.6 Extension by Mozilla // Documentation: http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:lastIndexOf - JSObject* thisObj = thisValue->toThisObject(exec); + JSObject* thisObj = thisValue.toThisObject(exec); - unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec); + unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); int index = length - 1; - double d = args.at(exec, 1)->toIntegerPreserveNaN(exec); + double d = args.at(exec, 1).toIntegerPreserveNaN(exec); if (d < 0) { d += length; @@ -779,12 +790,12 @@ JSValue* arrayProtoFuncLastIndexOf(ExecState* exec, JSObject*, JSValue* thisValu if (d < length) index = static_cast<int>(d); - JSValue* searchElement = args.at(exec, 0); + JSValuePtr searchElement = args.at(exec, 0); for (; index >= 0; --index) { - JSValue* e = getProperty(exec, thisObj, index); + JSValuePtr e = getProperty(exec, thisObj, index); if (!e) continue; - if (strictEqual(searchElement, e)) + if (JSValuePtr::strictEqual(searchElement, e)) return jsNumber(exec, index); } diff --git a/JavaScriptCore/runtime/ArrayPrototype.h b/JavaScriptCore/runtime/ArrayPrototype.h index 33ce30b..2165089 100644 --- a/JavaScriptCore/runtime/ArrayPrototype.h +++ b/JavaScriptCore/runtime/ArrayPrototype.h @@ -22,13 +22,13 @@ #define ArrayPrototype_h #include "JSArray.h" -#include "lookup.h" +#include "Lookup.h" namespace JSC { class ArrayPrototype : public JSArray { public: - explicit ArrayPrototype(PassRefPtr<StructureID>); + explicit ArrayPrototype(PassRefPtr<Structure>); bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&); diff --git a/JavaScriptCore/runtime/BatchedTransitionOptimizer.h b/JavaScriptCore/runtime/BatchedTransitionOptimizer.h index 536d09c..13dd95c 100644 --- a/JavaScriptCore/runtime/BatchedTransitionOptimizer.h +++ b/JavaScriptCore/runtime/BatchedTransitionOptimizer.h @@ -37,13 +37,13 @@ namespace JSC { BatchedTransitionOptimizer(JSObject* object) : m_object(object) { - if (!m_object->structureID()->isDictionary()) - m_object->setStructureID(StructureID::toDictionaryTransition(m_object->structureID())); + if (!m_object->structure()->isDictionary()) + m_object->setStructure(Structure::toDictionaryTransition(m_object->structure())); } ~BatchedTransitionOptimizer() { - m_object->setStructureID(StructureID::fromDictionaryTransition(m_object->structureID())); + m_object->setStructure(Structure::fromDictionaryTransition(m_object->structure())); } private: diff --git a/JavaScriptCore/runtime/BooleanConstructor.cpp b/JavaScriptCore/runtime/BooleanConstructor.cpp index 46a6018..bdf3322 100644 --- a/JavaScriptCore/runtime/BooleanConstructor.cpp +++ b/JavaScriptCore/runtime/BooleanConstructor.cpp @@ -28,7 +28,7 @@ namespace JSC { ASSERT_CLASS_FITS_IN_CELL(BooleanConstructor); -BooleanConstructor::BooleanConstructor(ExecState* exec, PassRefPtr<StructureID> structure, BooleanPrototype* booleanPrototype) +BooleanConstructor::BooleanConstructor(ExecState* exec, PassRefPtr<Structure> structure, BooleanPrototype* booleanPrototype) : InternalFunction(&exec->globalData(), structure, Identifier(exec, booleanPrototype->classInfo()->className)) { putDirectWithoutTransition(exec->propertyNames().prototype, booleanPrototype, DontEnum | DontDelete | ReadOnly); @@ -41,7 +41,7 @@ BooleanConstructor::BooleanConstructor(ExecState* exec, PassRefPtr<StructureID> JSObject* constructBoolean(ExecState* exec, const ArgList& args) { BooleanObject* obj = new (exec) BooleanObject(exec->lexicalGlobalObject()->booleanObjectStructure()); - obj->setInternalValue(jsBoolean(args.at(exec, 0)->toBoolean(exec))); + obj->setInternalValue(jsBoolean(args.at(exec, 0).toBoolean(exec))); return obj; } @@ -57,9 +57,9 @@ ConstructType BooleanConstructor::getConstructData(ConstructData& constructData) } // ECMA 15.6.1 -static JSValue* callBooleanConstructor(ExecState* exec, JSObject*, JSValue*, const ArgList& args) +static JSValuePtr callBooleanConstructor(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) { - return jsBoolean(args.at(exec, 0)->toBoolean(exec)); + return jsBoolean(args.at(exec, 0).toBoolean(exec)); } CallType BooleanConstructor::getCallData(CallData& callData) @@ -68,7 +68,7 @@ CallType BooleanConstructor::getCallData(CallData& callData) return CallTypeHost; } -JSObject* constructBooleanFromImmediateBoolean(ExecState* exec, JSValue* immediateBooleanValue) +JSObject* constructBooleanFromImmediateBoolean(ExecState* exec, JSValuePtr immediateBooleanValue) { BooleanObject* obj = new (exec) BooleanObject(exec->lexicalGlobalObject()->booleanObjectStructure()); obj->setInternalValue(immediateBooleanValue); diff --git a/JavaScriptCore/runtime/BooleanConstructor.h b/JavaScriptCore/runtime/BooleanConstructor.h index 3b1f1a0..db4e8e2 100644 --- a/JavaScriptCore/runtime/BooleanConstructor.h +++ b/JavaScriptCore/runtime/BooleanConstructor.h @@ -29,14 +29,14 @@ namespace JSC { class BooleanConstructor : public InternalFunction { public: - BooleanConstructor(ExecState*, PassRefPtr<StructureID>, BooleanPrototype*); + BooleanConstructor(ExecState*, PassRefPtr<Structure>, BooleanPrototype*); private: virtual ConstructType getConstructData(ConstructData&); virtual CallType getCallData(CallData&); }; - JSObject* constructBooleanFromImmediateBoolean(ExecState*, JSValue*); + JSObject* constructBooleanFromImmediateBoolean(ExecState*, JSValuePtr); JSObject* constructBoolean(ExecState*, const ArgList&); } // namespace JSC diff --git a/JavaScriptCore/runtime/BooleanObject.cpp b/JavaScriptCore/runtime/BooleanObject.cpp index 2ebfb1b..01f695a 100644 --- a/JavaScriptCore/runtime/BooleanObject.cpp +++ b/JavaScriptCore/runtime/BooleanObject.cpp @@ -27,7 +27,7 @@ ASSERT_CLASS_FITS_IN_CELL(BooleanObject); const ClassInfo BooleanObject::info = { "Boolean", 0, 0, 0 }; -BooleanObject::BooleanObject(PassRefPtr<StructureID> structure) +BooleanObject::BooleanObject(PassRefPtr<Structure> structure) : JSWrapperObject(structure) { } diff --git a/JavaScriptCore/runtime/BooleanObject.h b/JavaScriptCore/runtime/BooleanObject.h index 5963b28..68941e3 100644 --- a/JavaScriptCore/runtime/BooleanObject.h +++ b/JavaScriptCore/runtime/BooleanObject.h @@ -27,15 +27,15 @@ namespace JSC { class BooleanObject : public JSWrapperObject { public: - explicit BooleanObject(PassRefPtr<StructureID>); + explicit BooleanObject(PassRefPtr<Structure>); virtual const ClassInfo* classInfo() const { return &info; } static const ClassInfo info; }; - BooleanObject* asBooleanObject(JSValue*); + BooleanObject* asBooleanObject(JSValuePtr); - inline BooleanObject* asBooleanObject(JSValue* value) + inline BooleanObject* asBooleanObject(JSValuePtr value) { ASSERT(asObject(value)->inherits(&BooleanObject::info)); return static_cast<BooleanObject*>(asObject(value)); diff --git a/JavaScriptCore/runtime/BooleanPrototype.cpp b/JavaScriptCore/runtime/BooleanPrototype.cpp index b47aeac..9eb52d1 100644 --- a/JavaScriptCore/runtime/BooleanPrototype.cpp +++ b/JavaScriptCore/runtime/BooleanPrototype.cpp @@ -31,12 +31,12 @@ namespace JSC { ASSERT_CLASS_FITS_IN_CELL(BooleanPrototype); // Functions -static JSValue* booleanProtoFuncToString(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* booleanProtoFuncValueOf(ExecState*, JSObject*, JSValue*, const ArgList&); +static JSValuePtr booleanProtoFuncToString(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr booleanProtoFuncValueOf(ExecState*, JSObject*, JSValuePtr, const ArgList&); // ECMA 15.6.4 -BooleanPrototype::BooleanPrototype(ExecState* exec, PassRefPtr<StructureID> structure, StructureID* prototypeFunctionStructure) +BooleanPrototype::BooleanPrototype(ExecState* exec, PassRefPtr<Structure> structure, Structure* prototypeFunctionStructure) : BooleanObject(structure) { setInternalValue(jsBoolean(false)); @@ -50,7 +50,7 @@ BooleanPrototype::BooleanPrototype(ExecState* exec, PassRefPtr<StructureID> stru // ECMA 15.6.4.2 + 15.6.4.3 -JSValue* booleanProtoFuncToString(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&) +JSValuePtr booleanProtoFuncToString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) { if (thisValue == jsBoolean(false)) return jsNontrivialString(exec, "false"); @@ -58,7 +58,7 @@ JSValue* booleanProtoFuncToString(ExecState* exec, JSObject*, JSValue* thisValue if (thisValue == jsBoolean(true)) return jsNontrivialString(exec, "true"); - if (!thisValue->isObject(&BooleanObject::info)) + if (!thisValue.isObject(&BooleanObject::info)) return throwError(exec, TypeError); if (asBooleanObject(thisValue)->internalValue() == jsBoolean(false)) @@ -68,12 +68,12 @@ JSValue* booleanProtoFuncToString(ExecState* exec, JSObject*, JSValue* thisValue return jsNontrivialString(exec, "true"); } -JSValue* booleanProtoFuncValueOf(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&) +JSValuePtr booleanProtoFuncValueOf(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) { - if (JSImmediate::isBoolean(thisValue)) + if (thisValue.isBoolean()) return thisValue; - if (!thisValue->isObject(&BooleanObject::info)) + if (!thisValue.isObject(&BooleanObject::info)) return throwError(exec, TypeError); return asBooleanObject(thisValue)->internalValue(); diff --git a/JavaScriptCore/runtime/BooleanPrototype.h b/JavaScriptCore/runtime/BooleanPrototype.h index 484bb7d..16f80b5 100644 --- a/JavaScriptCore/runtime/BooleanPrototype.h +++ b/JavaScriptCore/runtime/BooleanPrototype.h @@ -27,7 +27,7 @@ namespace JSC { class BooleanPrototype : public BooleanObject { public: - BooleanPrototype(ExecState*, PassRefPtr<StructureID>, StructureID* prototypeFunctionStructure); + BooleanPrototype(ExecState*, PassRefPtr<Structure>, Structure* prototypeFunctionStructure); }; } // namespace JSC diff --git a/JavaScriptCore/runtime/CallData.cpp b/JavaScriptCore/runtime/CallData.cpp index 572c495..fbb6392 100644 --- a/JavaScriptCore/runtime/CallData.cpp +++ b/JavaScriptCore/runtime/CallData.cpp @@ -30,7 +30,7 @@ namespace JSC { -JSValue* call(ExecState* exec, JSValue* functionObject, CallType callType, const CallData& callData, JSValue* thisValue, const ArgList& args) +JSValuePtr call(ExecState* exec, JSValuePtr functionObject, CallType callType, const CallData& callData, JSValuePtr thisValue, const ArgList& args) { if (callType == CallTypeHost) return callData.native.function(exec, asObject(functionObject), thisValue, args); diff --git a/JavaScriptCore/runtime/CallData.h b/JavaScriptCore/runtime/CallData.h index 5be011a..b8d84cd 100644 --- a/JavaScriptCore/runtime/CallData.h +++ b/JavaScriptCore/runtime/CallData.h @@ -29,14 +29,13 @@ #ifndef CallData_h #define CallData_h -#include "JSImmediate.h" - namespace JSC { class ArgList; class ExecState; class FunctionBodyNode; class JSObject; + class JSValuePtr; class ScopeChainNode; enum CallType { @@ -45,7 +44,7 @@ namespace JSC { CallTypeJS }; - typedef JSValue* (*NativeFunction)(ExecState*, JSObject*, JSValue* thisValue, const ArgList&); + typedef JSValuePtr (*NativeFunction)(ExecState*, JSObject*, JSValuePtr thisValue, const ArgList&); union CallData { struct { @@ -57,7 +56,7 @@ namespace JSC { } js; }; - JSValue* call(ExecState*, JSValue* functionObject, CallType, const CallData&, JSValue* thisValue, const ArgList&); + JSValuePtr call(ExecState*, JSValuePtr functionObject, CallType, const CallData&, JSValuePtr thisValue, const ArgList&); } // namespace JSC diff --git a/JavaScriptCore/runtime/ClassInfo.h b/JavaScriptCore/runtime/ClassInfo.h index 979145e..097fb09 100644 --- a/JavaScriptCore/runtime/ClassInfo.h +++ b/JavaScriptCore/runtime/ClassInfo.h @@ -23,7 +23,7 @@ #ifndef ClassInfo_h #define ClassInfo_h -#include "ExecState.h" +#include "CallFrame.h" namespace JSC { diff --git a/JavaScriptCore/kjs/collector.cpp b/JavaScriptCore/runtime/Collector.cpp index 53e889e..13e7f51 100644 --- a/JavaScriptCore/kjs/collector.cpp +++ b/JavaScriptCore/runtime/Collector.cpp @@ -19,16 +19,17 @@ */ #include "config.h" -#include "collector.h" +#include "Collector.h" #include "ArgList.h" +#include "CallFrame.h" #include "CollectorHeapIterator.h" -#include "ExecState.h" +#include "Interpreter.h" #include "JSGlobalObject.h" #include "JSLock.h" #include "JSString.h" #include "JSValue.h" -#include "Machine.h" +#include "Nodes.h" #include "Tracing.h" #include <algorithm> #include <setjmp.h> @@ -59,10 +60,6 @@ #include <thread.h> #endif -#if PLATFORM(LINUX) -#include <pthread.h> -#endif - #if PLATFORM(OPENBSD) #include <pthread.h> #endif @@ -125,17 +122,12 @@ Heap::Heap(JSGlobalData* globalData) : m_markListSet(0) #if ENABLE(JSC_MULTIPLE_THREADS) , m_registeredThreads(0) + , m_currentThreadRegistrar(0) #endif , m_globalData(globalData) { ASSERT(globalData); -#if ENABLE(JSC_MULTIPLE_THREADS) - int error = pthread_key_create(&m_currentThreadRegistrar, unregisterThread); - if (error) - CRASH(); -#endif - memset(&primaryHeap, 0, sizeof(CollectorHeap)); memset(&numberHeap, 0, sizeof(CollectorHeap)); } @@ -169,11 +161,10 @@ void Heap::destroy() freeHeap(&numberHeap); #if ENABLE(JSC_MULTIPLE_THREADS) -#ifndef NDEBUG - int error = -#endif - pthread_key_delete(m_currentThreadRegistrar); - ASSERT(!error); + if (m_currentThreadRegistrar) { + int error = pthread_key_delete(m_currentThreadRegistrar); + ASSERT_UNUSED(error, !error); + } MutexLocker registeredThreadsLock(m_registeredThreadsMutex); for (Heap::Thread* t = m_registeredThreads; t;) { @@ -193,6 +184,10 @@ static NEVER_INLINE CollectorBlock* allocateBlock() vm_address_t address = 0; // FIXME: tag the region as a JavaScriptCore heap when we get a registered VM tag: <rdar://problem/6054788>. vm_map(current_task(), &address, BLOCK_SIZE, BLOCK_OFFSET_MASK, VM_FLAGS_ANYWHERE, MEMORY_OBJECT_NULL, 0, FALSE, VM_PROT_DEFAULT, VM_PROT_DEFAULT, VM_INHERIT_DEFAULT); +#elif PLATFORM(SYMBIAN) + // no memory map in symbian, need to hack with fastMalloc + void* address = fastMalloc(BLOCK_SIZE); + memset(reinterpret_cast<void*>(address), 0, BLOCK_SIZE); #elif PLATFORM(WIN_OS) // windows virtual address granularity is naturally 64k LPVOID address = VirtualAlloc(NULL, BLOCK_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); @@ -235,6 +230,8 @@ static void freeBlock(CollectorBlock* block) { #if PLATFORM(DARWIN) vm_deallocate(current_task(), reinterpret_cast<vm_address_t>(block), BLOCK_SIZE); +#elif PLATFORM(SYMBIAN) + fastFree(block); #elif PLATFORM(WIN_OS) VirtualFree(block, 0, MEM_RELEASE); #elif HAVE(POSIX_MEMALIGN) @@ -278,24 +275,23 @@ template <HeapType heapType> ALWAYS_INLINE void* Heap::heapAllocate(size_t s) CollectorHeap& heap = heapType == PrimaryHeap ? primaryHeap : numberHeap; ASSERT(JSLock::lockCount() > 0); ASSERT(JSLock::currentThreadIsHoldingLock()); - ASSERT(s <= HeapConstants<heapType>::cellSize); - UNUSED_PARAM(s); // s is now only used for the above assert + ASSERT_UNUSED(s, s <= HeapConstants<heapType>::cellSize); ASSERT(heap.operationInProgress == NoOperation); ASSERT(heapType == PrimaryHeap || heap.extraCost == 0); // FIXME: If another global variable access here doesn't hurt performance - // too much, we could abort() in NDEBUG builds, which could help ensure we + // too much, we could CRASH() in NDEBUG builds, which could help ensure we // don't spend any time debugging cases where we allocate inside an object's // deallocation code. - size_t numLiveObjects = heap.numLiveObjects; - size_t usedBlocks = heap.usedBlocks; - size_t i = heap.firstBlockWithPossibleSpace; - #if COLLECT_ON_EVERY_ALLOCATION collect(); #endif + size_t numLiveObjects = heap.numLiveObjects; + size_t usedBlocks = heap.usedBlocks; + size_t i = heap.firstBlockWithPossibleSpace; + // if we have a huge amount of extra cost, we'll try to collect even if we still have // free cells left. if (heapType == PrimaryHeap && heap.extraCost > ALLOCATIONS_PER_COLLECTION) { @@ -436,7 +432,7 @@ static inline void* currentThreadStackBase() if (stackBase == 0 || thread != stackThread) { pthread_attr_t sattr; pthread_attr_init(&sattr); -#if HAVE(PTHREAD_NP_H) +#if HAVE(PTHREAD_NP_H) || PLATFORM(NETBSD) // e.g. on FreeBSD 5.4, neundorf@kde.org pthread_attr_get_np(thread, &sattr); #else @@ -450,6 +446,15 @@ static inline void* currentThreadStackBase() stackThread = thread; } return static_cast<char*>(stackBase) + stackSize; +#elif PLATFORM(SYMBIAN) + static void* stackBase = 0; + if (stackBase == 0) { + TThreadStackInfo info; + RThread thread; + thread.StackInfo(info); + stackBase = (void*)info.iBase; + } + return (void*)stackBase; #else #error Need a way to get the stack base on this platform #endif @@ -467,9 +472,19 @@ static inline PlatformThread getCurrentPlatformThread() #endif } +void Heap::makeUsableFromMultipleThreads() +{ + if (m_currentThreadRegistrar) + return; + + int error = pthread_key_create(&m_currentThreadRegistrar, unregisterThread); + if (error) + CRASH(); +} + void Heap::registerThread() { - if (pthread_getspecific(m_currentThreadRegistrar)) + if (!m_currentThreadRegistrar || pthread_getspecific(m_currentThreadRegistrar)) return; pthread_setspecific(m_currentThreadRegistrar, this); @@ -651,7 +666,7 @@ typedef CONTEXT PlatformThreadRegisters; #error Need a thread register struct for this platform #endif -size_t getPlatformThreadRegisters(const PlatformThread& platformThread, PlatformThreadRegisters& regs) +static size_t getPlatformThreadRegisters(const PlatformThread& platformThread, PlatformThreadRegisters& regs) { #if PLATFORM(DARWIN) @@ -789,45 +804,45 @@ void Heap::setGCProtectNeedsLocking() m_protectedValuesMutex.set(new Mutex); } -void Heap::protect(JSValue* k) +void Heap::protect(JSValuePtr k) { ASSERT(k); ASSERT(JSLock::currentThreadIsHoldingLock() || !m_globalData->isSharedInstance); - if (JSImmediate::isImmediate(k)) + if (!k.isCell()) return; if (m_protectedValuesMutex) m_protectedValuesMutex->lock(); - m_protectedValues.add(k->asCell()); + m_protectedValues.add(k.asCell()); if (m_protectedValuesMutex) m_protectedValuesMutex->unlock(); } -void Heap::unprotect(JSValue* k) +void Heap::unprotect(JSValuePtr k) { ASSERT(k); ASSERT(JSLock::currentThreadIsHoldingLock() || !m_globalData->isSharedInstance); - if (JSImmediate::isImmediate(k)) + if (!k.isCell()) return; if (m_protectedValuesMutex) m_protectedValuesMutex->lock(); - m_protectedValues.remove(k->asCell()); + m_protectedValues.remove(k.asCell()); if (m_protectedValuesMutex) m_protectedValuesMutex->unlock(); } -Heap* Heap::heap(JSValue* v) +Heap* Heap::heap(JSValuePtr v) { - if (JSImmediate::isImmediate(v)) + if (!v.isCell()) return 0; - return Heap::cellBlock(v->asCell())->heap; + return Heap::cellBlock(v.asCell())->heap; } void Heap::markProtectedObjects() @@ -956,7 +971,7 @@ bool Heap::collect() ASSERT((primaryHeap.operationInProgress == NoOperation) | (numberHeap.operationInProgress == NoOperation)); if ((primaryHeap.operationInProgress != NoOperation) | (numberHeap.operationInProgress != NoOperation)) - abort(); + CRASH(); JAVASCRIPTCORE_GC_BEGIN(); primaryHeap.operationInProgress = Collection; @@ -968,18 +983,12 @@ bool Heap::collect() markProtectedObjects(); if (m_markListSet && m_markListSet->size()) ArgList::markLists(*m_markListSet); - if (m_globalData->exception && !m_globalData->exception->marked()) - m_globalData->exception->mark(); - m_globalData->machine->registerFile().markCallFrames(this); + if (m_globalData->exception && !m_globalData->exception.marked()) + m_globalData->exception.mark(); + m_globalData->interpreter->registerFile().markCallFrames(this); m_globalData->smallStrings.mark(); - - JSGlobalObject* globalObject = m_globalData->head; - if (globalObject) { - do { - globalObject->markCrossHeapDependentObjects(); - globalObject = globalObject->next(); - } while (globalObject != m_globalData->head); - } + if (m_globalData->scopeNodeBeingReparsed) + m_globalData->scopeNodeBeingReparsed->mark(); JAVASCRIPTCORE_GC_MARKED(); @@ -994,9 +1003,29 @@ bool Heap::collect() return numLiveObjects < originalLiveObjects; } -size_t Heap::size() +size_t Heap::objectCount() +{ + return primaryHeap.numLiveObjects + numberHeap.numLiveObjects - m_globalData->smallStrings.count(); +} + +template <HeapType heapType> +static void addToStatistics(Heap::Statistics& statistics, const CollectorHeap& heap) +{ + typedef HeapConstants<heapType> HC; + for (size_t i = 0; i < heap.usedBlocks; ++i) { + if (heap.blocks[i]) { + statistics.size += BLOCK_SIZE; + statistics.free += (HC::cellsPerBlock - heap.blocks[i]->usedCells) * HC::cellSize; + } + } +} + +Heap::Statistics Heap::statistics() const { - return primaryHeap.numLiveObjects + numberHeap.numLiveObjects; + Statistics statistics = { 0, 0 }; + JSC::addToStatistics<PrimaryHeap>(statistics, primaryHeap); + JSC::addToStatistics<NumberHeap>(statistics, numberHeap); + return statistics; } size_t Heap::globalObjectCount() @@ -1046,16 +1075,16 @@ size_t Heap::protectedObjectCount() return result; } -static const char* typeName(JSCell* val) +static const char* typeName(JSCell* cell) { - if (val->isString()) + if (cell->isString()) return "string"; - if (val->isNumber()) + if (cell->isNumber()) return "number"; - if (val->isGetterSetter()) + if (cell->isGetterSetter()) return "gettersetter"; - ASSERT(val->isObject()); - const ClassInfo* info = static_cast<JSObject*>(val)->classInfo(); + ASSERT(cell->isObject()); + const ClassInfo* info = static_cast<JSObject*>(cell)->classInfo(); return info ? info->className : "Object"; } diff --git a/JavaScriptCore/kjs/collector.h b/JavaScriptCore/runtime/Collector.h index 4233b06..ba41d60 100644 --- a/JavaScriptCore/kjs/collector.h +++ b/JavaScriptCore/runtime/Collector.h @@ -1,7 +1,7 @@ /* * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) * Copyright (C) 2001 Peter Kelly (pmk@post.com) - * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2004, 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 Lesser General Public @@ -19,10 +19,10 @@ * */ -#ifndef KJSCOLLECTOR_H_ -#define KJSCOLLECTOR_H_ +#ifndef Collector_h +#define Collector_h -#include "JSImmediate.h" +#include <stddef.h> #include <string.h> #include <wtf/HashCountedSet.h> #include <wtf/HashSet.h> @@ -43,6 +43,7 @@ namespace JSC { class CollectorBlock; class JSCell; class JSGlobalData; + class JSValuePtr; enum OperationInProgress { NoOperation, Allocation, Collection }; enum HeapType { PrimaryHeap, NumberHeap }; @@ -87,13 +88,18 @@ namespace JSC { void reportExtraMemoryCost(size_t cost); - size_t size(); + size_t objectCount(); + struct Statistics { + size_t size; + size_t free; + }; + Statistics statistics() const; void setGCProtectNeedsLocking(); - void protect(JSValue*); - void unprotect(JSValue*); + void protect(JSValuePtr); + void unprotect(JSValuePtr); - static Heap* heap(JSValue*); // 0 for immediate values + static Heap* heap(JSValuePtr); // 0 for immediate values size_t globalObjectCount(); size_t protectedObjectCount(); @@ -144,6 +150,8 @@ namespace JSC { HashSet<ArgList*>* m_markListSet; #if ENABLE(JSC_MULTIPLE_THREADS) + void makeUsableFromMultipleThreads(); + static void unregisterThread(void*); void unregisterThread(); @@ -276,4 +284,4 @@ namespace JSC { } // namespace JSC -#endif /* KJSCOLLECTOR_H_ */ +#endif /* Collector_h */ diff --git a/JavaScriptCore/runtime/CollectorHeapIterator.h b/JavaScriptCore/runtime/CollectorHeapIterator.h index c5e1d78..e38a852 100644 --- a/JavaScriptCore/runtime/CollectorHeapIterator.h +++ b/JavaScriptCore/runtime/CollectorHeapIterator.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Apple Inc. All rights reserved. + * 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 @@ -24,7 +24,10 @@ */ #include "config.h" -#include "collector.h" +#include "Collector.h" + +#ifndef CollectorHeapIterator_h +#define CollectorHeapIterator_h namespace JSC { @@ -83,3 +86,5 @@ namespace JSC { } } // namespace JSC + +#endif // CollectorHeapIterator_h diff --git a/JavaScriptCore/runtime/CommonIdentifiers.h b/JavaScriptCore/runtime/CommonIdentifiers.h index 1788c77..45b99a8 100644 --- a/JavaScriptCore/runtime/CommonIdentifiers.h +++ b/JavaScriptCore/runtime/CommonIdentifiers.h @@ -21,7 +21,7 @@ #ifndef CommonIdentifiers_h #define CommonIdentifiers_h -#include "identifier.h" +#include "Identifier.h" #include <wtf/Noncopyable.h> // ArgList of property names, passed to a macro so we can do set them up various diff --git a/JavaScriptCore/kjs/interpreter.cpp b/JavaScriptCore/runtime/Completion.cpp index 1188349..0231a15 100644 --- a/JavaScriptCore/kjs/interpreter.cpp +++ b/JavaScriptCore/runtime/Completion.cpp @@ -21,14 +21,13 @@ */ #include "config.h" -#include "interpreter.h" +#include "Completion.h" -#include "ExecState.h" +#include "CallFrame.h" #include "JSGlobalObject.h" #include "JSLock.h" -#include "Machine.h" +#include "Interpreter.h" #include "Parser.h" -#include "completion.h" #include "Debugger.h" #include <stdio.h> @@ -38,7 +37,7 @@ namespace JSC { -Completion Interpreter::checkSyntax(ExecState* exec, const SourceCode& source) +Completion checkSyntax(ExecState* exec, const SourceCode& source) { JSLock lock(exec); @@ -51,7 +50,7 @@ Completion Interpreter::checkSyntax(ExecState* exec, const SourceCode& source) return Completion(Normal); } -Completion Interpreter::evaluate(ExecState* exec, ScopeChain& scopeChain, const SourceCode& source, JSValue* thisValue) +Completion evaluate(ExecState* exec, ScopeChain& scopeChain, const SourceCode& source, JSValuePtr thisValue) { JSLock lock(exec); @@ -62,13 +61,13 @@ Completion Interpreter::evaluate(ExecState* exec, ScopeChain& scopeChain, const if (!programNode) return Completion(Throw, Error::create(exec, SyntaxError, errMsg, errLine, source.provider()->asID(), source.provider()->url())); - JSObject* thisObj = (!thisValue || thisValue->isUndefinedOrNull()) ? exec->dynamicGlobalObject() : thisValue->toObject(exec); + JSObject* thisObj = (!thisValue || thisValue.isUndefinedOrNull()) ? exec->dynamicGlobalObject() : thisValue.toObject(exec); - JSValue* exception = noValue(); - JSValue* result = exec->machine()->execute(programNode.get(), exec, scopeChain.node(), thisObj, &exception); + JSValuePtr exception = noValue(); + JSValuePtr result = exec->interpreter()->execute(programNode.get(), exec, scopeChain.node(), thisObj, &exception); if (exception) { - if (exception->isObject() && asObject(exception)->isWatchdogException()) + if (exception.isObject() && asObject(exception)->isWatchdogException()) return Completion(Interrupted, result); return Completion(Throw, exception); } diff --git a/JavaScriptCore/kjs/completion.h b/JavaScriptCore/runtime/Completion.h index 56d13ed..9631b50 100644 --- a/JavaScriptCore/kjs/completion.h +++ b/JavaScriptCore/runtime/Completion.h @@ -20,13 +20,17 @@ * */ -#ifndef KJS_COMPLETION_H -#define KJS_COMPLETION_H +#ifndef Completion_h +#define Completion_h #include "JSValue.h" namespace JSC { + class ExecState; + class ScopeChain; + class SourceCode; + enum ComplType { Normal, Break, Continue, ReturnValue, Throw, Interrupted }; /* @@ -35,22 +39,25 @@ namespace JSC { */ class Completion { public: - Completion(ComplType type = Normal, JSValue* value = noValue()) + Completion(ComplType type = Normal, JSValuePtr value = noValue()) : m_type(type) , m_value(value) { } ComplType complType() const { return m_type; } - JSValue* value() const { return m_value; } - void setValue(JSValue* v) { m_value = v; } - bool isValueCompletion() const { return !!m_value; } + JSValuePtr value() const { return m_value; } + void setValue(JSValuePtr v) { m_value = v; } + bool isValueCompletion() const { return m_value; } private: ComplType m_type; - JSValue* m_value; + JSValuePtr m_value; }; + Completion checkSyntax(ExecState*, const SourceCode&); + Completion evaluate(ExecState*, ScopeChain&, const SourceCode&, JSValuePtr thisValue = noValue()); + } // namespace JSC -#endif // KJS_COMPLETION_H +#endif // Completion_h diff --git a/JavaScriptCore/runtime/ConstructData.cpp b/JavaScriptCore/runtime/ConstructData.cpp index 88a8ef6..7a729ae 100644 --- a/JavaScriptCore/runtime/ConstructData.cpp +++ b/JavaScriptCore/runtime/ConstructData.cpp @@ -30,7 +30,7 @@ namespace JSC { -JSObject* construct(ExecState* exec, JSValue* object, ConstructType constructType, const ConstructData& constructData, const ArgList& args) +JSObject* construct(ExecState* exec, JSValuePtr object, ConstructType constructType, const ConstructData& constructData, const ArgList& args) { if (constructType == ConstructTypeHost) return constructData.native.function(exec, asObject(object), args); diff --git a/JavaScriptCore/runtime/ConstructData.h b/JavaScriptCore/runtime/ConstructData.h index 3cc52a0..559c1bd 100644 --- a/JavaScriptCore/runtime/ConstructData.h +++ b/JavaScriptCore/runtime/ConstructData.h @@ -29,14 +29,13 @@ #ifndef ConstructData_h #define ConstructData_h -#include "JSImmediate.h" // temporary until JSValue* becomes a class we can forward-declare - namespace JSC { class ArgList; class ExecState; class FunctionBodyNode; class JSObject; + class JSValuePtr; class ScopeChainNode; enum ConstructType { @@ -57,7 +56,7 @@ namespace JSC { } js; }; - JSObject* construct(ExecState*, JSValue* constructor, ConstructType, const ConstructData&, const ArgList&); + JSObject* construct(ExecState*, JSValuePtr constructor, ConstructType, const ConstructData&, const ArgList&); } // namespace JSC diff --git a/JavaScriptCore/runtime/DateConstructor.cpp b/JavaScriptCore/runtime/DateConstructor.cpp index 8339ff3..92ab897 100644 --- a/JavaScriptCore/runtime/DateConstructor.cpp +++ b/JavaScriptCore/runtime/DateConstructor.cpp @@ -47,11 +47,11 @@ namespace JSC { ASSERT_CLASS_FITS_IN_CELL(DateConstructor); -static JSValue* dateParse(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* dateNow(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* dateUTC(ExecState*, JSObject*, JSValue*, const ArgList&); +static JSValuePtr dateParse(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr dateNow(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr dateUTC(ExecState*, JSObject*, JSValuePtr, const ArgList&); -DateConstructor::DateConstructor(ExecState* exec, PassRefPtr<StructureID> structure, StructureID* prototypeFunctionStructure, DatePrototype* datePrototype) +DateConstructor::DateConstructor(ExecState* exec, PassRefPtr<Structure> structure, Structure* prototypeFunctionStructure, DatePrototype* datePrototype) : InternalFunction(&exec->globalData(), structure, Identifier(exec, datePrototype->classInfo()->className)) { putDirectWithoutTransition(exec->propertyNames().prototype, datePrototype, DontEnum|DontDelete|ReadOnly); @@ -73,35 +73,35 @@ JSObject* constructDate(ExecState* exec, const ArgList& args) if (numArgs == 0) // new Date() ECMA 15.9.3.3 value = getCurrentUTCTime(); else if (numArgs == 1) { - if (args.at(exec, 0)->isObject(&DateInstance::info)) + if (args.at(exec, 0).isObject(&DateInstance::info)) value = asDateInstance(args.at(exec, 0))->internalNumber(); else { - JSValue* primitive = args.at(exec, 0)->toPrimitive(exec); - if (primitive->isString()) - value = parseDate(primitive->getString()); + JSValuePtr primitive = args.at(exec, 0).toPrimitive(exec); + if (primitive.isString()) + value = parseDate(primitive.getString()); else - value = primitive->toNumber(exec); + value = primitive.toNumber(exec); } } else { - if (isnan(args.at(exec, 0)->toNumber(exec)) - || isnan(args.at(exec, 1)->toNumber(exec)) - || (numArgs >= 3 && isnan(args.at(exec, 2)->toNumber(exec))) - || (numArgs >= 4 && isnan(args.at(exec, 3)->toNumber(exec))) - || (numArgs >= 5 && isnan(args.at(exec, 4)->toNumber(exec))) - || (numArgs >= 6 && isnan(args.at(exec, 5)->toNumber(exec))) - || (numArgs >= 7 && isnan(args.at(exec, 6)->toNumber(exec)))) + if (isnan(args.at(exec, 0).toNumber(exec)) + || isnan(args.at(exec, 1).toNumber(exec)) + || (numArgs >= 3 && isnan(args.at(exec, 2).toNumber(exec))) + || (numArgs >= 4 && isnan(args.at(exec, 3).toNumber(exec))) + || (numArgs >= 5 && isnan(args.at(exec, 4).toNumber(exec))) + || (numArgs >= 6 && isnan(args.at(exec, 5).toNumber(exec))) + || (numArgs >= 7 && isnan(args.at(exec, 6).toNumber(exec)))) value = NaN; else { GregorianDateTime t; - int year = args.at(exec, 0)->toInt32(exec); + int year = args.at(exec, 0).toInt32(exec); t.year = (year >= 0 && year <= 99) ? year : year - 1900; - t.month = args.at(exec, 1)->toInt32(exec); - t.monthDay = (numArgs >= 3) ? args.at(exec, 2)->toInt32(exec) : 1; - t.hour = args.at(exec, 3)->toInt32(exec); - t.minute = args.at(exec, 4)->toInt32(exec); - t.second = args.at(exec, 5)->toInt32(exec); + t.month = args.at(exec, 1).toInt32(exec); + t.monthDay = (numArgs >= 3) ? args.at(exec, 2).toInt32(exec) : 1; + t.hour = args.at(exec, 3).toInt32(exec); + t.minute = args.at(exec, 4).toInt32(exec); + t.second = args.at(exec, 5).toInt32(exec); t.isDST = -1; - double ms = (numArgs >= 7) ? args.at(exec, 6)->toNumber(exec) : 0; + double ms = (numArgs >= 7) ? args.at(exec, 6).toNumber(exec) : 0; value = gregorianDateTimeToMS(t, ms, false); } } @@ -123,7 +123,7 @@ ConstructType DateConstructor::getConstructData(ConstructData& constructData) } // ECMA 15.9.2 -static JSValue* callDate(ExecState* exec, JSObject*, JSValue*, const ArgList&) +static JSValuePtr callDate(ExecState* exec, JSObject*, JSValuePtr, const ArgList&) { time_t localTime = time(0); tm localTM; @@ -138,37 +138,37 @@ CallType DateConstructor::getCallData(CallData& callData) return CallTypeHost; } -static JSValue* dateParse(ExecState* exec, JSObject*, JSValue*, const ArgList& args) +static JSValuePtr dateParse(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) { - return jsNumber(exec, parseDate(args.at(exec, 0)->toString(exec))); + return jsNumber(exec, parseDate(args.at(exec, 0).toString(exec))); } -static JSValue* dateNow(ExecState* exec, JSObject*, JSValue*, const ArgList&) +static JSValuePtr dateNow(ExecState* exec, JSObject*, JSValuePtr, const ArgList&) { return jsNumber(exec, getCurrentUTCTime()); } -static JSValue* dateUTC(ExecState* exec, JSObject*, JSValue*, const ArgList& args) +static JSValuePtr dateUTC(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) { int n = args.size(); - if (isnan(args.at(exec, 0)->toNumber(exec)) - || isnan(args.at(exec, 1)->toNumber(exec)) - || (n >= 3 && isnan(args.at(exec, 2)->toNumber(exec))) - || (n >= 4 && isnan(args.at(exec, 3)->toNumber(exec))) - || (n >= 5 && isnan(args.at(exec, 4)->toNumber(exec))) - || (n >= 6 && isnan(args.at(exec, 5)->toNumber(exec))) - || (n >= 7 && isnan(args.at(exec, 6)->toNumber(exec)))) + if (isnan(args.at(exec, 0).toNumber(exec)) + || isnan(args.at(exec, 1).toNumber(exec)) + || (n >= 3 && isnan(args.at(exec, 2).toNumber(exec))) + || (n >= 4 && isnan(args.at(exec, 3).toNumber(exec))) + || (n >= 5 && isnan(args.at(exec, 4).toNumber(exec))) + || (n >= 6 && isnan(args.at(exec, 5).toNumber(exec))) + || (n >= 7 && isnan(args.at(exec, 6).toNumber(exec)))) return jsNaN(exec); GregorianDateTime t; - int year = args.at(exec, 0)->toInt32(exec); + int year = args.at(exec, 0).toInt32(exec); t.year = (year >= 0 && year <= 99) ? year : year - 1900; - t.month = args.at(exec, 1)->toInt32(exec); - t.monthDay = (n >= 3) ? args.at(exec, 2)->toInt32(exec) : 1; - t.hour = args.at(exec, 3)->toInt32(exec); - t.minute = args.at(exec, 4)->toInt32(exec); - t.second = args.at(exec, 5)->toInt32(exec); - double ms = (n >= 7) ? args.at(exec, 6)->toNumber(exec) : 0; + t.month = args.at(exec, 1).toInt32(exec); + t.monthDay = (n >= 3) ? args.at(exec, 2).toInt32(exec) : 1; + t.hour = args.at(exec, 3).toInt32(exec); + t.minute = args.at(exec, 4).toInt32(exec); + t.second = args.at(exec, 5).toInt32(exec); + double ms = (n >= 7) ? args.at(exec, 6).toNumber(exec) : 0; return jsNumber(exec, gregorianDateTimeToMS(t, ms, true)); } diff --git a/JavaScriptCore/runtime/DateConstructor.h b/JavaScriptCore/runtime/DateConstructor.h index 1279f82..dcef3cc 100644 --- a/JavaScriptCore/runtime/DateConstructor.h +++ b/JavaScriptCore/runtime/DateConstructor.h @@ -29,7 +29,7 @@ namespace JSC { class DateConstructor : public InternalFunction { public: - DateConstructor(ExecState*, PassRefPtr<StructureID>, StructureID* prototypeFunctionStructure, DatePrototype*); + DateConstructor(ExecState*, PassRefPtr<Structure>, Structure* prototypeFunctionStructure, DatePrototype*); private: virtual ConstructType getConstructData(ConstructData&); diff --git a/JavaScriptCore/runtime/DateInstance.cpp b/JavaScriptCore/runtime/DateInstance.cpp index b38c6ef..8806dec 100644 --- a/JavaScriptCore/runtime/DateInstance.cpp +++ b/JavaScriptCore/runtime/DateInstance.cpp @@ -37,7 +37,7 @@ struct DateInstance::Cache { const ClassInfo DateInstance::info = {"Date", 0, 0, 0}; -DateInstance::DateInstance(PassRefPtr<StructureID> structure) +DateInstance::DateInstance(PassRefPtr<Structure> structure) : JSWrapperObject(structure) , m_cache(0) { diff --git a/JavaScriptCore/runtime/DateInstance.h b/JavaScriptCore/runtime/DateInstance.h index 98f4b64..398f299 100644 --- a/JavaScriptCore/runtime/DateInstance.h +++ b/JavaScriptCore/runtime/DateInstance.h @@ -29,10 +29,10 @@ namespace JSC { class DateInstance : public JSWrapperObject { public: - explicit DateInstance(PassRefPtr<StructureID>); + explicit DateInstance(PassRefPtr<Structure>); virtual ~DateInstance(); - double internalNumber() const { return internalValue()->uncheckedGetNumber(); } + double internalNumber() const { return internalValue().uncheckedGetNumber(); } bool getTime(GregorianDateTime&, int& offset) const; bool getUTCTime(GregorianDateTime&) const; @@ -52,9 +52,9 @@ namespace JSC { mutable Cache* m_cache; }; - DateInstance* asDateInstance(JSValue*); + DateInstance* asDateInstance(JSValuePtr); - inline DateInstance* asDateInstance(JSValue* value) + inline DateInstance* asDateInstance(JSValuePtr value) { ASSERT(asObject(value)->inherits(&DateInstance::info)); return static_cast<DateInstance*>(asObject(value)); diff --git a/JavaScriptCore/runtime/DateMath.cpp b/JavaScriptCore/runtime/DateMath.cpp index ec2a3f6..b452963 100644 --- a/JavaScriptCore/runtime/DateMath.cpp +++ b/JavaScriptCore/runtime/DateMath.cpp @@ -48,6 +48,7 @@ #include <time.h> #include <wtf/ASCIICType.h> #include <wtf/Assertions.h> +#include <wtf/CurrentTime.h> #include <wtf/MathExtras.h> #include <wtf/StringExtras.h> @@ -67,6 +68,10 @@ #include <sys/timeb.h> #endif +#if HAVE(STRINGS_H) +#include <strings.h> +#endif + using namespace WTF; namespace JSC { @@ -287,129 +292,15 @@ double getCurrentUTCTime() return floor(getCurrentUTCTimeWithMicroseconds()); } -#if PLATFORM(WIN_OS) - -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() -{ - struct _timeb timebuffer; - _ftime(&timebuffer); - return timebuffer.time * msPerSecond + timebuffer.millitm; -} - -static bool qpcAvailable() -{ - static bool available; - static bool checked; - - if (checked) - return available; - - available = QueryPerformanceFrequency(&qpcFrequency); - checked = true; - return available; -} - -#endif - +// Returns current time in milliseconds since 1 Jan 1970. double getCurrentUTCTimeWithMicroseconds() { -#if PLATFORM(WIN_OS) - // 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 bool started; - static double syncLowResUTCTime; - static double syncHighResUpTime; - static double lastUTCTime; - - double lowResTime = lowResUTCTime(); - - if (!qpcAvailable()) - return lowResTime; - - 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; - lastUTCTime = utc; -#else - struct timeval tv; - gettimeofday(&tv, 0); - double utc = tv.tv_sec * msPerSecond + tv.tv_usec / 1000.0; -#endif - return utc; + return currentTime() * 1000.0; } void getLocalTime(const time_t* localTime, struct tm* localTM) { -#if COMPILER(MSVC7) || COMPILER(MINGW) +#if COMPILER(MSVC7) || COMPILER(MINGW) || PLATFORM(WIN_CE) *localTM = *localtime(localTime); #elif COMPILER(MSVC) localtime_s(localTM, localTime); @@ -696,6 +587,15 @@ static int findMonth(const char* monthStr) 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; +} + double parseDate(const UString &date) { // This parses a date in the form: @@ -741,10 +641,9 @@ double parseDate(const UString &date) return NaN; // ' 09-Nov-99 23:12:40 GMT' - char *newPosStr; - errno = 0; - long day = strtol(dateString, &newPosStr, 10); - if (errno) + char* newPosStr; + long day; + if (!parseLong(dateString, &newPosStr, 10, &day)) return NaN; dateString = newPosStr; @@ -763,22 +662,20 @@ double parseDate(const UString &date) if (!*++dateString) return NaN; year = day; - month = strtol(dateString, &newPosStr, 10) - 1; - if (errno) + if (!parseLong(dateString, &newPosStr, 10, &month)) return NaN; + month -= 1; dateString = newPosStr; if (*dateString++ != '/' || !*dateString) return NaN; - day = strtol(dateString, &newPosStr, 10); - if (errno) + if (!parseLong(dateString, &newPosStr, 10, &day)) return 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 - day = strtol(dateString, &newPosStr, 10); - if (errno) + if (!parseLong(dateString, &newPosStr, 10, &day)) return NaN; if (day < 1 || day > 31) return NaN; @@ -819,8 +716,7 @@ double parseDate(const UString &date) // '99 23:12:40 GMT' if (year <= 0 && *dateString) { - year = strtol(dateString, &newPosStr, 10); - if (errno) + if (!parseLong(dateString, &newPosStr, 10, &year)) return NaN; } @@ -843,7 +739,7 @@ double parseDate(const UString &date) skipSpacesAndComments(dateString); } - hour = strtol(dateString, &newPosStr, 10); + 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! @@ -862,8 +758,7 @@ double parseDate(const UString &date) if (*dateString++ != ':') return NaN; - minute = strtol(dateString, &newPosStr, 10); - if (errno) + if (!parseLong(dateString, &newPosStr, 10, &minute)) return NaN; dateString = newPosStr; @@ -878,8 +773,7 @@ double parseDate(const UString &date) if (*dateString ==':') { dateString++; - second = strtol(dateString, &newPosStr, 10); - if (errno) + if (!parseLong(dateString, &newPosStr, 10, &second)) return NaN; dateString = newPosStr; @@ -919,8 +813,8 @@ double parseDate(const UString &date) } if (*dateString == '+' || *dateString == '-') { - long o = strtol(dateString, &newPosStr, 10); - if (errno) + long o; + if (!parseLong(dateString, &newPosStr, 10, &o)) return NaN; dateString = newPosStr; @@ -932,8 +826,8 @@ double parseDate(const UString &date) if (*dateString != ':') { offset = ((o / 100) * 60 + (o % 100)) * sgn; } else { // GMT+05:00 - long o2 = strtol(dateString, &newPosStr, 10); - if (errno) + long o2; + if (!parseLong(dateString, &newPosStr, 10, &o2)) return NaN; dateString = newPosStr; offset = (o * 60 + o2) * sgn; @@ -954,8 +848,7 @@ double parseDate(const UString &date) skipSpacesAndComments(dateString); if (*dateString && year == -1) { - year = strtol(dateString, &newPosStr, 10); - if (errno) + if (!parseLong(dateString, &newPosStr, 10, &year)) return NaN; dateString = newPosStr; } diff --git a/JavaScriptCore/runtime/DateMath.h b/JavaScriptCore/runtime/DateMath.h index ab939a7..8a15c80 100644 --- a/JavaScriptCore/runtime/DateMath.h +++ b/JavaScriptCore/runtime/DateMath.h @@ -113,7 +113,7 @@ struct GregorianDateTime : Noncopyable { , year(inTm.tm_year) , isDST(inTm.tm_isdst) { -#if !PLATFORM(WIN_OS) && !PLATFORM(SOLARIS) +#if !PLATFORM(WIN_OS) && !PLATFORM(SOLARIS) && !COMPILER(RVCT) utcOffset = static_cast<int>(inTm.tm_gmtoff); int inZoneSize = strlen(inTm.tm_zone) + 1; @@ -140,7 +140,7 @@ struct GregorianDateTime : Noncopyable { ret.tm_year = year; ret.tm_isdst = isDST; -#if !PLATFORM(WIN_OS) && !PLATFORM(SOLARIS) +#if !PLATFORM(WIN_OS) && !PLATFORM(SOLARIS) && !COMPILER(RVCT) ret.tm_gmtoff = static_cast<long>(utcOffset); ret.tm_zone = timeZone; #endif diff --git a/JavaScriptCore/runtime/DatePrototype.cpp b/JavaScriptCore/runtime/DatePrototype.cpp index a3e792e..b325070 100644 --- a/JavaScriptCore/runtime/DatePrototype.cpp +++ b/JavaScriptCore/runtime/DatePrototype.cpp @@ -58,50 +58,49 @@ namespace JSC { ASSERT_CLASS_FITS_IN_CELL(DatePrototype); -static JSValue* dateProtoFuncGetDate(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* dateProtoFuncGetDay(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* dateProtoFuncGetFullYear(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* dateProtoFuncGetHours(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* dateProtoFuncGetMilliSeconds(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* dateProtoFuncGetMinutes(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* dateProtoFuncGetMonth(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* dateProtoFuncGetSeconds(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* dateProtoFuncGetTime(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* dateProtoFuncGetTimezoneOffset(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* dateProtoFuncGetUTCDate(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* dateProtoFuncGetUTCDay(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* dateProtoFuncGetUTCFullYear(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* dateProtoFuncGetUTCHours(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* dateProtoFuncGetUTCMilliseconds(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* dateProtoFuncGetUTCMinutes(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* dateProtoFuncGetUTCMonth(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* dateProtoFuncGetUTCSeconds(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* dateProtoFuncGetYear(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* dateProtoFuncSetDate(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* dateProtoFuncSetFullYear(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* dateProtoFuncSetHours(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* dateProtoFuncSetMilliSeconds(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* dateProtoFuncSetMinutes(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* dateProtoFuncSetMonth(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* dateProtoFuncSetSeconds(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* dateProtoFuncSetTime(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* dateProtoFuncSetUTCDate(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* dateProtoFuncSetUTCFullYear(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* dateProtoFuncSetUTCHours(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* dateProtoFuncSetUTCMilliseconds(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* dateProtoFuncSetUTCMinutes(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* dateProtoFuncSetUTCMonth(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* dateProtoFuncSetUTCSeconds(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* dateProtoFuncSetYear(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* dateProtoFuncToDateString(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* dateProtoFuncToGMTString(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* dateProtoFuncToLocaleDateString(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* dateProtoFuncToLocaleString(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* dateProtoFuncToLocaleTimeString(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* dateProtoFuncToString(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* dateProtoFuncToTimeString(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* dateProtoFuncToUTCString(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* dateProtoFuncValueOf(ExecState*, JSObject*, JSValue*, const ArgList&); +static JSValuePtr dateProtoFuncGetDate(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr dateProtoFuncGetDay(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr dateProtoFuncGetFullYear(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr dateProtoFuncGetHours(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr dateProtoFuncGetMilliSeconds(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr dateProtoFuncGetMinutes(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr dateProtoFuncGetMonth(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr dateProtoFuncGetSeconds(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr dateProtoFuncGetTime(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr dateProtoFuncGetTimezoneOffset(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr dateProtoFuncGetUTCDate(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr dateProtoFuncGetUTCDay(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr dateProtoFuncGetUTCFullYear(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr dateProtoFuncGetUTCHours(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr dateProtoFuncGetUTCMilliseconds(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr dateProtoFuncGetUTCMinutes(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr dateProtoFuncGetUTCMonth(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr dateProtoFuncGetUTCSeconds(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr dateProtoFuncGetYear(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr dateProtoFuncSetDate(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr dateProtoFuncSetFullYear(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr dateProtoFuncSetHours(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr dateProtoFuncSetMilliSeconds(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr dateProtoFuncSetMinutes(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr dateProtoFuncSetMonth(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr dateProtoFuncSetSeconds(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr dateProtoFuncSetTime(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr dateProtoFuncSetUTCDate(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr dateProtoFuncSetUTCFullYear(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr dateProtoFuncSetUTCHours(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr dateProtoFuncSetUTCMilliseconds(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr dateProtoFuncSetUTCMinutes(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr dateProtoFuncSetUTCMonth(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr dateProtoFuncSetUTCSeconds(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr dateProtoFuncSetYear(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr dateProtoFuncToDateString(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr dateProtoFuncToGMTString(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr dateProtoFuncToLocaleDateString(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr dateProtoFuncToLocaleString(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr dateProtoFuncToLocaleTimeString(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr dateProtoFuncToString(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr dateProtoFuncToTimeString(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr dateProtoFuncToUTCString(ExecState*, JSObject*, JSValuePtr, const ArgList&); } @@ -109,8 +108,13 @@ static JSValue* dateProtoFuncValueOf(ExecState*, JSObject*, JSValue*, const ArgL namespace JSC { +enum LocaleDateTimeFormat { LocaleDateAndTime, LocaleDate, LocaleTime }; + #if PLATFORM(MAC) +// FIXME: Since this is superior to the strftime-based version, why limit this to PLATFORM(MAC)? +// Instead we should consider using this whenever PLATFORM(CF) is true. + static CFDateFormatterStyle styleFromArgString(const UString& string, CFDateFormatterStyle defaultStyle) { if (string == "short") @@ -124,24 +128,24 @@ static CFDateFormatterStyle styleFromArgString(const UString& string, CFDateForm return defaultStyle; } -static UString formatLocaleDate(ExecState* exec, double time, bool includeDate, bool includeTime, const ArgList& args) +static JSCell* formatLocaleDate(ExecState* exec, DateInstance*, double timeInMilliseconds, LocaleDateTimeFormat format, const ArgList& args) { - CFDateFormatterStyle dateStyle = (includeDate ? kCFDateFormatterLongStyle : kCFDateFormatterNoStyle); - CFDateFormatterStyle timeStyle = (includeTime ? kCFDateFormatterLongStyle : kCFDateFormatterNoStyle); + CFDateFormatterStyle dateStyle = (format != LocaleTime ? kCFDateFormatterLongStyle : kCFDateFormatterNoStyle); + CFDateFormatterStyle timeStyle = (format != LocaleDate ? kCFDateFormatterLongStyle : kCFDateFormatterNoStyle); bool useCustomFormat = false; UString customFormatString; - UString arg0String = args.at(exec, 0)->toString(exec); - if (arg0String == "custom" && !args.at(exec, 1)->isUndefined()) { + UString arg0String = args.at(exec, 0).toString(exec); + if (arg0String == "custom" && !args.at(exec, 1).isUndefined()) { useCustomFormat = true; - customFormatString = args.at(exec, 1)->toString(exec); - } else if (includeDate && includeTime && !args.at(exec, 1)->isUndefined()) { + customFormatString = args.at(exec, 1).toString(exec); + } else if (format == LocaleDateAndTime && !args.at(exec, 1).isUndefined()) { dateStyle = styleFromArgString(arg0String, dateStyle); - timeStyle = styleFromArgString(args.at(exec, 1)->toString(exec), timeStyle); - } else if (includeDate && !args.at(exec, 0)->isUndefined()) + timeStyle = styleFromArgString(args.at(exec, 1).toString(exec), timeStyle); + } else if (format != LocaleTime && !args.at(exec, 0).isUndefined()) dateStyle = styleFromArgString(arg0String, dateStyle); - else if (includeTime && !args.at(exec, 0)->isUndefined()) + else if (format != LocaleDate && !args.at(exec, 0).isUndefined()) timeStyle = styleFromArgString(arg0String, timeStyle); CFLocaleRef locale = CFLocaleCopyCurrent(); @@ -149,12 +153,12 @@ static UString formatLocaleDate(ExecState* exec, double time, bool includeDate, CFRelease(locale); if (useCustomFormat) { - CFStringRef customFormatCFString = CFStringCreateWithCharacters(0, (UniChar *)customFormatString.data(), customFormatString.size()); + CFStringRef customFormatCFString = CFStringCreateWithCharacters(0, customFormatString.data(), customFormatString.size()); CFDateFormatterSetFormat(formatter, customFormatCFString); CFRelease(customFormatCFString); } - CFStringRef string = CFDateFormatterCreateStringWithAbsoluteTime(0, formatter, time - kCFAbsoluteTimeIntervalSince1970); + CFStringRef string = CFDateFormatterCreateStringWithAbsoluteTime(0, formatter, floor(timeInMilliseconds / msPerSecond) - kCFAbsoluteTimeIntervalSince1970); CFRelease(formatter); @@ -166,20 +170,18 @@ static UString formatLocaleDate(ExecState* exec, double time, bool includeDate, ASSERT(length <= bufferLength); if (length > bufferLength) length = bufferLength; - CFStringGetCharacters(string, CFRangeMake(0, length), reinterpret_cast<UniChar *>(buffer)); + CFStringGetCharacters(string, CFRangeMake(0, length), buffer); CFRelease(string); - return UString(buffer, length); + return jsNontrivialString(exec, UString(buffer, length)); } -#else +#else // !PLATFORM(MAC) -enum LocaleDateTimeFormat { LocaleDateAndTime, LocaleDate, LocaleTime }; - -static JSCell* formatLocaleDate(ExecState* exec, const GregorianDateTime& gdt, const LocaleDateTimeFormat format) +static JSCell* formatLocaleDate(ExecState* exec, const GregorianDateTime& gdt, LocaleDateTimeFormat format) { - static const char* formatStrings[] = {"%#c", "%#x", "%X"}; + static const char* const formatStrings[] = { "%#c", "%#x", "%X" }; // Offset year if needed struct tm localTM = gdt; @@ -211,7 +213,15 @@ static JSCell* formatLocaleDate(ExecState* exec, const GregorianDateTime& gdt, c return jsNontrivialString(exec, timebuffer); } -#endif // PLATFORM(WIN_OS) +static JSCell* formatLocaleDate(ExecState* exec, DateInstance* dateObject, double timeInMilliseconds, LocaleDateTimeFormat format, const ArgList&) +{ + GregorianDateTime gregorianDateTime; + const bool notUTC = false; + dateObject->msToGregorianDateTime(timeInMilliseconds, notUTC, gregorianDateTime); + return formatLocaleDate(exec, gregorianDateTime, format); +} + +#endif // !PLATFORM(MAC) // Converts a list of arguments sent to a Date member function into milliseconds, updating // ms (representing milliseconds) and t (representing the rest of the date structure) appropriately. @@ -231,19 +241,19 @@ static bool fillStructuresUsingTimeArgs(ExecState* exec, const ArgList& args, in // hours if (maxArgs >= 4 && idx < numArgs) { t->hour = 0; - milliseconds += args.at(exec, idx++)->toInt32(exec, ok) * msPerHour; + milliseconds += args.at(exec, idx++).toInt32(exec, ok) * msPerHour; } // minutes if (maxArgs >= 3 && idx < numArgs && ok) { t->minute = 0; - milliseconds += args.at(exec, idx++)->toInt32(exec, ok) * msPerMinute; + milliseconds += args.at(exec, idx++).toInt32(exec, ok) * msPerMinute; } // seconds if (maxArgs >= 2 && idx < numArgs && ok) { t->second = 0; - milliseconds += args.at(exec, idx++)->toInt32(exec, ok) * msPerSecond; + milliseconds += args.at(exec, idx++).toInt32(exec, ok) * msPerSecond; } if (!ok) @@ -251,7 +261,7 @@ static bool fillStructuresUsingTimeArgs(ExecState* exec, const ArgList& args, in // milliseconds if (idx < numArgs) { - double millis = args.at(exec, idx)->toNumber(exec); + double millis = args.at(exec, idx).toNumber(exec); ok = isfinite(millis); milliseconds += millis; } else @@ -277,16 +287,16 @@ static bool fillStructuresUsingDateArgs(ExecState *exec, const ArgList& args, in // years if (maxArgs >= 3 && idx < numArgs) - t->year = args.at(exec, idx++)->toInt32(exec, ok) - 1900; + t->year = args.at(exec, idx++).toInt32(exec, ok) - 1900; // months if (maxArgs >= 2 && idx < numArgs && ok) - t->month = args.at(exec, idx++)->toInt32(exec, ok); + t->month = args.at(exec, idx++).toInt32(exec, ok); // days if (idx < numArgs && ok) { t->monthDay = 0; - *ms += args.at(exec, idx)->toInt32(exec, ok) * msPerDay; + *ms += args.at(exec, idx).toInt32(exec, ok) * msPerDay; } return ok; @@ -295,7 +305,6 @@ static bool fillStructuresUsingDateArgs(ExecState *exec, const ArgList& args, in const ClassInfo DatePrototype::info = {"Date", &DateInstance::info, 0, ExecState::dateTable}; /* Source for DatePrototype.lut.h - FIXME: We could use templates to simplify the UTC variants. @begin dateTable toString dateProtoFuncToString DontEnum|Function 0 toUTCString dateProtoFuncToUTCString DontEnum|Function 0 @@ -304,7 +313,7 @@ const ClassInfo DatePrototype::info = {"Date", &DateInstance::info, 0, ExecState toLocaleString dateProtoFuncToLocaleString DontEnum|Function 0 toLocaleDateString dateProtoFuncToLocaleDateString DontEnum|Function 0 toLocaleTimeString dateProtoFuncToLocaleTimeString DontEnum|Function 0 - valueOf dateProtoFuncValueOf DontEnum|Function 0 + valueOf dateProtoFuncGetTime DontEnum|Function 0 getTime dateProtoFuncGetTime DontEnum|Function 0 getFullYear dateProtoFuncGetFullYear DontEnum|Function 0 getUTCFullYear dateProtoFuncGetUTCFullYear DontEnum|Function 0 @@ -343,9 +352,10 @@ const ClassInfo DatePrototype::info = {"Date", &DateInstance::info, 0, ExecState getYear dateProtoFuncGetYear DontEnum|Function 0 @end */ + // ECMA 15.9.4 -DatePrototype::DatePrototype(ExecState* exec, PassRefPtr<StructureID> structure) +DatePrototype::DatePrototype(ExecState* exec, PassRefPtr<Structure> structure) : DateInstance(structure) { setInternalValue(jsNaN(exec)); @@ -359,9 +369,9 @@ bool DatePrototype::getOwnPropertySlot(ExecState* exec, const Identifier& proper // Functions -JSValue* dateProtoFuncToString(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&) +JSValuePtr dateProtoFuncToString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) { - if (!thisValue->isObject(&DateInstance::info)) + if (!thisValue.isObject(&DateInstance::info)) return throwError(exec, TypeError); const bool utc = false; @@ -376,9 +386,9 @@ JSValue* dateProtoFuncToString(ExecState* exec, JSObject*, JSValue* thisValue, c return jsNontrivialString(exec, formatDate(t) + " " + formatTime(t, utc)); } -JSValue* dateProtoFuncToUTCString(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&) +JSValuePtr dateProtoFuncToUTCString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) { - if (!thisValue->isObject(&DateInstance::info)) + if (!thisValue.isObject(&DateInstance::info)) return throwError(exec, TypeError); const bool utc = true; @@ -393,9 +403,9 @@ JSValue* dateProtoFuncToUTCString(ExecState* exec, JSObject*, JSValue* thisValue return jsNontrivialString(exec, formatDateUTCVariant(t) + " " + formatTime(t, utc)); } -JSValue* dateProtoFuncToDateString(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&) +JSValuePtr dateProtoFuncToDateString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) { - if (!thisValue->isObject(&DateInstance::info)) + if (!thisValue.isObject(&DateInstance::info)) return throwError(exec, TypeError); const bool utc = false; @@ -410,9 +420,9 @@ JSValue* dateProtoFuncToDateString(ExecState* exec, JSObject*, JSValue* thisValu return jsNontrivialString(exec, formatDate(t)); } -JSValue* dateProtoFuncToTimeString(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&) +JSValuePtr dateProtoFuncToTimeString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) { - if (!thisValue->isObject(&DateInstance::info)) + if (!thisValue.isObject(&DateInstance::info)) return throwError(exec, TypeError); const bool utc = false; @@ -427,9 +437,9 @@ JSValue* dateProtoFuncToTimeString(ExecState* exec, JSObject*, JSValue* thisValu return jsNontrivialString(exec, formatTime(t, utc)); } -JSValue* dateProtoFuncToLocaleString(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) +JSValuePtr dateProtoFuncToLocaleString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) { - if (!thisValue->isObject(&DateInstance::info)) + if (!thisValue.isObject(&DateInstance::info)) return throwError(exec, TypeError); DateInstance* thisDateObj = asDateInstance(thisValue); @@ -437,23 +447,12 @@ JSValue* dateProtoFuncToLocaleString(ExecState* exec, JSObject*, JSValue* thisVa if (isnan(milli)) return jsNontrivialString(exec, "Invalid Date"); -#if PLATFORM(MAC) - double secs = floor(milli / msPerSecond); - return jsNontrivialString(exec, formatLocaleDate(exec, secs, true, true, args)); -#else - UNUSED_PARAM(args); - - const bool utc = false; - - GregorianDateTime t; - thisDateObj->msToGregorianDateTime(milli, utc, t); - return formatLocaleDate(exec, t, LocaleDateAndTime); -#endif + return formatLocaleDate(exec, thisDateObj, milli, LocaleDateAndTime, args); } -JSValue* dateProtoFuncToLocaleDateString(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) +JSValuePtr dateProtoFuncToLocaleDateString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) { - if (!thisValue->isObject(&DateInstance::info)) + if (!thisValue.isObject(&DateInstance::info)) return throwError(exec, TypeError); DateInstance* thisDateObj = asDateInstance(thisValue); @@ -461,23 +460,12 @@ JSValue* dateProtoFuncToLocaleDateString(ExecState* exec, JSObject*, JSValue* th if (isnan(milli)) return jsNontrivialString(exec, "Invalid Date"); -#if PLATFORM(MAC) - double secs = floor(milli / msPerSecond); - return jsNontrivialString(exec, formatLocaleDate(exec, secs, true, false, args)); -#else - UNUSED_PARAM(args); - - const bool utc = false; - - GregorianDateTime t; - thisDateObj->msToGregorianDateTime(milli, utc, t); - return formatLocaleDate(exec, t, LocaleDate); -#endif + return formatLocaleDate(exec, thisDateObj, milli, LocaleDate, args); } -JSValue* dateProtoFuncToLocaleTimeString(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) +JSValuePtr dateProtoFuncToLocaleTimeString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) { - if (!thisValue->isObject(&DateInstance::info)) + if (!thisValue.isObject(&DateInstance::info)) return throwError(exec, TypeError); DateInstance* thisDateObj = asDateInstance(thisValue); @@ -485,36 +473,12 @@ JSValue* dateProtoFuncToLocaleTimeString(ExecState* exec, JSObject*, JSValue* th if (isnan(milli)) return jsNontrivialString(exec, "Invalid Date"); -#if PLATFORM(MAC) - double secs = floor(milli / msPerSecond); - return jsNontrivialString(exec, formatLocaleDate(exec, secs, false, true, args)); -#else - UNUSED_PARAM(args); - - const bool utc = false; - - GregorianDateTime t; - thisDateObj->msToGregorianDateTime(milli, utc, t); - return formatLocaleDate(exec, t, LocaleTime); -#endif -} - -JSValue* dateProtoFuncValueOf(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&) -{ - if (!thisValue->isObject(&DateInstance::info)) - return throwError(exec, TypeError); - - DateInstance* thisDateObj = asDateInstance(thisValue); - double milli = thisDateObj->internalNumber(); - if (isnan(milli)) - return jsNaN(exec); - - return jsNumber(exec, milli); + return formatLocaleDate(exec, thisDateObj, milli, LocaleTime, args); } -JSValue* dateProtoFuncGetTime(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&) +JSValuePtr dateProtoFuncGetTime(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) { - if (!thisValue->isObject(&DateInstance::info)) + if (!thisValue.isObject(&DateInstance::info)) return throwError(exec, TypeError); DateInstance* thisDateObj = asDateInstance(thisValue); @@ -525,9 +489,9 @@ JSValue* dateProtoFuncGetTime(ExecState* exec, JSObject*, JSValue* thisValue, co return jsNumber(exec, milli); } -JSValue* dateProtoFuncGetFullYear(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&) +JSValuePtr dateProtoFuncGetFullYear(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) { - if (!thisValue->isObject(&DateInstance::info)) + if (!thisValue.isObject(&DateInstance::info)) return throwError(exec, TypeError); const bool utc = false; @@ -542,9 +506,9 @@ JSValue* dateProtoFuncGetFullYear(ExecState* exec, JSObject*, JSValue* thisValue return jsNumber(exec, 1900 + t.year); } -JSValue* dateProtoFuncGetUTCFullYear(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&) +JSValuePtr dateProtoFuncGetUTCFullYear(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) { - if (!thisValue->isObject(&DateInstance::info)) + if (!thisValue.isObject(&DateInstance::info)) return throwError(exec, TypeError); const bool utc = true; @@ -559,9 +523,9 @@ JSValue* dateProtoFuncGetUTCFullYear(ExecState* exec, JSObject*, JSValue* thisVa return jsNumber(exec, 1900 + t.year); } -JSValue* dateProtoFuncToGMTString(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&) +JSValuePtr dateProtoFuncToGMTString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) { - if (!thisValue->isObject(&DateInstance::info)) + if (!thisValue.isObject(&DateInstance::info)) return throwError(exec, TypeError); const bool utc = true; @@ -576,9 +540,9 @@ JSValue* dateProtoFuncToGMTString(ExecState* exec, JSObject*, JSValue* thisValue return jsNontrivialString(exec, formatDateUTCVariant(t) + " " + formatTime(t, utc)); } -JSValue* dateProtoFuncGetMonth(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&) +JSValuePtr dateProtoFuncGetMonth(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) { - if (!thisValue->isObject(&DateInstance::info)) + if (!thisValue.isObject(&DateInstance::info)) return throwError(exec, TypeError); const bool utc = false; @@ -593,9 +557,9 @@ JSValue* dateProtoFuncGetMonth(ExecState* exec, JSObject*, JSValue* thisValue, c return jsNumber(exec, t.month); } -JSValue* dateProtoFuncGetUTCMonth(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&) +JSValuePtr dateProtoFuncGetUTCMonth(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) { - if (!thisValue->isObject(&DateInstance::info)) + if (!thisValue.isObject(&DateInstance::info)) return throwError(exec, TypeError); const bool utc = true; @@ -610,9 +574,9 @@ JSValue* dateProtoFuncGetUTCMonth(ExecState* exec, JSObject*, JSValue* thisValue return jsNumber(exec, t.month); } -JSValue* dateProtoFuncGetDate(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&) +JSValuePtr dateProtoFuncGetDate(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) { - if (!thisValue->isObject(&DateInstance::info)) + if (!thisValue.isObject(&DateInstance::info)) return throwError(exec, TypeError); const bool utc = false; @@ -627,9 +591,9 @@ JSValue* dateProtoFuncGetDate(ExecState* exec, JSObject*, JSValue* thisValue, co return jsNumber(exec, t.monthDay); } -JSValue* dateProtoFuncGetUTCDate(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&) +JSValuePtr dateProtoFuncGetUTCDate(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) { - if (!thisValue->isObject(&DateInstance::info)) + if (!thisValue.isObject(&DateInstance::info)) return throwError(exec, TypeError); const bool utc = true; @@ -644,9 +608,9 @@ JSValue* dateProtoFuncGetUTCDate(ExecState* exec, JSObject*, JSValue* thisValue, return jsNumber(exec, t.monthDay); } -JSValue* dateProtoFuncGetDay(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&) +JSValuePtr dateProtoFuncGetDay(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) { - if (!thisValue->isObject(&DateInstance::info)) + if (!thisValue.isObject(&DateInstance::info)) return throwError(exec, TypeError); const bool utc = false; @@ -661,9 +625,9 @@ JSValue* dateProtoFuncGetDay(ExecState* exec, JSObject*, JSValue* thisValue, con return jsNumber(exec, t.weekDay); } -JSValue* dateProtoFuncGetUTCDay(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&) +JSValuePtr dateProtoFuncGetUTCDay(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) { - if (!thisValue->isObject(&DateInstance::info)) + if (!thisValue.isObject(&DateInstance::info)) return throwError(exec, TypeError); const bool utc = true; @@ -678,9 +642,9 @@ JSValue* dateProtoFuncGetUTCDay(ExecState* exec, JSObject*, JSValue* thisValue, return jsNumber(exec, t.weekDay); } -JSValue* dateProtoFuncGetHours(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&) +JSValuePtr dateProtoFuncGetHours(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) { - if (!thisValue->isObject(&DateInstance::info)) + if (!thisValue.isObject(&DateInstance::info)) return throwError(exec, TypeError); const bool utc = false; @@ -695,9 +659,9 @@ JSValue* dateProtoFuncGetHours(ExecState* exec, JSObject*, JSValue* thisValue, c return jsNumber(exec, t.hour); } -JSValue* dateProtoFuncGetUTCHours(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&) +JSValuePtr dateProtoFuncGetUTCHours(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) { - if (!thisValue->isObject(&DateInstance::info)) + if (!thisValue.isObject(&DateInstance::info)) return throwError(exec, TypeError); const bool utc = true; @@ -712,9 +676,9 @@ JSValue* dateProtoFuncGetUTCHours(ExecState* exec, JSObject*, JSValue* thisValue return jsNumber(exec, t.hour); } -JSValue* dateProtoFuncGetMinutes(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&) +JSValuePtr dateProtoFuncGetMinutes(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) { - if (!thisValue->isObject(&DateInstance::info)) + if (!thisValue.isObject(&DateInstance::info)) return throwError(exec, TypeError); const bool utc = false; @@ -729,9 +693,9 @@ JSValue* dateProtoFuncGetMinutes(ExecState* exec, JSObject*, JSValue* thisValue, return jsNumber(exec, t.minute); } -JSValue* dateProtoFuncGetUTCMinutes(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&) +JSValuePtr dateProtoFuncGetUTCMinutes(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) { - if (!thisValue->isObject(&DateInstance::info)) + if (!thisValue.isObject(&DateInstance::info)) return throwError(exec, TypeError); const bool utc = true; @@ -746,9 +710,9 @@ JSValue* dateProtoFuncGetUTCMinutes(ExecState* exec, JSObject*, JSValue* thisVal return jsNumber(exec, t.minute); } -JSValue* dateProtoFuncGetSeconds(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&) +JSValuePtr dateProtoFuncGetSeconds(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) { - if (!thisValue->isObject(&DateInstance::info)) + if (!thisValue.isObject(&DateInstance::info)) return throwError(exec, TypeError); const bool utc = false; @@ -763,9 +727,9 @@ JSValue* dateProtoFuncGetSeconds(ExecState* exec, JSObject*, JSValue* thisValue, return jsNumber(exec, t.second); } -JSValue* dateProtoFuncGetUTCSeconds(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&) +JSValuePtr dateProtoFuncGetUTCSeconds(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) { - if (!thisValue->isObject(&DateInstance::info)) + if (!thisValue.isObject(&DateInstance::info)) return throwError(exec, TypeError); const bool utc = true; @@ -780,9 +744,9 @@ JSValue* dateProtoFuncGetUTCSeconds(ExecState* exec, JSObject*, JSValue* thisVal return jsNumber(exec, t.second); } -JSValue* dateProtoFuncGetMilliSeconds(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&) +JSValuePtr dateProtoFuncGetMilliSeconds(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) { - if (!thisValue->isObject(&DateInstance::info)) + if (!thisValue.isObject(&DateInstance::info)) return throwError(exec, TypeError); DateInstance* thisDateObj = asDateInstance(thisValue); @@ -795,9 +759,9 @@ JSValue* dateProtoFuncGetMilliSeconds(ExecState* exec, JSObject*, JSValue* thisV return jsNumber(exec, ms); } -JSValue* dateProtoFuncGetUTCMilliseconds(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&) +JSValuePtr dateProtoFuncGetUTCMilliseconds(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) { - if (!thisValue->isObject(&DateInstance::info)) + if (!thisValue.isObject(&DateInstance::info)) return throwError(exec, TypeError); DateInstance* thisDateObj = asDateInstance(thisValue); @@ -810,9 +774,9 @@ JSValue* dateProtoFuncGetUTCMilliseconds(ExecState* exec, JSObject*, JSValue* th return jsNumber(exec, ms); } -JSValue* dateProtoFuncGetTimezoneOffset(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&) +JSValuePtr dateProtoFuncGetTimezoneOffset(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) { - if (!thisValue->isObject(&DateInstance::info)) + if (!thisValue.isObject(&DateInstance::info)) return throwError(exec, TypeError); const bool utc = false; @@ -827,29 +791,29 @@ JSValue* dateProtoFuncGetTimezoneOffset(ExecState* exec, JSObject*, JSValue* thi return jsNumber(exec, -gmtoffset(t) / minutesPerHour); } -JSValue* dateProtoFuncSetTime(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) +JSValuePtr dateProtoFuncSetTime(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) { - if (!thisValue->isObject(&DateInstance::info)) + if (!thisValue.isObject(&DateInstance::info)) return throwError(exec, TypeError); DateInstance* thisDateObj = asDateInstance(thisValue); - double milli = timeClip(args.at(exec, 0)->toNumber(exec)); - JSValue* result = jsNumber(exec, milli); + double milli = timeClip(args.at(exec, 0).toNumber(exec)); + JSValuePtr result = jsNumber(exec, milli); thisDateObj->setInternalValue(result); return result; } -static JSValue* setNewValueFromTimeArgs(ExecState* exec, JSValue* thisValue, const ArgList& args, int numArgsToUse, bool inputIsUTC) +static JSValuePtr setNewValueFromTimeArgs(ExecState* exec, JSValuePtr thisValue, const ArgList& args, int numArgsToUse, bool inputIsUTC) { - if (!thisValue->isObject(&DateInstance::info)) + if (!thisValue.isObject(&DateInstance::info)) return throwError(exec, TypeError); DateInstance* thisDateObj = asDateInstance(thisValue); double milli = thisDateObj->internalNumber(); if (args.isEmpty() || isnan(milli)) { - JSValue* result = jsNaN(exec); + JSValuePtr result = jsNaN(exec); thisDateObj->setInternalValue(result); return result; } @@ -861,24 +825,24 @@ static JSValue* setNewValueFromTimeArgs(ExecState* exec, JSValue* thisValue, con thisDateObj->msToGregorianDateTime(milli, inputIsUTC, t); if (!fillStructuresUsingTimeArgs(exec, args, numArgsToUse, &ms, &t)) { - JSValue* result = jsNaN(exec); + JSValuePtr result = jsNaN(exec); thisDateObj->setInternalValue(result); return result; } - JSValue* result = jsNumber(exec, gregorianDateTimeToMS(t, ms, inputIsUTC)); + JSValuePtr result = jsNumber(exec, gregorianDateTimeToMS(t, ms, inputIsUTC)); thisDateObj->setInternalValue(result); return result; } -static JSValue* setNewValueFromDateArgs(ExecState* exec, JSValue* thisValue, const ArgList& args, int numArgsToUse, bool inputIsUTC) +static JSValuePtr setNewValueFromDateArgs(ExecState* exec, JSValuePtr thisValue, const ArgList& args, int numArgsToUse, bool inputIsUTC) { - if (!thisValue->isObject(&DateInstance::info)) + if (!thisValue.isObject(&DateInstance::info)) return throwError(exec, TypeError); DateInstance* thisDateObj = asDateInstance(thisValue); if (args.isEmpty()) { - JSValue* result = jsNaN(exec); + JSValuePtr result = jsNaN(exec); thisDateObj->setInternalValue(result); return result; } @@ -898,110 +862,110 @@ static JSValue* setNewValueFromDateArgs(ExecState* exec, JSValue* thisValue, con } if (!fillStructuresUsingDateArgs(exec, args, numArgsToUse, &ms, &t)) { - JSValue* result = jsNaN(exec); + JSValuePtr result = jsNaN(exec); thisDateObj->setInternalValue(result); return result; } - JSValue* result = jsNumber(exec, gregorianDateTimeToMS(t, ms, inputIsUTC)); + JSValuePtr result = jsNumber(exec, gregorianDateTimeToMS(t, ms, inputIsUTC)); thisDateObj->setInternalValue(result); return result; } -JSValue* dateProtoFuncSetMilliSeconds(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) +JSValuePtr dateProtoFuncSetMilliSeconds(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) { const bool inputIsUTC = false; return setNewValueFromTimeArgs(exec, thisValue, args, 1, inputIsUTC); } -JSValue* dateProtoFuncSetUTCMilliseconds(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) +JSValuePtr dateProtoFuncSetUTCMilliseconds(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) { const bool inputIsUTC = true; return setNewValueFromTimeArgs(exec, thisValue, args, 1, inputIsUTC); } -JSValue* dateProtoFuncSetSeconds(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) +JSValuePtr dateProtoFuncSetSeconds(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) { const bool inputIsUTC = false; return setNewValueFromTimeArgs(exec, thisValue, args, 2, inputIsUTC); } -JSValue* dateProtoFuncSetUTCSeconds(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) +JSValuePtr dateProtoFuncSetUTCSeconds(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) { const bool inputIsUTC = true; return setNewValueFromTimeArgs(exec, thisValue, args, 2, inputIsUTC); } -JSValue* dateProtoFuncSetMinutes(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) +JSValuePtr dateProtoFuncSetMinutes(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) { const bool inputIsUTC = false; return setNewValueFromTimeArgs(exec, thisValue, args, 3, inputIsUTC); } -JSValue* dateProtoFuncSetUTCMinutes(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) +JSValuePtr dateProtoFuncSetUTCMinutes(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) { const bool inputIsUTC = true; return setNewValueFromTimeArgs(exec, thisValue, args, 3, inputIsUTC); } -JSValue* dateProtoFuncSetHours(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) +JSValuePtr dateProtoFuncSetHours(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) { const bool inputIsUTC = false; return setNewValueFromTimeArgs(exec, thisValue, args, 4, inputIsUTC); } -JSValue* dateProtoFuncSetUTCHours(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) +JSValuePtr dateProtoFuncSetUTCHours(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) { const bool inputIsUTC = true; return setNewValueFromTimeArgs(exec, thisValue, args, 4, inputIsUTC); } -JSValue* dateProtoFuncSetDate(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) +JSValuePtr dateProtoFuncSetDate(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) { const bool inputIsUTC = false; return setNewValueFromDateArgs(exec, thisValue, args, 1, inputIsUTC); } -JSValue* dateProtoFuncSetUTCDate(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) +JSValuePtr dateProtoFuncSetUTCDate(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) { const bool inputIsUTC = true; return setNewValueFromDateArgs(exec, thisValue, args, 1, inputIsUTC); } -JSValue* dateProtoFuncSetMonth(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) +JSValuePtr dateProtoFuncSetMonth(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) { const bool inputIsUTC = false; return setNewValueFromDateArgs(exec, thisValue, args, 2, inputIsUTC); } -JSValue* dateProtoFuncSetUTCMonth(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) +JSValuePtr dateProtoFuncSetUTCMonth(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) { const bool inputIsUTC = true; return setNewValueFromDateArgs(exec, thisValue, args, 2, inputIsUTC); } -JSValue* dateProtoFuncSetFullYear(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) +JSValuePtr dateProtoFuncSetFullYear(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) { const bool inputIsUTC = false; return setNewValueFromDateArgs(exec, thisValue, args, 3, inputIsUTC); } -JSValue* dateProtoFuncSetUTCFullYear(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) +JSValuePtr dateProtoFuncSetUTCFullYear(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) { const bool inputIsUTC = true; return setNewValueFromDateArgs(exec, thisValue, args, 3, inputIsUTC); } -JSValue* dateProtoFuncSetYear(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) +JSValuePtr dateProtoFuncSetYear(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) { - if (!thisValue->isObject(&DateInstance::info)) + if (!thisValue.isObject(&DateInstance::info)) return throwError(exec, TypeError); const bool utc = false; DateInstance* thisDateObj = asDateInstance(thisValue); if (args.isEmpty()) { - JSValue* result = jsNaN(exec); + JSValuePtr result = jsNaN(exec); thisDateObj->setInternalValue(result); return result; } @@ -1021,22 +985,22 @@ JSValue* dateProtoFuncSetYear(ExecState* exec, JSObject*, JSValue* thisValue, co } bool ok = true; - int32_t year = args.at(exec, 0)->toInt32(exec, ok); + int32_t year = args.at(exec, 0).toInt32(exec, ok); if (!ok) { - JSValue* result = jsNaN(exec); + JSValuePtr result = jsNaN(exec); thisDateObj->setInternalValue(result); return result; } t.year = (year > 99 || year < 0) ? year - 1900 : year; - JSValue* result = jsNumber(exec, gregorianDateTimeToMS(t, ms, utc)); + JSValuePtr result = jsNumber(exec, gregorianDateTimeToMS(t, ms, utc)); thisDateObj->setInternalValue(result); return result; } -JSValue* dateProtoFuncGetYear(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&) +JSValuePtr dateProtoFuncGetYear(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) { - if (!thisValue->isObject(&DateInstance::info)) + if (!thisValue.isObject(&DateInstance::info)) return throwError(exec, TypeError); const bool utc = false; diff --git a/JavaScriptCore/runtime/DatePrototype.h b/JavaScriptCore/runtime/DatePrototype.h index 500b40d..a6bbdf2 100644 --- a/JavaScriptCore/runtime/DatePrototype.h +++ b/JavaScriptCore/runtime/DatePrototype.h @@ -29,16 +29,16 @@ namespace JSC { class DatePrototype : public DateInstance { public: - DatePrototype(ExecState*, PassRefPtr<StructureID>); + DatePrototype(ExecState*, PassRefPtr<Structure>); virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&); virtual const ClassInfo* classInfo() const { return &info; } static const ClassInfo info; - static PassRefPtr<StructureID> createStructureID(JSValue* prototype) + static PassRefPtr<Structure> createStructure(JSValuePtr prototype) { - return StructureID::create(prototype, TypeInfo(ObjectType)); + return Structure::create(prototype, TypeInfo(ObjectType)); } }; diff --git a/JavaScriptCore/runtime/ErrorConstructor.cpp b/JavaScriptCore/runtime/ErrorConstructor.cpp index 3c83fd4..5cc0df0 100644 --- a/JavaScriptCore/runtime/ErrorConstructor.cpp +++ b/JavaScriptCore/runtime/ErrorConstructor.cpp @@ -29,7 +29,7 @@ namespace JSC { ASSERT_CLASS_FITS_IN_CELL(ErrorConstructor); -ErrorConstructor::ErrorConstructor(ExecState* exec, PassRefPtr<StructureID> structure, ErrorPrototype* errorPrototype) +ErrorConstructor::ErrorConstructor(ExecState* exec, PassRefPtr<Structure> structure, ErrorPrototype* errorPrototype) : InternalFunction(&exec->globalData(), structure, Identifier(exec, errorPrototype->classInfo()->className)) { // ECMA 15.11.3.1 Error.prototype @@ -41,8 +41,8 @@ ErrorConstructor::ErrorConstructor(ExecState* exec, PassRefPtr<StructureID> stru ErrorInstance* constructError(ExecState* exec, const ArgList& args) { ErrorInstance* obj = new (exec) ErrorInstance(exec->lexicalGlobalObject()->errorStructure()); - if (!args.at(exec, 0)->isUndefined()) - obj->putDirect(exec->propertyNames().message, jsString(exec, args.at(exec, 0)->toString(exec))); + if (!args.at(exec, 0).isUndefined()) + obj->putDirect(exec->propertyNames().message, jsString(exec, args.at(exec, 0).toString(exec))); return obj; } @@ -58,7 +58,7 @@ ConstructType ErrorConstructor::getConstructData(ConstructData& constructData) } // ECMA 15.9.2 -static JSValue* callErrorConstructor(ExecState* exec, JSObject*, JSValue*, const ArgList& args) +static JSValuePtr callErrorConstructor(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) { // "Error()" gives the sames result as "new Error()" return constructError(exec, args); diff --git a/JavaScriptCore/runtime/ErrorConstructor.h b/JavaScriptCore/runtime/ErrorConstructor.h index 45e4bb0..2dd4124 100644 --- a/JavaScriptCore/runtime/ErrorConstructor.h +++ b/JavaScriptCore/runtime/ErrorConstructor.h @@ -30,7 +30,7 @@ namespace JSC { class ErrorConstructor : public InternalFunction { public: - ErrorConstructor(ExecState*, PassRefPtr<StructureID>, ErrorPrototype*); + ErrorConstructor(ExecState*, PassRefPtr<Structure>, ErrorPrototype*); private: virtual ConstructType getConstructData(ConstructData&); diff --git a/JavaScriptCore/runtime/ErrorInstance.cpp b/JavaScriptCore/runtime/ErrorInstance.cpp index 1c55856..2e2cdce 100644 --- a/JavaScriptCore/runtime/ErrorInstance.cpp +++ b/JavaScriptCore/runtime/ErrorInstance.cpp @@ -25,7 +25,7 @@ namespace JSC { const ClassInfo ErrorInstance::info = { "Error", 0, 0, 0 }; -ErrorInstance::ErrorInstance(PassRefPtr<StructureID> structure) +ErrorInstance::ErrorInstance(PassRefPtr<Structure> structure) : JSObject(structure) { } diff --git a/JavaScriptCore/runtime/ErrorInstance.h b/JavaScriptCore/runtime/ErrorInstance.h index 8d86eec..6f9d262 100644 --- a/JavaScriptCore/runtime/ErrorInstance.h +++ b/JavaScriptCore/runtime/ErrorInstance.h @@ -27,7 +27,7 @@ namespace JSC { class ErrorInstance : public JSObject { public: - explicit ErrorInstance(PassRefPtr<StructureID>); + explicit ErrorInstance(PassRefPtr<Structure>); virtual const ClassInfo* classInfo() const { return &info; } static const ClassInfo info; diff --git a/JavaScriptCore/runtime/ErrorPrototype.cpp b/JavaScriptCore/runtime/ErrorPrototype.cpp index 69255c1..8703d81 100644 --- a/JavaScriptCore/runtime/ErrorPrototype.cpp +++ b/JavaScriptCore/runtime/ErrorPrototype.cpp @@ -24,16 +24,16 @@ #include "JSString.h" #include "ObjectPrototype.h" #include "PrototypeFunction.h" -#include "ustring.h" +#include "UString.h" namespace JSC { ASSERT_CLASS_FITS_IN_CELL(ErrorPrototype); -static JSValue* errorProtoFuncToString(ExecState*, JSObject*, JSValue*, const ArgList&); +static JSValuePtr errorProtoFuncToString(ExecState*, JSObject*, JSValuePtr, const ArgList&); // ECMA 15.9.4 -ErrorPrototype::ErrorPrototype(ExecState* exec, PassRefPtr<StructureID> structure, StructureID* prototypeFunctionStructure) +ErrorPrototype::ErrorPrototype(ExecState* exec, PassRefPtr<Structure> structure, Structure* prototypeFunctionStructure) : ErrorInstance(structure) { // The constructor will be added later in ErrorConstructor's constructor @@ -44,21 +44,21 @@ ErrorPrototype::ErrorPrototype(ExecState* exec, PassRefPtr<StructureID> structur putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 0, exec->propertyNames().toString, errorProtoFuncToString), DontEnum); } -JSValue* errorProtoFuncToString(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&) +JSValuePtr errorProtoFuncToString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) { - JSObject* thisObj = thisValue->toThisObject(exec); + JSObject* thisObj = thisValue.toThisObject(exec); UString s = "Error"; - JSValue* v = thisObj->get(exec, exec->propertyNames().name); - if (!v->isUndefined()) - s = v->toString(exec); + JSValuePtr v = thisObj->get(exec, exec->propertyNames().name); + if (!v.isUndefined()) + s = v.toString(exec); v = thisObj->get(exec, exec->propertyNames().message); - if (!v->isUndefined()) { + if (!v.isUndefined()) { // Mozilla-compatible format. s += ": "; - s += v->toString(exec); + s += v.toString(exec); } return jsNontrivialString(exec, s); diff --git a/JavaScriptCore/runtime/ErrorPrototype.h b/JavaScriptCore/runtime/ErrorPrototype.h index 255ea11..53d12d9 100644 --- a/JavaScriptCore/runtime/ErrorPrototype.h +++ b/JavaScriptCore/runtime/ErrorPrototype.h @@ -29,7 +29,7 @@ namespace JSC { class ErrorPrototype : public ErrorInstance { public: - ErrorPrototype(ExecState*, PassRefPtr<StructureID>, StructureID* prototypeFunctionStructure); + ErrorPrototype(ExecState*, PassRefPtr<Structure>, Structure* prototypeFunctionStructure); }; } // namespace JSC diff --git a/JavaScriptCore/VM/ExceptionHelpers.cpp b/JavaScriptCore/runtime/ExceptionHelpers.cpp index 0ad332d..d1b5aac 100644 --- a/JavaScriptCore/VM/ExceptionHelpers.cpp +++ b/JavaScriptCore/runtime/ExceptionHelpers.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Apple Inc. All rights reserved. + * 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 @@ -30,24 +30,15 @@ #include "ExceptionHelpers.h" #include "CodeBlock.h" -#include "ExecState.h" +#include "CallFrame.h" +#include "JSGlobalObjectFunctions.h" #include "JSObject.h" #include "JSNotAnObject.h" -#include "Machine.h" -#include "nodes.h" +#include "Interpreter.h" +#include "Nodes.h" namespace JSC { -static void substitute(UString& string, const UString& substring) -{ - int position = string.find("%s"); - ASSERT(position != -1); - UString newString = string.substr(0, position); - newString.append(substring); - newString.append(string.substr(position + 2)); - string = newString; -} - class InterruptedExecutionError : public JSObject { public: InterruptedExecutionError(JSGlobalData* globalData) @@ -58,56 +49,40 @@ public: virtual bool isWatchdogException() const { return true; } }; -JSValue* createInterruptedExecutionException(JSGlobalData* globalData) +JSValuePtr createInterruptedExecutionException(JSGlobalData* globalData) { return new (globalData) InterruptedExecutionError(globalData); } -JSValue* createError(ExecState* exec, ErrorType e, const char* msg) +static JSValuePtr createError(ExecState* exec, ErrorType e, const char* msg) { return Error::create(exec, e, msg, -1, -1, 0); } -JSValue* createError(ExecState* exec, ErrorType e, const char* msg, const Identifier& label) -{ - UString message = msg; - substitute(message, label.ustring()); - return Error::create(exec, e, message, -1, -1, 0); -} - -JSValue* createError(ExecState* exec, ErrorType e, const char* msg, JSValue* v) -{ - UString message = msg; - substitute(message, v->toString(exec)); - return Error::create(exec, e, message, -1, -1, 0); -} - -JSValue* createStackOverflowError(ExecState* exec) +JSValuePtr createStackOverflowError(ExecState* exec) { return createError(exec, RangeError, "Maximum call stack size exceeded."); } -JSValue* createUndefinedVariableError(ExecState* exec, const Identifier& ident, const Instruction* vPC, CodeBlock* codeBlock) +JSValuePtr createUndefinedVariableError(ExecState* exec, const Identifier& ident, unsigned bytecodeOffset, CodeBlock* codeBlock) { int startOffset = 0; int endOffset = 0; int divotPoint = 0; - int line = codeBlock->expressionRangeForVPC(vPC, divotPoint, startOffset, endOffset); + int line = codeBlock->expressionRangeForBytecodeOffset(exec, bytecodeOffset, divotPoint, startOffset, endOffset); UString message = "Can't find variable: "; message.append(ident.ustring()); - JSObject* exception = Error::create(exec, ReferenceError, message, line, codeBlock->ownerNode->sourceID(), codeBlock->ownerNode->sourceURL()); + JSObject* exception = Error::create(exec, ReferenceError, message, line, codeBlock->ownerNode()->sourceID(), codeBlock->ownerNode()->sourceURL()); exception->putWithAttributes(exec, Identifier(exec, expressionBeginOffsetPropertyName), jsNumber(exec, divotPoint - startOffset), ReadOnly | DontDelete); exception->putWithAttributes(exec, Identifier(exec, expressionCaretOffsetPropertyName), jsNumber(exec, divotPoint), ReadOnly | DontDelete); exception->putWithAttributes(exec, Identifier(exec, expressionEndOffsetPropertyName), jsNumber(exec, divotPoint + endOffset), ReadOnly | DontDelete); return exception; } -bool isStrWhiteSpace(UChar c); - -static UString createErrorMessage(ExecState* exec, CodeBlock* codeBlock, int, int expressionStart, int expressionStop, JSValue* value, UString error) +static UString createErrorMessage(ExecState* exec, CodeBlock* codeBlock, int, int expressionStart, int expressionStop, JSValuePtr value, UString error) { - if (!expressionStop || expressionStart > codeBlock->source->length()) { - UString errorText = value->toString(exec); + if (!expressionStop || expressionStart > codeBlock->source()->length()) { + UString errorText = value.toString(exec); errorText.append(" is "); errorText.append(error); return errorText; @@ -117,14 +92,14 @@ static UString createErrorMessage(ExecState* exec, CodeBlock* codeBlock, int, in if (expressionStart < expressionStop) { errorText.append('\''); - errorText.append(codeBlock->source->getRange(expressionStart, expressionStop)); + errorText.append(codeBlock->source()->getRange(expressionStart, expressionStop)); errorText.append("' ["); - errorText.append(value->toString(exec)); + errorText.append(value.toString(exec)); errorText.append("] is "); } else { // No range information, so give a few characters of context - const UChar* data = codeBlock->source->data(); - int dataLength = codeBlock->source->length(); + const UChar* data = codeBlock->source()->data(); + int dataLength = codeBlock->source()->length(); int start = expressionStart; int stop = expressionStart; // Get up to 20 characters of context to the left and right of the divot, clamping to the line. @@ -138,9 +113,9 @@ static UString createErrorMessage(ExecState* exec, CodeBlock* codeBlock, int, in while (stop > expressionStart && isStrWhiteSpace(data[stop])) stop--; errorText.append("near '..."); - errorText.append(codeBlock->source->getRange(start, stop)); + errorText.append(codeBlock->source()->getRange(start, stop)); errorText.append("...' ["); - errorText.append(value->toString(exec)); + errorText.append(value.toString(exec)); errorText.append("] is "); } errorText.append(error); @@ -148,7 +123,7 @@ static UString createErrorMessage(ExecState* exec, CodeBlock* codeBlock, int, in return errorText; } -JSObject* createInvalidParamError(ExecState* exec, const char* op, JSValue* value, const Instruction* vPC, CodeBlock* codeBlock) +JSObject* createInvalidParamError(ExecState* exec, const char* op, JSValuePtr value, unsigned bytecodeOffset, CodeBlock* codeBlock) { UString message = "not a valid argument for '"; message.append(op); @@ -157,44 +132,44 @@ JSObject* createInvalidParamError(ExecState* exec, const char* op, JSValue* valu int startOffset = 0; int endOffset = 0; int divotPoint = 0; - int line = codeBlock->expressionRangeForVPC(vPC, divotPoint, startOffset, endOffset); + int line = codeBlock->expressionRangeForBytecodeOffset(exec, bytecodeOffset, divotPoint, startOffset, endOffset); UString errorMessage = createErrorMessage(exec, codeBlock, line, divotPoint, divotPoint + endOffset, value, message); - JSObject* exception = Error::create(exec, TypeError, errorMessage, line, codeBlock->ownerNode->sourceID(), codeBlock->ownerNode->sourceURL()); + JSObject* exception = Error::create(exec, TypeError, errorMessage, line, codeBlock->ownerNode()->sourceID(), codeBlock->ownerNode()->sourceURL()); exception->putWithAttributes(exec, Identifier(exec, expressionBeginOffsetPropertyName), jsNumber(exec, divotPoint - startOffset), ReadOnly | DontDelete); exception->putWithAttributes(exec, Identifier(exec, expressionCaretOffsetPropertyName), jsNumber(exec, divotPoint), ReadOnly | DontDelete); exception->putWithAttributes(exec, Identifier(exec, expressionEndOffsetPropertyName), jsNumber(exec, divotPoint + endOffset), ReadOnly | DontDelete); return exception; } -JSObject* createNotAConstructorError(ExecState* exec, JSValue* value, const Instruction* vPC, CodeBlock* codeBlock) +JSObject* createNotAConstructorError(ExecState* exec, JSValuePtr value, unsigned bytecodeOffset, CodeBlock* codeBlock) { int startOffset = 0; int endOffset = 0; int divotPoint = 0; - int line = codeBlock->expressionRangeForVPC(vPC, divotPoint, startOffset, endOffset); + int line = codeBlock->expressionRangeForBytecodeOffset(exec, bytecodeOffset, divotPoint, startOffset, endOffset); // We're in a "new" expression, so we need to skip over the "new.." part int startPoint = divotPoint - (startOffset ? startOffset - 4 : 0); // -4 for "new " - const UChar* data = codeBlock->source->data(); + const UChar* data = codeBlock->source()->data(); while (startPoint < divotPoint && isStrWhiteSpace(data[startPoint])) startPoint++; UString errorMessage = createErrorMessage(exec, codeBlock, line, startPoint, divotPoint, value, "not a constructor"); - JSObject* exception = Error::create(exec, TypeError, errorMessage, line, codeBlock->ownerNode->sourceID(), codeBlock->ownerNode->sourceURL()); + JSObject* exception = Error::create(exec, TypeError, errorMessage, line, codeBlock->ownerNode()->sourceID(), codeBlock->ownerNode()->sourceURL()); exception->putWithAttributes(exec, Identifier(exec, expressionBeginOffsetPropertyName), jsNumber(exec, divotPoint - startOffset), ReadOnly | DontDelete); exception->putWithAttributes(exec, Identifier(exec, expressionCaretOffsetPropertyName), jsNumber(exec, divotPoint), ReadOnly | DontDelete); exception->putWithAttributes(exec, Identifier(exec, expressionEndOffsetPropertyName), jsNumber(exec, divotPoint + endOffset), ReadOnly | DontDelete); return exception; } -JSValue* createNotAFunctionError(ExecState* exec, JSValue* value, const Instruction* vPC, CodeBlock* codeBlock) +JSValuePtr createNotAFunctionError(ExecState* exec, JSValuePtr value, unsigned bytecodeOffset, CodeBlock* codeBlock) { int startOffset = 0; int endOffset = 0; int divotPoint = 0; - int line = codeBlock->expressionRangeForVPC(vPC, divotPoint, startOffset, endOffset); + int line = codeBlock->expressionRangeForBytecodeOffset(exec, bytecodeOffset, divotPoint, startOffset, endOffset); UString errorMessage = createErrorMessage(exec, codeBlock, line, divotPoint - startOffset, divotPoint, value, "not a function"); - JSObject* exception = Error::create(exec, TypeError, errorMessage, line, codeBlock->ownerNode->sourceID(), codeBlock->ownerNode->sourceURL()); + JSObject* exception = Error::create(exec, TypeError, errorMessage, line, codeBlock->ownerNode()->sourceID(), codeBlock->ownerNode()->sourceURL()); exception->putWithAttributes(exec, Identifier(exec, expressionBeginOffsetPropertyName), jsNumber(exec, divotPoint - startOffset), ReadOnly | DontDelete); exception->putWithAttributes(exec, Identifier(exec, expressionCaretOffsetPropertyName), jsNumber(exec, divotPoint), ReadOnly | DontDelete); exception->putWithAttributes(exec, Identifier(exec, expressionEndOffsetPropertyName), jsNumber(exec, divotPoint + endOffset), ReadOnly | DontDelete); @@ -206,19 +181,25 @@ JSNotAnObjectErrorStub* createNotAnObjectErrorStub(ExecState* exec, bool isNull) return new (exec) JSNotAnObjectErrorStub(exec, isNull); } -JSObject* createNotAnObjectError(ExecState* exec, JSNotAnObjectErrorStub* error, const Instruction* vPC, CodeBlock* codeBlock) +JSObject* createNotAnObjectError(ExecState* exec, JSNotAnObjectErrorStub* error, unsigned bytecodeOffset, CodeBlock* codeBlock) { - if (vPC[8].u.opcode == exec->machine()->getOpcode(op_instanceof)) - return createInvalidParamError(exec, "instanceof", error->isNull() ? jsNull() : jsUndefined(), vPC, codeBlock); - if (vPC[8].u.opcode == exec->machine()->getOpcode(op_construct)) - return createNotAConstructorError(exec, error->isNull() ? jsNull() : jsUndefined(), vPC, codeBlock); + // Both op_construct and op_instanceof require a use of op_get_by_id to get + // the prototype property from an object. The exception messages for exceptions + // thrown by these instances op_get_by_id need to reflect this. + OpcodeID followingOpcodeID; + if (codeBlock->getByIdExceptionInfoForBytecodeOffset(exec, bytecodeOffset, followingOpcodeID)) { + ASSERT(followingOpcodeID == op_construct || followingOpcodeID == op_instanceof); + if (followingOpcodeID == op_construct) + return createNotAConstructorError(exec, error->isNull() ? jsNull() : jsUndefined(), bytecodeOffset, codeBlock); + return createInvalidParamError(exec, "instanceof", error->isNull() ? jsNull() : jsUndefined(), bytecodeOffset, codeBlock); + } int startOffset = 0; int endOffset = 0; int divotPoint = 0; - int line = codeBlock->expressionRangeForVPC(vPC, divotPoint, startOffset, endOffset); + int line = codeBlock->expressionRangeForBytecodeOffset(exec, bytecodeOffset, divotPoint, startOffset, endOffset); UString errorMessage = createErrorMessage(exec, codeBlock, line, divotPoint - startOffset, divotPoint, error->isNull() ? jsNull() : jsUndefined(), "not an object"); - JSObject* exception = Error::create(exec, TypeError, errorMessage, line, codeBlock->ownerNode->sourceID(), codeBlock->ownerNode->sourceURL()); + JSObject* exception = Error::create(exec, TypeError, errorMessage, line, codeBlock->ownerNode()->sourceID(), codeBlock->ownerNode()->sourceURL()); exception->putWithAttributes(exec, Identifier(exec, expressionBeginOffsetPropertyName), jsNumber(exec, divotPoint - startOffset), ReadOnly | DontDelete); exception->putWithAttributes(exec, Identifier(exec, expressionCaretOffsetPropertyName), jsNumber(exec, divotPoint), ReadOnly | DontDelete); exception->putWithAttributes(exec, Identifier(exec, expressionEndOffsetPropertyName), jsNumber(exec, divotPoint + endOffset), ReadOnly | DontDelete); diff --git a/JavaScriptCore/VM/ExceptionHelpers.h b/JavaScriptCore/runtime/ExceptionHelpers.h index fbbe450..d4dfdd8 100644 --- a/JavaScriptCore/VM/ExceptionHelpers.h +++ b/JavaScriptCore/runtime/ExceptionHelpers.h @@ -40,16 +40,17 @@ namespace JSC { class JSGlobalData; class JSNotAnObjectErrorStub; class JSObject; + class JSValuePtr; class Node; - JSValue* createInterruptedExecutionException(JSGlobalData*); - JSValue* createStackOverflowError(ExecState*); - JSValue* createUndefinedVariableError(ExecState*, const Identifier&, const Instruction*, CodeBlock*); + JSValuePtr createInterruptedExecutionException(JSGlobalData*); + JSValuePtr createStackOverflowError(ExecState*); + JSValuePtr createUndefinedVariableError(ExecState*, const Identifier&, unsigned bytecodeOffset, CodeBlock*); JSNotAnObjectErrorStub* createNotAnObjectErrorStub(ExecState*, bool isNull); - JSObject* createInvalidParamError(ExecState*, const char* op, JSValue*, const Instruction*, CodeBlock*); - JSObject* createNotAConstructorError(ExecState*, JSValue*, const Instruction*, CodeBlock*); - JSValue* createNotAFunctionError(ExecState*, JSValue*, const Instruction*, CodeBlock*); - JSObject* createNotAnObjectError(ExecState*, JSNotAnObjectErrorStub*, const Instruction*, CodeBlock*); + JSObject* createInvalidParamError(ExecState*, const char* op, JSValuePtr, unsigned bytecodeOffset, CodeBlock*); + JSObject* createNotAConstructorError(ExecState*, JSValuePtr, unsigned bytecodeOffset, CodeBlock*); + JSValuePtr createNotAFunctionError(ExecState*, JSValuePtr, unsigned bytecodeOffset, CodeBlock*); + JSObject* createNotAnObjectError(ExecState*, JSNotAnObjectErrorStub*, unsigned bytecodeOffset, CodeBlock*); } // namespace JSC diff --git a/JavaScriptCore/runtime/FunctionConstructor.cpp b/JavaScriptCore/runtime/FunctionConstructor.cpp index adc3d3c..d58334a 100644 --- a/JavaScriptCore/runtime/FunctionConstructor.cpp +++ b/JavaScriptCore/runtime/FunctionConstructor.cpp @@ -27,14 +27,14 @@ #include "JSString.h" #include "Parser.h" #include "Debugger.h" -#include "lexer.h" -#include "nodes.h" +#include "Lexer.h" +#include "Nodes.h" namespace JSC { ASSERT_CLASS_FITS_IN_CELL(FunctionConstructor); -FunctionConstructor::FunctionConstructor(ExecState* exec, PassRefPtr<StructureID> structure, FunctionPrototype* functionPrototype) +FunctionConstructor::FunctionConstructor(ExecState* exec, PassRefPtr<Structure> structure, FunctionPrototype* functionPrototype) : InternalFunction(&exec->globalData(), structure, Identifier(exec, functionPrototype->classInfo()->className)) { putDirectWithoutTransition(exec->propertyNames().prototype, functionPrototype, DontEnum | DontDelete | ReadOnly); @@ -54,7 +54,7 @@ ConstructType FunctionConstructor::getConstructData(ConstructData& constructData return ConstructTypeHost; } -static JSValue* callFunctionConstructor(ExecState* exec, JSObject*, JSValue*, const ArgList& args) +static JSValuePtr callFunctionConstructor(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) { return constructFunction(exec, args); } @@ -66,75 +66,57 @@ CallType FunctionConstructor::getCallData(CallData& callData) return CallTypeHost; } +FunctionBodyNode* extractFunctionBody(ProgramNode* program) +{ + if (!program) + return 0; + + StatementVector& children = program->children(); + if (children.size() != 1) + return 0; + + ExprStatementNode* exprStatement = static_cast<ExprStatementNode*>(children[0].get()); + ASSERT(exprStatement->isExprStatement()); + if (!exprStatement || !exprStatement->isExprStatement()) + return 0; + + FuncExprNode* funcExpr = static_cast<FuncExprNode*>(exprStatement->expr()); + ASSERT(funcExpr->isFuncExprNode()); + if (!funcExpr || !funcExpr->isFuncExprNode()) + return 0; + + FunctionBodyNode* body = funcExpr->body(); + ASSERT(body); + return body; +} + // ECMA 15.3.2 The Function Constructor JSObject* constructFunction(ExecState* exec, const ArgList& args, const Identifier& functionName, const UString& sourceURL, int lineNumber) { - UString p(""); - UString body; - int argsSize = args.size(); - if (argsSize == 0) - body = ""; - else if (argsSize == 1) - body = args.at(exec, 0)->toString(exec); + UString program; + if (args.isEmpty()) + program = "(function(){})"; + else if (args.size() == 1) + program = "(function(){" + args.at(exec, 0).toString(exec) + "})"; else { - p = args.at(exec, 0)->toString(exec); - for (int k = 1; k < argsSize - 1; k++) - p += "," + args.at(exec, k)->toString(exec); - body = args.at(exec, argsSize - 1)->toString(exec); + program = "(function(" + args.at(exec, 0).toString(exec); + for (size_t i = 1; i < args.size() - 1; i++) + program += "," + args.at(exec, i).toString(exec); + program += "){" + args.at(exec, args.size() - 1).toString(exec) + "})"; } - // parse the source code int errLine; UString errMsg; - SourceCode source = makeSource(body, sourceURL, lineNumber); - RefPtr<FunctionBodyNode> functionBody = exec->globalData().parser->parse<FunctionBodyNode>(exec, exec->dynamicGlobalObject()->debugger(), source, &errLine, &errMsg); + SourceCode source = makeSource(program, sourceURL, lineNumber); + RefPtr<ProgramNode> programNode = exec->globalData().parser->parse<ProgramNode>(exec, exec->dynamicGlobalObject()->debugger(), source, &errLine, &errMsg); - // No program node == syntax error - throw a syntax error - if (!functionBody) - // We can't return a Completion(Throw) here, so just set the exception - // and return it + FunctionBodyNode* body = extractFunctionBody(programNode.get()); + if (!body) return throwError(exec, SyntaxError, errMsg, errLine, source.provider()->asID(), source.provider()->url()); - // parse parameter list. throw syntax error on illegal identifiers - int len = p.size(); - const UChar* c = p.data(); - int i = 0; - UString param; - Vector<Identifier> parameters; - while (i < len) { - while (*c == ' ' && i < len) - c++, i++; - if (Lexer::isIdentStart(c[0])) { // else error - param = UString(c, 1); - c++, i++; - while (i < len && (Lexer::isIdentPart(c[0]))) { - param.append(*c); - c++, i++; - } - while (i < len && *c == ' ') - c++, i++; - if (i == len) { - parameters.append(Identifier(exec, param)); - break; - } else if (*c == ',') { - parameters.append(Identifier(exec, param)); - c++, i++; - continue; - } // else error - } - return throwError(exec, SyntaxError, "Syntax error in parameter list"); - } - size_t count = parameters.size(); - functionBody->finishParsing(parameters.releaseBuffer(), count); - JSGlobalObject* globalObject = exec->lexicalGlobalObject(); ScopeChain scopeChain(globalObject, globalObject->globalData(), exec->globalThisValue()); - JSFunction* function = new (exec) JSFunction(exec, functionName, functionBody.get(), scopeChain.node()); - - JSObject* prototype = constructEmptyObject(exec); - prototype->putDirect(exec->propertyNames().constructor, function, DontEnum); - function->putDirect(exec->propertyNames().prototype, prototype, DontDelete); - return function; + return new (exec) JSFunction(exec, functionName, body, scopeChain.node()); } // ECMA 15.3.2 The Function Constructor diff --git a/JavaScriptCore/runtime/FunctionConstructor.h b/JavaScriptCore/runtime/FunctionConstructor.h index c309c41..124b354 100644 --- a/JavaScriptCore/runtime/FunctionConstructor.h +++ b/JavaScriptCore/runtime/FunctionConstructor.h @@ -26,10 +26,12 @@ namespace JSC { class FunctionPrototype; + class ProgramNode; + class FunctionBodyNode; class FunctionConstructor : public InternalFunction { public: - FunctionConstructor(ExecState*, PassRefPtr<StructureID>, FunctionPrototype*); + FunctionConstructor(ExecState*, PassRefPtr<Structure>, FunctionPrototype*); private: virtual ConstructType getConstructData(ConstructData&); @@ -39,6 +41,8 @@ namespace JSC { JSObject* constructFunction(ExecState*, const ArgList&, const Identifier& functionName, const UString& sourceURL, int lineNumber); JSObject* constructFunction(ExecState*, const ArgList&); + FunctionBodyNode* extractFunctionBody(ProgramNode*); + } // namespace JSC #endif // FunctionConstructor_h diff --git a/JavaScriptCore/runtime/FunctionPrototype.cpp b/JavaScriptCore/runtime/FunctionPrototype.cpp index 8c3a260..7be2685 100644 --- a/JavaScriptCore/runtime/FunctionPrototype.cpp +++ b/JavaScriptCore/runtime/FunctionPrototype.cpp @@ -25,31 +25,31 @@ #include "JSArray.h" #include "JSFunction.h" #include "JSString.h" -#include "Machine.h" +#include "Interpreter.h" #include "PrototypeFunction.h" namespace JSC { ASSERT_CLASS_FITS_IN_CELL(FunctionPrototype); -static JSValue* functionProtoFuncToString(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* functionProtoFuncApply(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* functionProtoFuncCall(ExecState*, JSObject*, JSValue*, const ArgList&); +static JSValuePtr functionProtoFuncToString(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr functionProtoFuncApply(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr functionProtoFuncCall(ExecState*, JSObject*, JSValuePtr, const ArgList&); -FunctionPrototype::FunctionPrototype(ExecState* exec, PassRefPtr<StructureID> structure) +FunctionPrototype::FunctionPrototype(ExecState* exec, PassRefPtr<Structure> structure) : InternalFunction(&exec->globalData(), structure, exec->propertyNames().nullIdentifier) { putDirectWithoutTransition(exec->propertyNames().length, jsNumber(exec, 0), DontDelete | ReadOnly | DontEnum); } -void FunctionPrototype::addFunctionProperties(ExecState* exec, StructureID* prototypeFunctionStructure) +void FunctionPrototype::addFunctionProperties(ExecState* exec, Structure* prototypeFunctionStructure) { putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 0, exec->propertyNames().toString, functionProtoFuncToString), DontEnum); putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 2, exec->propertyNames().apply, functionProtoFuncApply), DontEnum); putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 1, exec->propertyNames().call, functionProtoFuncCall), DontEnum); } -static JSValue* callFunctionPrototype(ExecState*, JSObject*, JSValue*, const ArgList&) +static JSValuePtr callFunctionPrototype(ExecState*, JSObject*, JSValuePtr, const ArgList&) { return jsUndefined(); } @@ -63,14 +63,14 @@ CallType FunctionPrototype::getCallData(CallData& callData) // Functions -JSValue* functionProtoFuncToString(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&) +JSValuePtr functionProtoFuncToString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) { - if (thisValue->isObject(&JSFunction::info)) { + if (thisValue.isObject(&JSFunction::info)) { JSFunction* function = asFunction(thisValue); - return jsString(exec, "function " + function->name(&exec->globalData()) + "(" + function->m_body->paramString() + ") " + function->m_body->toSourceString()); + return jsString(exec, "function " + function->name(&exec->globalData()) + "(" + function->body()->paramString() + ") " + function->body()->toSourceString()); } - if (thisValue->isObject(&InternalFunction::info)) { + if (thisValue.isObject(&InternalFunction::info)) { InternalFunction* function = asInternalFunction(thisValue); return jsString(exec, "function " + function->name(&exec->globalData()) + "() {\n [native code]\n}"); } @@ -78,32 +78,32 @@ JSValue* functionProtoFuncToString(ExecState* exec, JSObject*, JSValue* thisValu return throwError(exec, TypeError); } -JSValue* functionProtoFuncApply(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) +JSValuePtr functionProtoFuncApply(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) { CallData callData; - CallType callType = thisValue->getCallData(callData); + CallType callType = thisValue.getCallData(callData); if (callType == CallTypeNone) return throwError(exec, TypeError); - JSValue* thisArg = args.at(exec, 0); - JSValue* argArray = args.at(exec, 1); + JSValuePtr thisArg = args.at(exec, 0); + JSValuePtr argArray = args.at(exec, 1); - JSValue* applyThis; - if (thisArg->isUndefinedOrNull()) + JSValuePtr applyThis; + if (thisArg.isUndefinedOrNull()) applyThis = exec->globalThisValue(); else - applyThis = thisArg->toObject(exec); + applyThis = thisArg.toObject(exec); ArgList applyArgs; - if (!argArray->isUndefinedOrNull()) { - if (!argArray->isObject()) + if (!argArray.isUndefinedOrNull()) { + if (!argArray.isObject()) return throwError(exec, TypeError); if (asObject(argArray)->classInfo() == &Arguments::info) asArguments(argArray)->fillArgList(exec, applyArgs); - else if (exec->machine()->isJSArray(argArray)) + else if (exec->interpreter()->isJSArray(argArray)) asArray(argArray)->fillArgList(exec, applyArgs); else if (asObject(argArray)->inherits(&JSArray::info)) { - unsigned length = asArray(argArray)->get(exec, exec->propertyNames().length)->toUInt32(exec); + unsigned length = asArray(argArray)->get(exec, exec->propertyNames().length).toUInt32(exec); for (unsigned i = 0; i < length; ++i) applyArgs.append(asArray(argArray)->get(exec, i)); } else @@ -113,20 +113,20 @@ JSValue* functionProtoFuncApply(ExecState* exec, JSObject*, JSValue* thisValue, return call(exec, thisValue, callType, callData, applyThis, applyArgs); } -JSValue* functionProtoFuncCall(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) +JSValuePtr functionProtoFuncCall(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) { CallData callData; - CallType callType = thisValue->getCallData(callData); + CallType callType = thisValue.getCallData(callData); if (callType == CallTypeNone) return throwError(exec, TypeError); - JSValue* thisArg = args.at(exec, 0); + JSValuePtr thisArg = args.at(exec, 0); JSObject* callThis; - if (thisArg->isUndefinedOrNull()) + if (thisArg.isUndefinedOrNull()) callThis = exec->globalThisValue(); else - callThis = thisArg->toObject(exec); + callThis = thisArg.toObject(exec); ArgList argsTail; args.getSlice(1, argsTail); diff --git a/JavaScriptCore/runtime/FunctionPrototype.h b/JavaScriptCore/runtime/FunctionPrototype.h index f493642..33d68b7 100644 --- a/JavaScriptCore/runtime/FunctionPrototype.h +++ b/JavaScriptCore/runtime/FunctionPrototype.h @@ -27,12 +27,12 @@ namespace JSC { class FunctionPrototype : public InternalFunction { public: - FunctionPrototype(ExecState*, PassRefPtr<StructureID>); - void addFunctionProperties(ExecState*, StructureID* prototypeFunctionStructure); + FunctionPrototype(ExecState*, PassRefPtr<Structure>); + void addFunctionProperties(ExecState*, Structure* prototypeFunctionStructure); - static PassRefPtr<StructureID> createStructureID(JSValue* proto) + static PassRefPtr<Structure> createStructure(JSValuePtr proto) { - return StructureID::create(proto, TypeInfo(ObjectType, HasStandardGetOwnPropertySlot)); + return Structure::create(proto, TypeInfo(ObjectType, HasStandardGetOwnPropertySlot)); } private: diff --git a/JavaScriptCore/runtime/GetterSetter.cpp b/JavaScriptCore/runtime/GetterSetter.cpp index c3d089f..39ee6fc 100644 --- a/JavaScriptCore/runtime/GetterSetter.cpp +++ b/JavaScriptCore/runtime/GetterSetter.cpp @@ -38,13 +38,13 @@ void GetterSetter::mark() m_setter->mark(); } -JSValue* GetterSetter::toPrimitive(ExecState*, PreferredPrimitiveType) const +JSValuePtr GetterSetter::toPrimitive(ExecState*, PreferredPrimitiveType) const { ASSERT_NOT_REACHED(); return jsNull(); } -bool GetterSetter::getPrimitiveNumber(ExecState*, double& number, JSValue*& value) +bool GetterSetter::getPrimitiveNumber(ExecState*, double& number, JSValuePtr& value) { ASSERT_NOT_REACHED(); number = 0; @@ -73,7 +73,7 @@ UString GetterSetter::toString(ExecState*) const JSObject* GetterSetter::toObject(ExecState* exec) const { ASSERT_NOT_REACHED(); - return jsNull()->toObject(exec); + return jsNull().toObject(exec); } bool GetterSetter::isGetterSetter() const diff --git a/JavaScriptCore/runtime/GetterSetter.h b/JavaScriptCore/runtime/GetterSetter.h index da968b2..48e1baf 100644 --- a/JavaScriptCore/runtime/GetterSetter.h +++ b/JavaScriptCore/runtime/GetterSetter.h @@ -50,8 +50,8 @@ namespace JSC { private: virtual bool isGetterSetter() const; - virtual JSValue* toPrimitive(ExecState*, PreferredPrimitiveType) const; - virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue*& value); + virtual JSValuePtr toPrimitive(ExecState*, PreferredPrimitiveType) const; + virtual bool getPrimitiveNumber(ExecState*, double& number, JSValuePtr& value); virtual bool toBoolean(ExecState*) const; virtual double toNumber(ExecState*) const; virtual UString toString(ExecState*) const; @@ -61,9 +61,9 @@ namespace JSC { JSObject* m_setter; }; - GetterSetter* asGetterSetter(JSValue*); + GetterSetter* asGetterSetter(JSValuePtr); - inline GetterSetter* asGetterSetter(JSValue* value) + inline GetterSetter* asGetterSetter(JSValuePtr value) { ASSERT(asCell(value)->isGetterSetter()); return static_cast<GetterSetter*>(asCell(value)); diff --git a/JavaScriptCore/runtime/GlobalEvalFunction.cpp b/JavaScriptCore/runtime/GlobalEvalFunction.cpp index 10b3a2f..b0d4c25 100644 --- a/JavaScriptCore/runtime/GlobalEvalFunction.cpp +++ b/JavaScriptCore/runtime/GlobalEvalFunction.cpp @@ -32,7 +32,7 @@ namespace JSC { ASSERT_CLASS_FITS_IN_CELL(GlobalEvalFunction); -GlobalEvalFunction::GlobalEvalFunction(ExecState* exec, PassRefPtr<StructureID> structure, int len, const Identifier& name, NativeFunction function, JSGlobalObject* cachedGlobalObject) +GlobalEvalFunction::GlobalEvalFunction(ExecState* exec, PassRefPtr<Structure> structure, int len, const Identifier& name, NativeFunction function, JSGlobalObject* cachedGlobalObject) : PrototypeFunction(exec, structure, len, name, function) , m_cachedGlobalObject(cachedGlobalObject) { diff --git a/JavaScriptCore/runtime/GlobalEvalFunction.h b/JavaScriptCore/runtime/GlobalEvalFunction.h index 2d207c4..49b1847 100644 --- a/JavaScriptCore/runtime/GlobalEvalFunction.h +++ b/JavaScriptCore/runtime/GlobalEvalFunction.h @@ -32,7 +32,7 @@ namespace JSC { class GlobalEvalFunction : public PrototypeFunction { public: - GlobalEvalFunction(ExecState*, PassRefPtr<StructureID>, int len, const Identifier&, NativeFunction, JSGlobalObject* expectedThisObject); + GlobalEvalFunction(ExecState*, PassRefPtr<Structure>, int len, const Identifier&, NativeFunction, JSGlobalObject* expectedThisObject); JSGlobalObject* cachedGlobalObject() const { return m_cachedGlobalObject; } private: diff --git a/JavaScriptCore/kjs/identifier.cpp b/JavaScriptCore/runtime/Identifier.cpp index 50a6cc3..040c123 100644 --- a/JavaScriptCore/kjs/identifier.cpp +++ b/JavaScriptCore/runtime/Identifier.cpp @@ -19,9 +19,9 @@ */ #include "config.h" -#include "identifier.h" +#include "Identifier.h" -#include "ExecState.h" +#include "CallFrame.h" #include <new> // for placement new #include <string.h> // for strlen #include <wtf/Assertions.h> @@ -96,8 +96,7 @@ bool Identifier::equal(const UString::Rep* r, const UChar* s, int length) return true; } -struct CStringTranslator -{ +struct CStringTranslator { static unsigned hash(const char* c) { return UString::Rep::computeHash(c); @@ -116,7 +115,6 @@ struct CStringTranslator d[i] = static_cast<unsigned char>(c[i]); // use unsigned char to zero-extend instead of sign-extend UString::Rep* r = UString::Rep::create(d, static_cast<int>(length)).releaseRef(); - r->rc = 0; r->_hash = hash; location = r; @@ -126,12 +124,12 @@ struct CStringTranslator PassRefPtr<UString::Rep> Identifier::add(JSGlobalData* globalData, const char* c) { if (!c) { - UString::Rep::null.hash(); - return &UString::Rep::null; + UString::Rep::null().hash(); + return &UString::Rep::null(); } if (!c[0]) { - UString::Rep::empty.hash(); - return &UString::Rep::empty; + UString::Rep::empty().hash(); + return &UString::Rep::empty(); } if (!c[1]) return add(globalData, globalData->smallStrings.singleCharacterStringRep(static_cast<unsigned char>(c[0]))); @@ -143,10 +141,15 @@ PassRefPtr<UString::Rep> Identifier::add(JSGlobalData* globalData, const char* c if (iter != literalIdentifierTable.end()) return iter->second; - UString::Rep* addedString = *identifierTable.add<const char*, CStringTranslator>(c).first; - literalIdentifierTable.add(c, addedString); + pair<HashSet<UString::Rep*>::iterator, bool> addResult = identifierTable.add<const char*, CStringTranslator>(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<UString::Rep> addedString = addResult.second ? adoptRef(*addResult.first) : *addResult.first; + + literalIdentifierTable.add(c, addedString.get()); - return addedString; + return addedString.release(); } PassRefPtr<UString::Rep> Identifier::add(ExecState* exec, const char* c) @@ -159,8 +162,7 @@ struct UCharBuffer { unsigned int length; }; -struct UCharBufferTranslator -{ +struct UCharBufferTranslator { static unsigned hash(const UCharBuffer& buf) { return UString::Rep::computeHash(buf.s, buf.length); @@ -178,7 +180,6 @@ struct UCharBufferTranslator d[i] = buf.s[i]; UString::Rep* r = UString::Rep::create(d, buf.length).releaseRef(); - r->rc = 0; r->_hash = hash; location = r; @@ -193,11 +194,15 @@ PassRefPtr<UString::Rep> Identifier::add(JSGlobalData* globalData, const UChar* return add(globalData, globalData->smallStrings.singleCharacterStringRep(c)); } if (!length) { - UString::Rep::empty.hash(); - return &UString::Rep::empty; + UString::Rep::empty().hash(); + return &UString::Rep::empty(); } UCharBuffer buf = {s, length}; - return *globalData->identifierTable->add<UCharBuffer, UCharBufferTranslator>(buf).first; + pair<HashSet<UString::Rep*>::iterator, bool> addResult = globalData->identifierTable->add<UCharBuffer, UCharBufferTranslator>(buf); + + // If the string is newly-translated, then we need to adopt it. + // The boolean in the pair tells us if that is so. + return addResult.second ? adoptRef(*addResult.first) : *addResult.first; } PassRefPtr<UString::Rep> Identifier::add(ExecState* exec, const UChar* s, int length) @@ -220,8 +225,8 @@ PassRefPtr<UString::Rep> Identifier::addSlowCase(JSGlobalData* globalData, UStri } } if (!r->len) { - UString::Rep::empty.hash(); - return &UString::Rep::empty; + UString::Rep::empty().hash(); + return &UString::Rep::empty(); } return *globalData->identifierTable->add(r).first; } diff --git a/JavaScriptCore/kjs/identifier.h b/JavaScriptCore/runtime/Identifier.h index a79dd92..631cf42 100644 --- a/JavaScriptCore/kjs/identifier.h +++ b/JavaScriptCore/runtime/Identifier.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003, 2006, 2007 Apple Inc. All rights reserved. + * Copyright (C) 2003, 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 @@ -18,18 +18,18 @@ * */ -#ifndef KJS_IDENTIFIER_H -#define KJS_IDENTIFIER_H +#ifndef Identifier_h +#define Identifier_h #include "JSGlobalData.h" -#include "ustring.h" +#include "UString.h" namespace JSC { class ExecState; class Identifier { - friend class StructureID; + friend class Structure; public: Identifier() { } @@ -68,6 +68,7 @@ namespace JSC { friend bool operator!=(const Identifier&, const Identifier&); friend bool operator==(const Identifier&, const char*); + friend bool operator!=(const Identifier&, const char*); static void remove(UString::Rep*); @@ -78,8 +79,6 @@ namespace JSC { static PassRefPtr<UString::Rep> add(ExecState*, const char*); // Only to be used with string literals. static PassRefPtr<UString::Rep> add(JSGlobalData*, const char*); // Only to be used with string literals. - static void initializeIdentifierThreading(); - private: UString _ustring; @@ -132,9 +131,14 @@ namespace JSC { return Identifier::equal(a, b); } + inline bool operator!=(const Identifier& a, const char* b) + { + return !Identifier::equal(a, b); + } + IdentifierTable* createIdentifierTable(); void deleteIdentifierTable(IdentifierTable*); } // namespace JSC -#endif // KJS_IDENTIFIER_H +#endif // Identifier_h diff --git a/JavaScriptCore/runtime/InitializeThreading.cpp b/JavaScriptCore/runtime/InitializeThreading.cpp index 9e14768..cda9fb1 100644 --- a/JavaScriptCore/runtime/InitializeThreading.cpp +++ b/JavaScriptCore/runtime/InitializeThreading.cpp @@ -29,14 +29,17 @@ #include "config.h" #include "InitializeThreading.h" -#include "collector.h" +#include "JSImmediate.h" +#include "Collector.h" #include "DateMath.h" #include "dtoa.h" -#include "identifier.h" +#include "Identifier.h" #include "JSGlobalObject.h" -#include "ustring.h" +#include "UString.h" #include <wtf/Threading.h> +using namespace WTF; + namespace JSC { #if PLATFORM(DARWIN) && ENABLE(JSC_MULTIPLE_THREADS) @@ -46,9 +49,9 @@ static pthread_once_t initializeThreadingKeyOnce = PTHREAD_ONCE_INIT; static void initializeThreadingOnce() { WTF::initializeThreading(); + initializeUString(); #if ENABLE(JSC_MULTIPLE_THREADS) s_dtoaP5Mutex = new Mutex; - UString::null(); initDateMath(); #endif } diff --git a/JavaScriptCore/runtime/InternalFunction.cpp b/JavaScriptCore/runtime/InternalFunction.cpp index ee81a58..6714cf5 100644 --- a/JavaScriptCore/runtime/InternalFunction.cpp +++ b/JavaScriptCore/runtime/InternalFunction.cpp @@ -37,7 +37,7 @@ const ClassInfo* InternalFunction::classInfo() const return &info; } -InternalFunction::InternalFunction(JSGlobalData* globalData, PassRefPtr<StructureID> structure, const Identifier& name) +InternalFunction::InternalFunction(JSGlobalData* globalData, PassRefPtr<Structure> structure, const Identifier& name) : JSObject(structure) { putDirect(globalData->propertyNames->name, jsString(globalData, name.ustring()), DontDelete | ReadOnly | DontEnum); diff --git a/JavaScriptCore/runtime/InternalFunction.h b/JavaScriptCore/runtime/InternalFunction.h index 54d90ae..cc4b917 100644 --- a/JavaScriptCore/runtime/InternalFunction.h +++ b/JavaScriptCore/runtime/InternalFunction.h @@ -25,7 +25,7 @@ #define InternalFunction_h #include "JSObject.h" -#include "identifier.h" +#include "Identifier.h" namespace JSC { @@ -38,22 +38,22 @@ namespace JSC { const UString& name(JSGlobalData*); - static PassRefPtr<StructureID> createStructureID(JSValue* proto) + static PassRefPtr<Structure> createStructure(JSValuePtr proto) { - return StructureID::create(proto, TypeInfo(ObjectType, ImplementsHasInstance | HasStandardGetOwnPropertySlot)); + return Structure::create(proto, TypeInfo(ObjectType, ImplementsHasInstance | HasStandardGetOwnPropertySlot)); } protected: - InternalFunction(PassRefPtr<StructureID> structure) : JSObject(structure) { } - InternalFunction(JSGlobalData*, PassRefPtr<StructureID>, const Identifier&); + InternalFunction(PassRefPtr<Structure> structure) : JSObject(structure) { } + InternalFunction(JSGlobalData*, PassRefPtr<Structure>, const Identifier&); private: virtual CallType getCallData(CallData&) = 0; }; - InternalFunction* asInternalFunction(JSValue*); + InternalFunction* asInternalFunction(JSValuePtr); - inline InternalFunction* asInternalFunction(JSValue* value) + inline InternalFunction* asInternalFunction(JSValuePtr value) { ASSERT(asObject(value)->inherits(&InternalFunction::info)); return static_cast<InternalFunction*>(asObject(value)); diff --git a/JavaScriptCore/runtime/JSActivation.cpp b/JavaScriptCore/runtime/JSActivation.cpp index 9cb77e8..a2d2634 100644 --- a/JavaScriptCore/runtime/JSActivation.cpp +++ b/JavaScriptCore/runtime/JSActivation.cpp @@ -30,7 +30,7 @@ #include "JSActivation.h" #include "Arguments.h" -#include "Machine.h" +#include "Interpreter.h" #include "JSFunction.h" namespace JSC { @@ -40,7 +40,7 @@ ASSERT_CLASS_FITS_IN_CELL(JSActivation); const ClassInfo JSActivation::info = { "JSActivation", 0, 0, 0 }; JSActivation::JSActivation(CallFrame* callFrame, PassRefPtr<FunctionBodyNode> functionBody) - : Base(callFrame->globalData().activationStructureID, new JSActivationData(functionBody, callFrame)) + : Base(callFrame->globalData().activationStructure, new JSActivationData(functionBody, callFrame)) { } @@ -57,7 +57,7 @@ void JSActivation::mark() if (!registerArray) return; - size_t numParametersMinusThis = d()->functionBody->generatedByteCode().numParameters - 1; + size_t numParametersMinusThis = d()->functionBody->generatedBytecode().m_numParameters - 1; size_t i = 0; size_t count = numParametersMinusThis; @@ -67,7 +67,7 @@ void JSActivation::mark() r.mark(); } - size_t numVars = d()->functionBody->generatedByteCode().numVars; + size_t numVars = d()->functionBody->generatedBytecode().m_numVars; // Skip the call frame, which sits between the parameters and vars. i += RegisterFile::CallFrameHeaderSize; @@ -85,7 +85,7 @@ bool JSActivation::getOwnPropertySlot(ExecState* exec, const Identifier& propert if (symbolTableGet(propertyName, slot)) return true; - if (JSValue** location = getDirectLocation(propertyName)) { + if (JSValuePtr* location = getDirectLocation(propertyName)) { slot.setValueSlot(location); return true; } @@ -99,11 +99,11 @@ bool JSActivation::getOwnPropertySlot(ExecState* exec, const Identifier& propert // We don't call through to JSObject because there's no way to give an // activation object getter properties or a prototype. ASSERT(!hasGetterSetterProperties()); - ASSERT(prototype()->isNull()); + ASSERT(prototype().isNull()); return false; } -void JSActivation::put(ExecState*, const Identifier& propertyName, JSValue* value, PutPropertySlot& slot) +void JSActivation::put(ExecState*, const Identifier& propertyName, JSValuePtr value, PutPropertySlot& slot) { ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this)); @@ -118,7 +118,7 @@ void JSActivation::put(ExecState*, const Identifier& propertyName, JSValue* valu } // FIXME: Make this function honor ReadOnly (const) and DontEnum -void JSActivation::putWithAttributes(ExecState*, const Identifier& propertyName, JSValue* value, unsigned attributes) +void JSActivation::putWithAttributes(ExecState*, const Identifier& propertyName, JSValuePtr value, unsigned attributes) { ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this)); @@ -151,7 +151,7 @@ bool JSActivation::isDynamicScope() const return d()->functionBody->usesEval(); } -JSValue* JSActivation::argumentsGetter(ExecState* exec, const Identifier&, const PropertySlot& slot) +JSValuePtr JSActivation::argumentsGetter(ExecState* exec, const Identifier&, const PropertySlot& slot) { JSActivation* activation = asActivation(slot.slotBase()); diff --git a/JavaScriptCore/runtime/JSActivation.h b/JavaScriptCore/runtime/JSActivation.h index 16d131b..5e82bdc 100644 --- a/JavaScriptCore/runtime/JSActivation.h +++ b/JavaScriptCore/runtime/JSActivation.h @@ -33,7 +33,7 @@ #include "JSVariableObject.h" #include "RegisterFile.h" #include "SymbolTable.h" -#include "nodes.h" +#include "Nodes.h" namespace JSC { @@ -50,11 +50,13 @@ namespace JSC { virtual bool isDynamicScope() const; + virtual bool isActivationObject() const { return true; } + virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&); - virtual void put(ExecState*, const Identifier&, JSValue*, PutPropertySlot&); + virtual void put(ExecState*, const Identifier&, JSValuePtr, PutPropertySlot&); - virtual void putWithAttributes(ExecState*, const Identifier&, JSValue*, unsigned attributes); + virtual void putWithAttributes(ExecState*, const Identifier&, JSValuePtr, unsigned attributes); virtual bool deleteProperty(ExecState*, const Identifier& propertyName); virtual JSObject* toThisObject(ExecState*) const; @@ -64,12 +66,12 @@ namespace JSC { virtual const ClassInfo* classInfo() const { return &info; } static const ClassInfo info; - static PassRefPtr<StructureID> createStructureID(JSValue* proto) { return StructureID::create(proto, TypeInfo(ObjectType, NeedsThisConversion)); } + static PassRefPtr<Structure> createStructure(JSValuePtr proto) { return Structure::create(proto, TypeInfo(ObjectType, NeedsThisConversion)); } private: struct JSActivationData : public JSVariableObjectData { JSActivationData(PassRefPtr<FunctionBodyNode> functionBody, Register* registers) - : JSVariableObjectData(&functionBody->symbolTable(), registers) + : JSVariableObjectData(&functionBody->generatedBytecode().symbolTable(), registers) , functionBody(functionBody) { } @@ -77,15 +79,15 @@ namespace JSC { RefPtr<FunctionBodyNode> functionBody; }; - static JSValue* argumentsGetter(ExecState*, const Identifier&, const PropertySlot&); + static JSValuePtr argumentsGetter(ExecState*, const Identifier&, const PropertySlot&); NEVER_INLINE PropertySlot::GetValueFunc getArgumentsGetter(); JSActivationData* d() const { return static_cast<JSActivationData*>(JSVariableObject::d); } }; - JSActivation* asActivation(JSValue*); + JSActivation* asActivation(JSValuePtr); - inline JSActivation* asActivation(JSValue* value) + inline JSActivation* asActivation(JSValuePtr value) { ASSERT(asObject(value)->inherits(&JSActivation::info)); return static_cast<JSActivation*>(asObject(value)); diff --git a/JavaScriptCore/runtime/JSArray.cpp b/JavaScriptCore/runtime/JSArray.cpp index d2d38a4..89a2b45 100644 --- a/JavaScriptCore/runtime/JSArray.cpp +++ b/JavaScriptCore/runtime/JSArray.cpp @@ -27,11 +27,12 @@ #include "PropertyNameArray.h" #include <wtf/AVLTree.h> #include <wtf/Assertions.h> -#include <operations.h> +#include <Operations.h> #define CHECK_ARRAY_CONSISTENCY 0 using namespace std; +using namespace WTF; namespace JSC { @@ -64,9 +65,9 @@ ASSERT_CLASS_FITS_IN_CELL(JSArray); // The definition of MAX_STORAGE_VECTOR_LENGTH is dependant on the definition storageSize // function below - the MAX_STORAGE_VECTOR_LENGTH limit is defined such that the storage -// size calculation cannot overflow. (sizeof(ArrayStorage) - sizeof(JSValue*)) + -// (vectorLength * sizeof(JSValue*)) must be <= 0xFFFFFFFFU (which is maximum value of size_t). -#define MAX_STORAGE_VECTOR_LENGTH static_cast<unsigned>((0xFFFFFFFFU - (sizeof(ArrayStorage) - sizeof(JSValue*))) / sizeof(JSValue*)) +// size calculation cannot overflow. (sizeof(ArrayStorage) - sizeof(JSValuePtr)) + +// (vectorLength * sizeof(JSValuePtr)) must be <= 0xFFFFFFFFU (which is maximum value of size_t). +#define MAX_STORAGE_VECTOR_LENGTH static_cast<unsigned>((0xFFFFFFFFU - (sizeof(ArrayStorage) - sizeof(JSValuePtr))) / sizeof(JSValuePtr)) // These values have to be macros to be used in max() and min() without introducing // a PIC branch in Mach-O binaries, see <rdar://problem/5971391>. @@ -89,10 +90,10 @@ static inline size_t storageSize(unsigned vectorLength) // MAX_STORAGE_VECTOR_LENGTH is defined such that provided (vectorLength <= MAX_STORAGE_VECTOR_LENGTH) // - as asserted above - the following calculation cannot overflow. - size_t size = (sizeof(ArrayStorage) - sizeof(JSValue*)) + (vectorLength * sizeof(JSValue*)); + size_t size = (sizeof(ArrayStorage) - sizeof(JSValuePtr)) + (vectorLength * sizeof(JSValuePtr)); // Assertion to detect integer overflow in previous calculation (should not be possible, provided that // MAX_STORAGE_VECTOR_LENGTH is correctly defined). - ASSERT(((size - (sizeof(ArrayStorage) - sizeof(JSValue*))) / sizeof(JSValue*) == vectorLength) && (size >= (sizeof(ArrayStorage) - sizeof(JSValue*)))); + ASSERT(((size - (sizeof(ArrayStorage) - sizeof(JSValuePtr))) / sizeof(JSValuePtr) == vectorLength) && (size >= (sizeof(ArrayStorage) - sizeof(JSValuePtr)))); return size; } @@ -125,8 +126,8 @@ inline void JSArray::checkConsistency(ConsistencyCheckType) #endif -JSArray::JSArray(PassRefPtr<StructureID> structureID) - : JSObject(structureID) +JSArray::JSArray(PassRefPtr<Structure> structure) + : JSObject(structure) { unsigned initialCapacity = 0; @@ -138,7 +139,7 @@ JSArray::JSArray(PassRefPtr<StructureID> structureID) checkConsistency(); } -JSArray::JSArray(PassRefPtr<StructureID> structure, unsigned initialLength) +JSArray::JSArray(PassRefPtr<Structure> structure, unsigned initialLength) : JSObject(structure) { unsigned initialCapacity = min(initialLength, MIN_SPARSE_ARRAY_INDEX); @@ -148,12 +149,12 @@ JSArray::JSArray(PassRefPtr<StructureID> structure, unsigned initialLength) m_storage->m_vectorLength = initialCapacity; m_storage->m_length = initialLength; - Heap::heap(this)->reportExtraMemoryCost(initialCapacity * sizeof(JSValue*)); + Heap::heap(this)->reportExtraMemoryCost(initialCapacity * sizeof(JSValuePtr)); checkConsistency(); } -JSArray::JSArray(ExecState* exec, PassRefPtr<StructureID> structure, const ArgList& list) +JSArray::JSArray(ExecState* exec, PassRefPtr<Structure> structure, const ArgList& list) : JSObject(structure) { unsigned length = list.size(); @@ -174,8 +175,7 @@ JSArray::JSArray(ExecState* exec, PassRefPtr<StructureID> structure, const ArgLi m_storage = storage; - // When the array is created non-empty, its cells are filled, so it's really no worse than - // a property map. Therefore don't report extra memory cost. + Heap::heap(this)->reportExtraMemoryCost(storageSize(length)); checkConsistency(); } @@ -199,7 +199,7 @@ bool JSArray::getOwnPropertySlot(ExecState* exec, unsigned i, PropertySlot& slot } if (i < storage->m_vectorLength) { - JSValue*& valueSlot = storage->m_vector[i]; + JSValuePtr& valueSlot = storage->m_vector[i]; if (valueSlot) { slot.setValueSlot(&valueSlot); return true; @@ -233,7 +233,7 @@ bool JSArray::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName } // ECMA 15.4.5.1 -void JSArray::put(ExecState* exec, const Identifier& propertyName, JSValue* value, PutPropertySlot& slot) +void JSArray::put(ExecState* exec, const Identifier& propertyName, JSValuePtr value, PutPropertySlot& slot) { bool isArrayIndex; unsigned i = propertyName.toArrayIndex(&isArrayIndex); @@ -243,8 +243,8 @@ void JSArray::put(ExecState* exec, const Identifier& propertyName, JSValue* valu } if (propertyName == exec->propertyNames().length) { - unsigned newLength = value->toUInt32(exec); - if (value->toNumber(exec) != static_cast<double>(newLength)) { + unsigned newLength = value.toUInt32(exec); + if (value.toNumber(exec) != static_cast<double>(newLength)) { throwError(exec, RangeError, "Invalid array length."); return; } @@ -255,7 +255,7 @@ void JSArray::put(ExecState* exec, const Identifier& propertyName, JSValue* valu JSObject::put(exec, propertyName, value, slot); } -void JSArray::put(ExecState* exec, unsigned i, JSValue* value) +void JSArray::put(ExecState* exec, unsigned i, JSValuePtr value) { checkConsistency(); @@ -266,7 +266,7 @@ void JSArray::put(ExecState* exec, unsigned i, JSValue* value) } if (i < m_storage->m_vectorLength) { - JSValue*& valueSlot = m_storage->m_vector[i]; + JSValuePtr& valueSlot = m_storage->m_vector[i]; if (valueSlot) { valueSlot = value; checkConsistency(); @@ -282,7 +282,7 @@ void JSArray::put(ExecState* exec, unsigned i, JSValue* value) putSlowCase(exec, i, value); } -NEVER_INLINE void JSArray::putSlowCase(ExecState* exec, unsigned i, JSValue* value) +NEVER_INLINE void JSArray::putSlowCase(ExecState* exec, unsigned i, JSValuePtr value) { ArrayStorage* storage = m_storage; SparseArrayValueMap* map = storage->m_sparseValueMap; @@ -348,6 +348,9 @@ NEVER_INLINE void JSArray::putSlowCase(ExecState* exec, unsigned i, JSValue* val } unsigned vectorLength = storage->m_vectorLength; + + Heap::heap(this)->reportExtraMemoryCost(storageSize(newVectorLength) - storageSize(vectorLength)); + if (newNumValuesInVector == storage->m_numValuesInVector + 1) { for (unsigned j = vectorLength; j < newVectorLength; ++j) storage->m_vector[j] = noValue(); @@ -390,7 +393,7 @@ bool JSArray::deleteProperty(ExecState* exec, unsigned i) ArrayStorage* storage = m_storage; if (i < storage->m_vectorLength) { - JSValue*& valueSlot = storage->m_vector[i]; + JSValuePtr& valueSlot = storage->m_vector[i]; if (!valueSlot) { checkConsistency(); return false; @@ -461,6 +464,7 @@ bool JSArray::increaseVectorLength(unsigned newLength) if (!storage) return false; + Heap::heap(this)->reportExtraMemoryCost(storageSize(newVectorLength) - storageSize(vectorLength)); storage->m_vectorLength = newVectorLength; for (unsigned i = vectorLength; i < newVectorLength; ++i) @@ -484,7 +488,7 @@ void JSArray::setLength(unsigned newLength) unsigned usedVectorLength = min(length, storage->m_vectorLength); for (unsigned i = newLength; i < usedVectorLength; ++i) { - JSValue*& valueSlot = storage->m_vector[i]; + JSValuePtr& valueSlot = storage->m_vector[i]; bool hadValue = valueSlot; valueSlot = noValue(); storage->m_numValuesInVector -= hadValue; @@ -509,7 +513,7 @@ void JSArray::setLength(unsigned newLength) checkConsistency(); } -JSValue* JSArray::pop() +JSValuePtr JSArray::pop() { checkConsistency(); @@ -519,17 +523,17 @@ JSValue* JSArray::pop() --length; - JSValue* result; + JSValuePtr result; if (m_fastAccessCutoff > length) { - JSValue*& valueSlot = m_storage->m_vector[length]; + JSValuePtr& valueSlot = m_storage->m_vector[length]; result = valueSlot; ASSERT(result); valueSlot = noValue(); --m_storage->m_numValuesInVector; m_fastAccessCutoff = length; } else if (length < m_storage->m_vectorLength) { - JSValue*& valueSlot = m_storage->m_vector[length]; + JSValuePtr& valueSlot = m_storage->m_vector[length]; result = valueSlot; valueSlot = noValue(); if (result) @@ -558,7 +562,7 @@ JSValue* JSArray::pop() return result; } -void JSArray::push(ExecState* exec, JSValue* value) +void JSArray::push(ExecState* exec, JSValuePtr value) { checkConsistency(); @@ -598,30 +602,68 @@ void JSArray::mark() unsigned usedVectorLength = min(storage->m_length, storage->m_vectorLength); for (unsigned i = 0; i < usedVectorLength; ++i) { - JSValue* value = storage->m_vector[i]; - if (value && !value->marked()) - value->mark(); + JSValuePtr value = storage->m_vector[i]; + if (value && !value.marked()) + value.mark(); } if (SparseArrayValueMap* map = storage->m_sparseValueMap) { SparseArrayValueMap::iterator end = map->end(); for (SparseArrayValueMap::iterator it = map->begin(); it != end; ++it) { - JSValue* value = it->second; - if (!value->marked()) - value->mark(); + JSValuePtr value = it->second; + if (!value.marked()) + value.mark(); } } } -typedef std::pair<JSValue*, UString> ArrayQSortPair; +static int compareNumbersForQSort(const void* a, const void* b) +{ + double da = static_cast<const JSValuePtr*>(a)->uncheckedGetNumber(); + double db = static_cast<const JSValuePtr*>(b)->uncheckedGetNumber(); + return (da > db) - (da < db); +} + +typedef std::pair<JSValuePtr, UString> ValueStringPair; static int compareByStringPairForQSort(const void* a, const void* b) { - const ArrayQSortPair* va = static_cast<const ArrayQSortPair*>(a); - const ArrayQSortPair* vb = static_cast<const ArrayQSortPair*>(b); + const ValueStringPair* va = static_cast<const ValueStringPair*>(a); + const ValueStringPair* vb = static_cast<const ValueStringPair*>(b); return compare(va->second, vb->second); } +void JSArray::sortNumeric(ExecState* exec, JSValuePtr compareFunction, CallType callType, const CallData& callData) +{ + unsigned lengthNotIncludingUndefined = compactForSorting(); + if (m_storage->m_sparseValueMap) { + throwOutOfMemoryError(exec); + return; + } + + if (!lengthNotIncludingUndefined) + return; + + bool allValuesAreNumbers = true; + size_t size = m_storage->m_numValuesInVector; + for (size_t i = 0; i < size; ++i) { + if (!m_storage->m_vector[i].isNumber()) { + allValuesAreNumbers = false; + break; + } + } + + if (!allValuesAreNumbers) + return sort(exec, compareFunction, callType, callData); + + // For numeric comparison, which is fast, qsort is faster than mergesort. We + // also don't require mergesort's stability, since there's no user visible + // side-effect from swapping the order of equal primitive values. + qsort(m_storage->m_vector, size, sizeof(JSValuePtr), compareNumbersForQSort); + + checkConsistency(SortConsistencyCheck); +} + void JSArray::sort(ExecState* exec) { unsigned lengthNotIncludingUndefined = compactForSorting(); @@ -638,15 +680,15 @@ void JSArray::sort(ExecState* exec) // buffer. Besides, this protects us from crashing if some objects have custom toString methods that return // random or otherwise changing results, effectively making compare function inconsistent. - Vector<ArrayQSortPair> values(lengthNotIncludingUndefined); + Vector<ValueStringPair> values(lengthNotIncludingUndefined); if (!values.begin()) { throwOutOfMemoryError(exec); return; } for (size_t i = 0; i < lengthNotIncludingUndefined; i++) { - JSValue* value = m_storage->m_vector[i]; - ASSERT(!value->isUndefined()); + JSValuePtr value = m_storage->m_vector[i]; + ASSERT(!value.isUndefined()); values[i].first = value; } @@ -657,7 +699,7 @@ void JSArray::sort(ExecState* exec) // a toString call raises an exception. for (size_t i = 0; i < lengthNotIncludingUndefined; i++) - values[i].second = values[i].first->toString(exec); + values[i].second = values[i].first.toString(exec); if (exec->hadException()) return; @@ -666,11 +708,11 @@ void JSArray::sort(ExecState* exec) // than O(N log N). #if HAVE(MERGESORT) - mergesort(values.begin(), values.size(), sizeof(ArrayQSortPair), compareByStringPairForQSort); + 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. - qsort(values.begin(), values.size(), sizeof(ArrayQSortPair), compareByStringPairForQSort); + qsort(values.begin(), values.size(), sizeof(ValueStringPair), compareByStringPairForQSort); #endif // FIXME: If the toString function changed the length of the array, this might be @@ -683,7 +725,7 @@ void JSArray::sort(ExecState* exec) } struct AVLTreeNodeForArrayCompare { - JSValue* value; + JSValuePtr value; // Child pointers. The high bit of gt is robbed and used as the // balance factor sign. The high bit of lt is robbed and used as @@ -694,15 +736,15 @@ struct AVLTreeNodeForArrayCompare { struct AVLTreeAbstractorForArrayCompare { typedef int32_t handle; // Handle is an index into m_nodes vector. - typedef JSValue* key; + typedef JSValuePtr key; typedef int32_t size; Vector<AVLTreeNodeForArrayCompare> m_nodes; ExecState* m_exec; - JSValue* m_compareFunction; + JSValuePtr m_compareFunction; CallType m_compareCallType; const CallData* m_compareCallData; - JSValue* m_globalThisValue; + JSValuePtr m_globalThisValue; handle get_less(handle h) { return m_nodes[h].lt & 0x7FFFFFFF; } void set_less(handle h, handle lh) { m_nodes[h].lt &= 0x80000000; m_nodes[h].lt |= lh; } @@ -732,8 +774,8 @@ struct AVLTreeAbstractorForArrayCompare { int compare_key_key(key va, key vb) { - ASSERT(!va->isUndefined()); - ASSERT(!vb->isUndefined()); + ASSERT(!va.isUndefined()); + ASSERT(!vb.isUndefined()); if (m_exec->hadException()) return 1; @@ -741,7 +783,7 @@ struct AVLTreeAbstractorForArrayCompare { ArgList arguments; arguments.append(va); arguments.append(vb); - double compareResult = call(m_exec, m_compareFunction, m_compareCallType, *m_compareCallData, m_globalThisValue, arguments)->toNumber(m_exec); + double compareResult = call(m_exec, m_compareFunction, m_compareCallType, *m_compareCallData, m_globalThisValue, arguments).toNumber(m_exec); return (compareResult < 0) ? -1 : 1; // Not passing equality through, because we need to store all values, even if equivalent. } @@ -751,7 +793,7 @@ struct AVLTreeAbstractorForArrayCompare { static handle null() { return 0x7FFFFFFF; } }; -void JSArray::sort(ExecState* exec, JSValue* compareFunction, CallType callType, const CallData& callData) +void JSArray::sort(ExecState* exec, JSValuePtr compareFunction, CallType callType, const CallData& callData) { checkConsistency(); @@ -789,15 +831,16 @@ void JSArray::sort(ExecState* exec, JSValue* compareFunction, CallType callType, // Iterate over the array, ignoring missing values, counting undefined ones, and inserting all other ones into the tree. for (; numDefined < usedVectorLength; ++numDefined) { - JSValue* v = m_storage->m_vector[numDefined]; - if (!v || v->isUndefined()) + JSValuePtr v = m_storage->m_vector[numDefined]; + if (!v || v.isUndefined()) break; tree.abstractor().m_nodes[numDefined].value = v; tree.insert(numDefined); } for (unsigned i = numDefined; i < usedVectorLength; ++i) { - if (JSValue* v = m_storage->m_vector[i]) { - if (v->isUndefined()) + JSValuePtr v = m_storage->m_vector[i]; + if (v) { + if (v.isUndefined()) ++numUndefined; else { tree.abstractor().m_nodes[numDefined].value = v; @@ -879,13 +922,14 @@ unsigned JSArray::compactForSorting() unsigned numUndefined = 0; for (; numDefined < usedVectorLength; ++numDefined) { - JSValue* v = storage->m_vector[numDefined]; - if (!v || v->isUndefined()) + JSValuePtr v = storage->m_vector[numDefined]; + if (!v || v.isUndefined()) break; } for (unsigned i = numDefined; i < usedVectorLength; ++i) { - if (JSValue* v = storage->m_vector[i]) { - if (v->isUndefined()) + JSValuePtr v = storage->m_vector[i]; + if (v) { + if (v.isUndefined()) ++numUndefined; else storage->m_vector[numDefined++] = v; @@ -948,7 +992,7 @@ void JSArray::checkConsistency(ConsistencyCheckType type) unsigned numValuesInVector = 0; for (unsigned i = 0; i < m_storage->m_vectorLength; ++i) { - if (JSValue* value = m_storage->m_vector[i]) { + if (JSValuePtr value = m_storage->m_vector[i]) { ASSERT(i < m_storage->m_length); if (type != DestructorConsistencyCheck) value->type(); // Likely to crash if the object was deallocated. @@ -987,7 +1031,7 @@ JSArray* constructEmptyArray(ExecState* exec, unsigned initialLength) return new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure(), initialLength); } -JSArray* constructArray(ExecState* exec, JSValue* singleItemValue) +JSArray* constructArray(ExecState* exec, JSValuePtr singleItemValue) { ArgList values; values.append(singleItemValue); diff --git a/JavaScriptCore/runtime/JSArray.h b/JavaScriptCore/runtime/JSArray.h index 165fafd..7eecf33 100644 --- a/JavaScriptCore/runtime/JSArray.h +++ b/JavaScriptCore/runtime/JSArray.h @@ -25,7 +25,7 @@ namespace JSC { - typedef HashMap<unsigned, JSValue*> SparseArrayValueMap; + typedef HashMap<unsigned, JSValuePtr> SparseArrayValueMap; struct ArrayStorage { unsigned m_length; @@ -33,21 +33,21 @@ namespace JSC { unsigned m_numValuesInVector; SparseArrayValueMap* m_sparseValueMap; void* lazyCreationData; // A JSArray subclass can use this to fill the vector lazily. - JSValue* m_vector[1]; + JSValuePtr m_vector[1]; }; class JSArray : public JSObject { - friend class CTI; + friend class JIT; public: - explicit JSArray(PassRefPtr<StructureID>); - JSArray(PassRefPtr<StructureID>, unsigned initialLength); - JSArray(ExecState*, PassRefPtr<StructureID>, const ArgList& initialValues); + explicit JSArray(PassRefPtr<Structure>); + JSArray(PassRefPtr<Structure>, unsigned initialLength); + JSArray(ExecState*, PassRefPtr<Structure>, const ArgList& initialValues); virtual ~JSArray(); virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&); - virtual void put(ExecState*, unsigned propertyName, JSValue*); // FIXME: Make protected and add setItem. + virtual void put(ExecState*, unsigned propertyName, JSValuePtr); // FIXME: Make protected and add setItem. static const ClassInfo info; @@ -55,20 +55,21 @@ namespace JSC { void setLength(unsigned); // OK to use on new arrays, but not if it might be a RegExpMatchArray. void sort(ExecState*); - void sort(ExecState*, JSValue* compareFunction, CallType, const CallData&); + void sort(ExecState*, JSValuePtr compareFunction, CallType, const CallData&); + void sortNumeric(ExecState*, JSValuePtr compareFunction, CallType, const CallData&); - void push(ExecState*, JSValue*); - JSValue* pop(); + void push(ExecState*, JSValuePtr); + JSValuePtr pop(); bool canGetIndex(unsigned i) { return i < m_fastAccessCutoff; } - JSValue* getIndex(unsigned i) + JSValuePtr getIndex(unsigned i) { ASSERT(canGetIndex(i)); return m_storage->m_vector[i]; } bool canSetIndex(unsigned i) { return i < m_fastAccessCutoff; } - JSValue* setIndex(unsigned i, JSValue* v) + JSValuePtr setIndex(unsigned i, JSValuePtr v) { ASSERT(canSetIndex(i)); return m_storage->m_vector[i] = v; @@ -76,13 +77,13 @@ namespace JSC { void fillArgList(ExecState*, ArgList&); - static PassRefPtr<StructureID> createStructureID(JSValue* prototype) + static PassRefPtr<Structure> createStructure(JSValuePtr prototype) { - return StructureID::create(prototype, TypeInfo(ObjectType)); + return Structure::create(prototype, TypeInfo(ObjectType)); } protected: - virtual void put(ExecState*, const Identifier& propertyName, JSValue*, PutPropertySlot&); + virtual void put(ExecState*, const Identifier& propertyName, JSValuePtr, PutPropertySlot&); virtual bool deleteProperty(ExecState*, const Identifier& propertyName); virtual bool deleteProperty(ExecState*, unsigned propertyName); virtual void getPropertyNames(ExecState*, PropertyNameArray&); @@ -95,7 +96,7 @@ namespace JSC { virtual const ClassInfo* classInfo() const { return &info; } bool getOwnPropertySlotSlowCase(ExecState*, unsigned propertyName, PropertySlot&); - void putSlowCase(ExecState*, unsigned propertyName, JSValue*); + void putSlowCase(ExecState*, unsigned propertyName, JSValuePtr); bool increaseVectorLength(unsigned newLength); @@ -108,14 +109,14 @@ namespace JSC { ArrayStorage* m_storage; }; - JSArray* asArray(JSValue*); + JSArray* asArray(JSValuePtr); JSArray* constructEmptyArray(ExecState*); JSArray* constructEmptyArray(ExecState*, unsigned initialLength); - JSArray* constructArray(ExecState*, JSValue* singleItemValue); + JSArray* constructArray(ExecState*, JSValuePtr singleItemValue); JSArray* constructArray(ExecState*, const ArgList& values); - inline JSArray* asArray(JSValue* value) + inline JSArray* asArray(JSValuePtr value) { ASSERT(asObject(value)->inherits(&JSArray::info)); return static_cast<JSArray*>(asObject(value)); diff --git a/JavaScriptCore/runtime/JSByteArray.cpp b/JavaScriptCore/runtime/JSByteArray.cpp new file mode 100644 index 0000000..54cf7cb --- /dev/null +++ b/JavaScriptCore/runtime/JSByteArray.cpp @@ -0,0 +1,97 @@ +/* + * 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_defaultInfo = { "ByteArray", 0, 0, 0 }; + +JSByteArray::JSByteArray(ExecState* exec, PassRefPtr<Structure> structure, ByteArray* storage, const JSC::ClassInfo* classInfo) + : JSObject(structure) + , m_storage(storage) + , m_classInfo(classInfo) +{ + putDirect(exec->globalData().propertyNames->length, jsNumber(exec, m_storage->length()), ReadOnly | DontDelete); +} + +PassRefPtr<Structure> JSByteArray::createStructure(JSValuePtr prototype) +{ + PassRefPtr<Structure> result = Structure::create(prototype, TypeInfo(ObjectType)); + return result; +} + +bool JSByteArray::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) +{ + bool ok; + unsigned index = propertyName.toUInt32(&ok, false); + if (ok && canAccessIndex(index)) { + slot.setValue(getIndex(exec, index)); + return true; + } + return JSObject::getOwnPropertySlot(exec, propertyName, slot); +} + +bool JSByteArray::getOwnPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot) +{ + if (canAccessIndex(propertyName)) { + slot.setValue(getIndex(exec, propertyName)); + return true; + } + return JSObject::getOwnPropertySlot(exec, Identifier::from(exec, propertyName), slot); +} + +void JSByteArray::put(ExecState* exec, const Identifier& propertyName, JSValuePtr value, PutPropertySlot& slot) +{ + bool ok; + unsigned index = propertyName.toUInt32(&ok, false); + if (ok) { + setIndex(exec, index, value); + return; + } + JSObject::put(exec, propertyName, value, slot); +} + +void JSByteArray::put(ExecState* exec, unsigned propertyName, JSValuePtr value) +{ + setIndex(exec, propertyName, value); +} + +void JSByteArray::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames) +{ + unsigned length = m_storage->length(); + for (unsigned i = 0; i < length; ++i) + propertyNames.add(Identifier::from(exec, i)); + JSObject::getPropertyNames(exec, propertyNames); +} + +} + diff --git a/JavaScriptCore/runtime/JSByteArray.h b/JavaScriptCore/runtime/JSByteArray.h new file mode 100644 index 0000000..19c8f0e --- /dev/null +++ b/JavaScriptCore/runtime/JSByteArray.h @@ -0,0 +1,110 @@ +/* + * 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 JSObject { + friend class Interpreter; + public: + bool canAccessIndex(unsigned i) { return i < m_storage->length(); } + JSValuePtr getIndex(ExecState* exec, unsigned i) + { + ASSERT(canAccessIndex(i)); + return jsNumber(exec, 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, JSValuePtr value) + { + double byteValue = value.toNumber(exec); + if (exec->hadException()) + return; + if (canAccessIndex(i)) + setIndex(i, byteValue); + } + + JSByteArray(ExecState* exec, PassRefPtr<Structure>, WTF::ByteArray* storage, const JSC::ClassInfo* = &s_defaultInfo); + static PassRefPtr<Structure> createStructure(JSValuePtr prototype); + + virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertySlot&); + virtual bool getOwnPropertySlot(JSC::ExecState*, unsigned propertyName, JSC::PropertySlot&); + virtual void put(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSValuePtr, JSC::PutPropertySlot&); + virtual void put(JSC::ExecState*, unsigned propertyName, JSC::JSValuePtr); + + virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&); + + virtual const ClassInfo* classInfo() const { return m_classInfo; } + static const ClassInfo s_defaultInfo; + + size_t length() const { return m_storage->length(); } + + private: + enum VPtrStealingHackType { VPtrStealingHack }; + JSByteArray(VPtrStealingHackType) + : JSObject(createStructure(jsNull())) + , m_classInfo(0) + { + } + + RefPtr<WTF::ByteArray> m_storage; + const ClassInfo* m_classInfo; + }; + + JSByteArray* asByteArray(JSValuePtr value); + inline JSByteArray* asByteArray(JSValuePtr value) + { + return static_cast<JSByteArray*>(asCell(value)); + } +} + +#endif diff --git a/JavaScriptCore/runtime/JSCell.cpp b/JavaScriptCore/runtime/JSCell.cpp index cfe2f72..d449deb 100644 --- a/JavaScriptCore/runtime/JSCell.cpp +++ b/JavaScriptCore/runtime/JSCell.cpp @@ -100,19 +100,6 @@ bool JSCell::getTruncatedUInt32(uint32_t&) const return false; } -bool JSCell::getNumber(double& numericValue) const -{ - if (!isNumber()) - return false; - numericValue = static_cast<const JSNumberCell*>(this)->value(); - return true; -} - -double JSCell::getNumber() const -{ - return isNumber() ? static_cast<const JSNumberCell*>(this)->value() : NaN; -} - bool JSCell::getString(UString&stringValue) const { if (!isString()) @@ -170,12 +157,12 @@ bool JSCell::getOwnPropertySlot(ExecState* exec, unsigned identifier, PropertySl return true; } -void JSCell::put(ExecState* exec, const Identifier& identifier, JSValue* value, PutPropertySlot& slot) +void JSCell::put(ExecState* exec, const Identifier& identifier, JSValuePtr value, PutPropertySlot& slot) { toObject(exec)->put(exec, identifier, value, slot); } -void JSCell::put(ExecState* exec, unsigned identifier, JSValue* value) +void JSCell::put(ExecState* exec, unsigned identifier, JSValuePtr value) { toObject(exec)->put(exec, identifier, value); } @@ -210,7 +197,7 @@ const ClassInfo* JSCell::classInfo() const return 0; } -JSValue* JSCell::getJSNumber() +JSValuePtr JSCell::getJSNumber() { return noValue(); } diff --git a/JavaScriptCore/runtime/JSCell.h b/JavaScriptCore/runtime/JSCell.h index 108dab6..43d81a5 100644 --- a/JavaScriptCore/runtime/JSCell.h +++ b/JavaScriptCore/runtime/JSCell.h @@ -23,25 +23,27 @@ #ifndef JSCell_h #define JSCell_h -#include "StructureID.h" +#include <wtf/Noncopyable.h> +#include "Structure.h" #include "JSValue.h" -#include "collector.h" +#include "JSImmediate.h" +#include "Collector.h" namespace JSC { - class JSCell : public JSValue { - friend class CTI; + class JSCell : Noncopyable { + friend class JIT; friend class GetterSetter; friend class Heap; friend class JSNumberCell; friend class JSObject; friend class JSPropertyNameIterator; friend class JSString; - friend class JSValue; - friend class Machine; + friend class JSValuePtr; + friend class Interpreter; private: - explicit JSCell(StructureID*); + explicit JSCell(Structure*); virtual ~JSCell(); public: @@ -52,11 +54,9 @@ namespace JSC { virtual bool isGetterSetter() const; virtual bool isObject(const ClassInfo*) const; - StructureID* structureID() const; + Structure* structure() const; // Extracting the value. - bool getNumber(double&) const; - double getNumber() const; // NaN if not a number bool getString(UString&) const; UString getString() const; // null string if not a string JSObject* getObject(); // NULL if not an object @@ -66,13 +66,14 @@ namespace JSC { virtual ConstructType getConstructData(ConstructData&); // Extracting integer values. + // FIXME: remove these methods, can check isNumberCell in JSValuePtr && then call asNumberCell::*. virtual bool getUInt32(uint32_t&) const; virtual bool getTruncatedInt32(int32_t&) const; virtual bool getTruncatedUInt32(uint32_t&) const; // Basic conversions. - virtual JSValue* toPrimitive(ExecState*, PreferredPrimitiveType) const = 0; - virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue*&) = 0; + virtual JSValuePtr toPrimitive(ExecState*, PreferredPrimitiveType) const = 0; + virtual bool getPrimitiveNumber(ExecState*, double& number, JSValuePtr&) = 0; virtual bool toBoolean(ExecState*) const = 0; virtual double toNumber(ExecState*) const = 0; virtual UString toString(ExecState*) const = 0; @@ -87,15 +88,15 @@ namespace JSC { // Object operations, with the toObject operation included. virtual const ClassInfo* classInfo() const; - virtual void put(ExecState*, const Identifier& propertyName, JSValue*, PutPropertySlot&); - virtual void put(ExecState*, unsigned propertyName, JSValue*); + virtual void put(ExecState*, const Identifier& propertyName, JSValuePtr, PutPropertySlot&); + virtual void put(ExecState*, unsigned propertyName, JSValuePtr); virtual bool deleteProperty(ExecState*, const Identifier& propertyName); virtual bool deleteProperty(ExecState*, unsigned propertyName); virtual JSObject* toThisObject(ExecState*) const; virtual UString toThisString(ExecState*) const; virtual JSString* toThisJSString(ExecState*); - virtual JSValue* getJSNumber(); + virtual JSValuePtr getJSNumber(); void* vptr() { return *reinterpret_cast<void**>(this); } private: @@ -104,19 +105,18 @@ namespace JSC { virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&); - StructureID* m_structureID; + Structure* m_structure; }; - JSCell* asCell(JSValue*); + JSCell* asCell(JSValuePtr); - inline JSCell* asCell(JSValue* value) + inline JSCell* asCell(JSValuePtr value) { - ASSERT(!JSImmediate::isImmediate(value)); - return static_cast<JSCell*>(value); + return value.asCell(); } - inline JSCell::JSCell(StructureID* structureID) - : m_structureID(structureID) + inline JSCell::JSCell(Structure* structure) + : m_structure(structure) { } @@ -131,17 +131,17 @@ namespace JSC { inline bool JSCell::isObject() const { - return m_structureID->typeInfo().type() == ObjectType; + return m_structure->typeInfo().type() == ObjectType; } inline bool JSCell::isString() const { - return m_structureID->typeInfo().type() == StringType; + return m_structure->typeInfo().type() == StringType; } - inline StructureID* JSCell::structureID() const + inline Structure* JSCell::structure() const { - return m_structureID; + return m_structure; } inline bool JSCell::marked() const @@ -154,10 +154,10 @@ namespace JSC { return Heap::markCell(this); } - ALWAYS_INLINE JSCell* JSValue::asCell() const + ALWAYS_INLINE JSCell* JSValuePtr::asCell() const { - ASSERT(!JSImmediate::isImmediate(asValue())); - return reinterpret_cast<JSCell*>(const_cast<JSValue*>(this)); + ASSERT(isCell()); + return m_ptr; } inline void* JSCell::operator new(size_t size, JSGlobalData* globalData) @@ -171,87 +171,77 @@ namespace JSC { // --- JSValue inlines ---------------------------- - inline bool JSValue::isNumber() const - { - return JSImmediate::isNumber(asValue()) || (!JSImmediate::isImmediate(asValue()) && asCell()->isNumber()); - } - - inline bool JSValue::isString() const + inline bool JSValuePtr::isString() const { return !JSImmediate::isImmediate(asValue()) && asCell()->isString(); } - inline bool JSValue::isGetterSetter() const + inline bool JSValuePtr::isGetterSetter() const { return !JSImmediate::isImmediate(asValue()) && asCell()->isGetterSetter(); } - inline bool JSValue::isObject() const + inline bool JSValuePtr::isObject() const { return !JSImmediate::isImmediate(asValue()) && asCell()->isObject(); } - inline double JSValue::getNumber() const - { - return JSImmediate::isImmediate(asValue()) ? JSImmediate::toDouble(asValue()) : asCell()->getNumber(); - } - - inline bool JSValue::getString(UString& s) const + inline bool JSValuePtr::getString(UString& s) const { return !JSImmediate::isImmediate(asValue()) && asCell()->getString(s); } - inline UString JSValue::getString() const + inline UString JSValuePtr::getString() const { return JSImmediate::isImmediate(asValue()) ? UString() : asCell()->getString(); } - inline JSObject* JSValue::getObject() const + inline JSObject* JSValuePtr::getObject() const { return JSImmediate::isImmediate(asValue()) ? 0 : asCell()->getObject(); } - inline CallType JSValue::getCallData(CallData& callData) + inline CallType JSValuePtr::getCallData(CallData& callData) { return JSImmediate::isImmediate(asValue()) ? CallTypeNone : asCell()->getCallData(callData); } - inline ConstructType JSValue::getConstructData(ConstructData& constructData) + inline ConstructType JSValuePtr::getConstructData(ConstructData& constructData) { return JSImmediate::isImmediate(asValue()) ? ConstructTypeNone : asCell()->getConstructData(constructData); } - ALWAYS_INLINE bool JSValue::getUInt32(uint32_t& v) const + ALWAYS_INLINE bool JSValuePtr::getUInt32(uint32_t& v) const { return JSImmediate::isImmediate(asValue()) ? JSImmediate::getUInt32(asValue(), v) : asCell()->getUInt32(v); } - ALWAYS_INLINE bool JSValue::getTruncatedInt32(int32_t& v) const + ALWAYS_INLINE bool JSValuePtr::getTruncatedInt32(int32_t& v) const { return JSImmediate::isImmediate(asValue()) ? JSImmediate::getTruncatedInt32(asValue(), v) : asCell()->getTruncatedInt32(v); } - inline bool JSValue::getTruncatedUInt32(uint32_t& v) const + inline bool JSValuePtr::getTruncatedUInt32(uint32_t& v) const { return JSImmediate::isImmediate(asValue()) ? JSImmediate::getTruncatedUInt32(asValue(), v) : asCell()->getTruncatedUInt32(v); } - inline void JSValue::mark() + inline void JSValuePtr::mark() { asCell()->mark(); // callers should check !marked() before calling mark(), so this should only be called with cells } - inline bool JSValue::marked() const + inline bool JSValuePtr::marked() const { return JSImmediate::isImmediate(asValue()) || asCell()->marked(); } - inline JSValue* JSValue::toPrimitive(ExecState* exec, PreferredPrimitiveType preferredType) const + inline JSValuePtr JSValuePtr::toPrimitive(ExecState* exec, PreferredPrimitiveType preferredType) const { return JSImmediate::isImmediate(asValue()) ? asValue() : asCell()->toPrimitive(exec, preferredType); } - inline bool JSValue::getPrimitiveNumber(ExecState* exec, double& number, JSValue*& value) + inline bool JSValuePtr::getPrimitiveNumber(ExecState* exec, double& number, JSValuePtr& value) { if (JSImmediate::isImmediate(asValue())) { number = JSImmediate::toDouble(asValue()); @@ -261,48 +251,47 @@ namespace JSC { return asCell()->getPrimitiveNumber(exec, number, value); } - inline bool JSValue::toBoolean(ExecState* exec) const + inline bool JSValuePtr::toBoolean(ExecState* exec) const { return JSImmediate::isImmediate(asValue()) ? JSImmediate::toBoolean(asValue()) : asCell()->toBoolean(exec); } - ALWAYS_INLINE double JSValue::toNumber(ExecState* exec) const + ALWAYS_INLINE double JSValuePtr::toNumber(ExecState* exec) const { return JSImmediate::isImmediate(asValue()) ? JSImmediate::toDouble(asValue()) : asCell()->toNumber(exec); } - inline UString JSValue::toString(ExecState* exec) const + inline UString JSValuePtr::toString(ExecState* exec) const { return JSImmediate::isImmediate(asValue()) ? JSImmediate::toString(asValue()) : asCell()->toString(exec); } - inline JSObject* JSValue::toObject(ExecState* exec) const + inline JSObject* JSValuePtr::toObject(ExecState* exec) const { return JSImmediate::isImmediate(asValue()) ? JSImmediate::toObject(asValue(), exec) : asCell()->toObject(exec); } - inline JSObject* JSValue::toThisObject(ExecState* exec) const + inline JSObject* JSValuePtr::toThisObject(ExecState* exec) const { if (UNLIKELY(JSImmediate::isImmediate(asValue()))) - return JSImmediate::toObject(asValue(), exec); + return JSImmediate::toThisObject(asValue(), exec); return asCell()->toThisObject(exec); } - inline bool JSValue::needsThisConversion() const + inline bool JSValuePtr::needsThisConversion() const { if (UNLIKELY(JSImmediate::isImmediate(asValue()))) return true; - return asCell()->structureID()->typeInfo().needsThisConversion(); + return asCell()->structure()->typeInfo().needsThisConversion(); } - inline UString JSValue::toThisString(ExecState* exec) const + inline UString JSValuePtr::toThisString(ExecState* exec) const { return JSImmediate::isImmediate(asValue()) ? JSImmediate::toString(asValue()) : asCell()->toThisString(exec); } - inline JSValue* JSValue::getJSNumber() + inline JSValuePtr JSValuePtr::getJSNumber() { - return JSImmediate::isNumber(asValue()) ? asValue() : JSImmediate::isImmediate(asValue()) ? noValue() : asCell()->getJSNumber(); } diff --git a/JavaScriptCore/runtime/JSFunction.cpp b/JavaScriptCore/runtime/JSFunction.cpp index 2973d2d..cb18115 100644 --- a/JavaScriptCore/runtime/JSFunction.cpp +++ b/JavaScriptCore/runtime/JSFunction.cpp @@ -27,10 +27,10 @@ #include "CodeBlock.h" #include "CommonIdentifiers.h" -#include "ExecState.h" +#include "CallFrame.h" #include "FunctionPrototype.h" #include "JSGlobalObject.h" -#include "Machine.h" +#include "Interpreter.h" #include "ObjectPrototype.h" #include "Parser.h" #include "PropertyNameArray.h" @@ -43,7 +43,7 @@ namespace JSC { ASSERT_CLASS_FITS_IN_CELL(JSFunction); -const ClassInfo JSFunction::info = { "Function", 0, 0, 0 }; +const ClassInfo JSFunction::info = { "Function", &InternalFunction::info, 0, 0 }; JSFunction::JSFunction(ExecState* exec, const Identifier& name, FunctionBodyNode* body, ScopeChainNode* scopeChainNode) : Base(&exec->globalData(), exec->lexicalGlobalObject()->functionStructure(), name) @@ -54,12 +54,12 @@ JSFunction::JSFunction(ExecState* exec, const Identifier& name, FunctionBodyNode JSFunction::~JSFunction() { -#if ENABLE(CTI) +#if ENABLE(JIT) // JIT code for other functions may have had calls linked directly to the code for this function; these links // are based on a check for the this pointer value for this JSFunction - which will no longer be valid once // this memory is freed and may be reused (potentially for another, different JSFunction). - if (m_body.get() && m_body->isGenerated()) - m_body->generatedByteCode().unlinkCallers(); + if (m_body && m_body->isGenerated()) + m_body->generatedBytecode().unlinkCallers(); #endif } @@ -77,24 +77,24 @@ CallType JSFunction::getCallData(CallData& callData) return CallTypeJS; } -JSValue* JSFunction::call(ExecState* exec, JSValue* thisValue, const ArgList& args) +JSValuePtr JSFunction::call(ExecState* exec, JSValuePtr thisValue, const ArgList& args) { - return exec->machine()->execute(m_body.get(), exec, this, thisValue->toThisObject(exec), args, m_scopeChain.node(), exec->exceptionSlot()); + return exec->interpreter()->execute(m_body.get(), exec, this, thisValue.toThisObject(exec), args, m_scopeChain.node(), exec->exceptionSlot()); } -JSValue* JSFunction::argumentsGetter(ExecState* exec, const Identifier&, const PropertySlot& slot) +JSValuePtr JSFunction::argumentsGetter(ExecState* exec, const Identifier&, const PropertySlot& slot) { JSFunction* thisObj = asFunction(slot.slotBase()); - return exec->machine()->retrieveArguments(exec, thisObj); + return exec->interpreter()->retrieveArguments(exec, thisObj); } -JSValue* JSFunction::callerGetter(ExecState* exec, const Identifier&, const PropertySlot& slot) +JSValuePtr JSFunction::callerGetter(ExecState* exec, const Identifier&, const PropertySlot& slot) { JSFunction* thisObj = asFunction(slot.slotBase()); - return exec->machine()->retrieveCaller(exec, thisObj); + return exec->interpreter()->retrieveCaller(exec, thisObj); } -JSValue* JSFunction::lengthGetter(ExecState* exec, const Identifier&, const PropertySlot& slot) +JSValuePtr JSFunction::lengthGetter(ExecState* exec, const Identifier&, const PropertySlot& slot) { JSFunction* thisObj = asFunction(slot.slotBase()); return jsNumber(exec, thisObj->m_body->parameterCount()); @@ -103,7 +103,7 @@ JSValue* JSFunction::lengthGetter(ExecState* exec, const Identifier&, const Prop bool JSFunction::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) { if (propertyName == exec->propertyNames().prototype) { - JSValue** location = getDirectLocation(propertyName); + JSValuePtr* location = getDirectLocation(propertyName); if (!location) { JSObject* prototype = new (exec) JSObject(m_scopeChain.globalObject()->emptyObjectStructure()); @@ -133,7 +133,7 @@ bool JSFunction::getOwnPropertySlot(ExecState* exec, const Identifier& propertyN return Base::getOwnPropertySlot(exec, propertyName, slot); } -void JSFunction::put(ExecState* exec, const Identifier& propertyName, JSValue* value, PutPropertySlot& slot) +void JSFunction::put(ExecState* exec, const Identifier& propertyName, JSValuePtr value, PutPropertySlot& slot) { if (propertyName == exec->propertyNames().arguments || propertyName == exec->propertyNames().length) return; @@ -147,32 +147,6 @@ bool JSFunction::deleteProperty(ExecState* exec, const Identifier& propertyName) return Base::deleteProperty(exec, propertyName); } -/* Returns the parameter name corresponding to the given index. eg: - * function f1(x, y, z): getParameterName(0) --> x - * - * If a name appears more than once, only the last index at which - * it appears associates with it. eg: - * function f2(x, x): getParameterName(0) --> null - */ -const Identifier& JSFunction::getParameterName(int index) -{ - const Identifier* parameters = m_body->parameters(); - - if (static_cast<size_t>(index) >= m_body->parameterCount()) - return m_scopeChain.globalObject()->globalData()->propertyNames->nullIdentifier; - - const Identifier& name = parameters[index]; - - // Are there any subsequent parameters with the same name? - size_t size = m_body->parameterCount(); - for (size_t i = index + 1; i < size; ++i) { - if (parameters[i] == name) - return m_scopeChain.globalObject()->globalData()->propertyNames->nullIdentifier; - } - - return name; -} - // ECMA 13.2.2 [[Construct]] ConstructType JSFunction::getConstructData(ConstructData& constructData) { @@ -183,16 +157,16 @@ ConstructType JSFunction::getConstructData(ConstructData& constructData) JSObject* JSFunction::construct(ExecState* exec, const ArgList& args) { - StructureID* structure; - JSValue* prototype = get(exec, exec->propertyNames().prototype); - if (prototype->isObject()) + Structure* structure; + JSValuePtr prototype = get(exec, exec->propertyNames().prototype); + if (prototype.isObject()) structure = asObject(prototype)->inheritorID(); else structure = exec->lexicalGlobalObject()->emptyObjectStructure(); JSObject* thisObj = new (exec) JSObject(structure); - JSValue* result = exec->machine()->execute(m_body.get(), exec, this, thisObj, args, m_scopeChain.node(), exec->exceptionSlot()); - if (exec->hadException() || !result->isObject()) + JSValuePtr result = exec->interpreter()->execute(m_body.get(), exec, this, thisObj, args, m_scopeChain.node(), exec->exceptionSlot()); + if (exec->hadException() || !result.isObject()) return thisObj; return asObject(result); } diff --git a/JavaScriptCore/runtime/JSFunction.h b/JavaScriptCore/runtime/JSFunction.h index 694a0f4..6a43737 100644 --- a/JavaScriptCore/runtime/JSFunction.h +++ b/JavaScriptCore/runtime/JSFunction.h @@ -1,6 +1,6 @@ /* * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) - * Copyright (C) 2003, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca) * Copyright (C) 2007 Maks Orlovich * @@ -27,7 +27,7 @@ #include "InternalFunction.h" #include "JSVariableObject.h" #include "SymbolTable.h" -#include "nodes.h" +#include "Nodes.h" #include "JSObject.h" namespace JSC { @@ -38,39 +38,42 @@ namespace JSC { class JSGlobalObject; class JSFunction : public InternalFunction { - friend class CTI; - friend class Machine; + friend class JIT; + friend class Interpreter; typedef InternalFunction Base; - JSFunction(PassRefPtr<JSC::StructureID> st) : InternalFunction(st), m_scopeChain(NoScopeChain()) {} + + JSFunction(PassRefPtr<Structure> structure) + : InternalFunction(structure) + , m_scopeChain(NoScopeChain()) + { + } + public: JSFunction(ExecState*, const Identifier&, FunctionBodyNode*, ScopeChainNode*); ~JSFunction(); virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&); - virtual void put(ExecState*, const Identifier& propertyName, JSValue*, PutPropertySlot&); + virtual void put(ExecState*, const Identifier& propertyName, JSValuePtr, PutPropertySlot&); virtual bool deleteProperty(ExecState*, const Identifier& propertyName); JSObject* construct(ExecState*, const ArgList&); - JSValue* call(ExecState*, JSValue* thisValue, const ArgList&); - - // Note: Returns a null identifier for any parameters that will never get set - // due to a later parameter with the same name. - const Identifier& getParameterName(int index); + JSValuePtr call(ExecState*, JSValuePtr thisValue, const ArgList&); void setScope(const ScopeChain& scopeChain) { m_scopeChain = scopeChain; } ScopeChain& scope() { return m_scopeChain; } + void setBody(FunctionBodyNode* body) { m_body = body; } + void setBody(PassRefPtr<FunctionBodyNode> body) { m_body = body; } + FunctionBodyNode* body() const { return m_body.get(); } + virtual void mark(); static const ClassInfo info; - // FIXME: This should be private - RefPtr<FunctionBodyNode> m_body; - - static PassRefPtr<StructureID> createStructureID(JSValue* prototype) + static PassRefPtr<Structure> createStructure(JSValuePtr prototype) { - return StructureID::create(prototype, TypeInfo(ObjectType, ImplementsHasInstance)); + return Structure::create(prototype, TypeInfo(ObjectType, ImplementsHasInstance)); } private: @@ -79,21 +82,22 @@ namespace JSC { virtual ConstructType getConstructData(ConstructData&); virtual CallType getCallData(CallData&); - static JSValue* argumentsGetter(ExecState*, const Identifier&, const PropertySlot&); - static JSValue* callerGetter(ExecState*, const Identifier&, const PropertySlot&); - static JSValue* lengthGetter(ExecState*, const Identifier&, const PropertySlot&); + static JSValuePtr argumentsGetter(ExecState*, const Identifier&, const PropertySlot&); + static JSValuePtr callerGetter(ExecState*, const Identifier&, const PropertySlot&); + static JSValuePtr lengthGetter(ExecState*, const Identifier&, const PropertySlot&); + RefPtr<FunctionBodyNode> m_body; ScopeChain m_scopeChain; }; - JSFunction* asFunction(JSValue*); + JSFunction* asFunction(JSValuePtr); - inline JSFunction* asFunction(JSValue* value) + inline JSFunction* asFunction(JSValuePtr value) { ASSERT(asObject(value)->inherits(&JSFunction::info)); return static_cast<JSFunction*>(asObject(value)); } -} // namespace kJS +} // namespace JSC #endif // JSFunction_h diff --git a/JavaScriptCore/runtime/JSGlobalData.cpp b/JavaScriptCore/runtime/JSGlobalData.cpp index 8910679..10b584d 100644 --- a/JavaScriptCore/runtime/JSGlobalData.cpp +++ b/JavaScriptCore/runtime/JSGlobalData.cpp @@ -30,18 +30,19 @@ #include "JSGlobalData.h" #include "ArgList.h" +#include "Collector.h" #include "CommonIdentifiers.h" +#include "FunctionConstructor.h" +#include "Interpreter.h" #include "JSActivation.h" #include "JSClassRef.h" #include "JSLock.h" #include "JSNotAnObject.h" #include "JSStaticScopeObject.h" -#include "Machine.h" #include "Parser.h" -#include "collector.h" -#include "lexer.h" -#include "lookup.h" -#include "nodes.h" +#include "Lexer.h" +#include "Lookup.h" +#include "Nodes.h" #if ENABLE(JSC_MULTIPLE_THREADS) #include <wtf/Threading.h> @@ -64,7 +65,8 @@ extern const HashTable regExpConstructorTable; extern const HashTable stringTable; JSGlobalData::JSGlobalData(bool isShared) - : machine(new Machine) + : initializingLazyNumericCompareFunction(false) + , interpreter(new Interpreter) , exception(noValue()) , arrayTable(new HashTable(JSC::arrayTable)) , dateTable(new HashTable(JSC::dateTable)) @@ -73,13 +75,15 @@ JSGlobalData::JSGlobalData(bool isShared) , regExpTable(new HashTable(JSC::regExpTable)) , regExpConstructorTable(new HashTable(JSC::regExpConstructorTable)) , stringTable(new HashTable(JSC::stringTable)) - , activationStructureID(JSActivation::createStructureID(jsNull())) - , interruptedExecutionErrorStructure(JSObject::createStructureID(jsNull())) - , staticScopeStructureID(JSStaticScopeObject::createStructureID(jsNull())) - , stringStructureID(JSString::createStructureID(jsNull())) - , notAnObjectErrorStubStructure(JSNotAnObjectErrorStub::createStructureID(jsNull())) - , notAnObjectStructure(JSNotAnObject::createStructureID(jsNull())) - , numberStructureID(JSNumberCell::createStructureID(jsNull())) + , activationStructure(JSActivation::createStructure(jsNull())) + , interruptedExecutionErrorStructure(JSObject::createStructure(jsNull())) + , staticScopeStructure(JSStaticScopeObject::createStructure(jsNull())) + , stringStructure(JSString::createStructure(jsNull())) + , notAnObjectErrorStubStructure(JSNotAnObjectErrorStub::createStructure(jsNull())) + , notAnObjectStructure(JSNotAnObject::createStructure(jsNull())) +#if !USE(ALTERNATE_JSIMMEDIATE) + , numberStructure(JSNumberCell::createStructure(jsNull())) +#endif , identifierTable(createIdentifierTable()) , propertyNames(new CommonIdentifiers(this)) , emptyList(new ArgList) @@ -91,21 +95,23 @@ JSGlobalData::JSGlobalData(bool isShared) , dynamicGlobalObject(0) , isSharedInstance(isShared) , clientData(0) + , scopeNodeBeingReparsed(0) , heap(this) { #if PLATFORM(MAC) startProfilerServerIfNeeded(); #endif + interpreter->initialize(this); } JSGlobalData::~JSGlobalData() { // By the time this is destroyed, heap.destroy() must already have been called. - delete machine; + delete interpreter; #ifndef NDEBUG // Zeroing out to make the behavior more predictable when someone attempts to use a deleted instance. - machine = 0; + interpreter = 0; #endif arrayTable->deleteTable(); @@ -147,9 +153,9 @@ PassRefPtr<JSGlobalData> JSGlobalData::create() PassRefPtr<JSGlobalData> JSGlobalData::createLeaked() { #ifndef NDEBUG - StructureID::startIgnoringLeaks(); + Structure::startIgnoringLeaks(); RefPtr<JSGlobalData> data = create(); - StructureID::stopIgnoringLeaks(); + Structure::stopIgnoringLeaks(); return data.release(); #else return create(); @@ -164,8 +170,12 @@ bool JSGlobalData::sharedInstanceExists() JSGlobalData& JSGlobalData::sharedInstance() { JSGlobalData*& instance = sharedInstanceInternal(); - if (!instance) + if (!instance) { instance = new JSGlobalData(true); +#if ENABLE(JSC_MULTIPLE_THREADS) + instance->makeUsableFromMultipleThreads(); +#endif + } return *instance; } @@ -176,8 +186,22 @@ JSGlobalData*& JSGlobalData::sharedInstanceInternal() return sharedInstance; } -JSGlobalData::ClientData::~ClientData() +// FIXME: We can also detect forms like v1 < v2 ? -1 : 0, reverse comparison, etc. +const Vector<Instruction>& JSGlobalData::numericCompareFunction(ExecState* exec) { + if (!lazyNumericCompareFunction.size() && !initializingLazyNumericCompareFunction) { + initializingLazyNumericCompareFunction = true; + RefPtr<ProgramNode> programNode = parser->parse<ProgramNode>(exec, 0, makeSource(UString("(function (v1, v2) { return v1 - v2; })")), 0, 0); + RefPtr<FunctionBodyNode> functionBody = extractFunctionBody(programNode.get()); + lazyNumericCompareFunction = functionBody->bytecode(exec->scopeChain()).instructions(); + initializingLazyNumericCompareFunction = false; + } + + return lazyNumericCompareFunction; } +JSGlobalData::ClientData::~ClientData() +{ } + +} // namespace JSC diff --git a/JavaScriptCore/runtime/JSGlobalData.h b/JavaScriptCore/runtime/JSGlobalData.h index 3210149..4223191 100644 --- a/JavaScriptCore/runtime/JSGlobalData.h +++ b/JavaScriptCore/runtime/JSGlobalData.h @@ -32,8 +32,10 @@ #include <wtf/Forward.h> #include <wtf/HashMap.h> #include <wtf/RefCounted.h> -#include "collector.h" +#include "Collector.h" +#include "ExecutableAllocator.h" #include "SmallStrings.h" +#include "JSValue.h" struct OpaqueJSClass; struct OpaqueJSClassContextData; @@ -44,13 +46,15 @@ namespace JSC { class CommonIdentifiers; class Heap; class IdentifierTable; + class Instruction; + class Interpreter; class JSGlobalObject; class JSObject; class Lexer; - class Machine; class Parser; class ParserRefCounted; - class StructureID; + class ScopeNode; + class Structure; class UString; struct HashTable; @@ -63,11 +67,20 @@ namespace JSC { static PassRefPtr<JSGlobalData> createLeaked(); ~JSGlobalData(); - Machine* machine; +#if ENABLE(JSC_MULTIPLE_THREADS) + // Will start tracking threads that use the heap, which is resource-heavy. + void makeUsableFromMultipleThreads() { heap.makeUsableFromMultipleThreads(); } +#endif + + const Vector<Instruction>& numericCompareFunction(ExecState*); + Vector<Instruction> lazyNumericCompareFunction; + bool initializingLazyNumericCompareFunction; - JSValue* exception; -#if ENABLE(CTI) - void* throwReturnAddress; + Interpreter* interpreter; + + JSValuePtr exception; +#if ENABLE(JIT) + void* exceptionLocation; #endif const HashTable* arrayTable; @@ -78,13 +91,15 @@ namespace JSC { const HashTable* regExpConstructorTable; const HashTable* stringTable; - RefPtr<StructureID> activationStructureID; - RefPtr<StructureID> interruptedExecutionErrorStructure; - RefPtr<StructureID> staticScopeStructureID; - RefPtr<StructureID> stringStructureID; - RefPtr<StructureID> notAnObjectErrorStubStructure; - RefPtr<StructureID> notAnObjectStructure; - RefPtr<StructureID> numberStructureID; + RefPtr<Structure> activationStructure; + RefPtr<Structure> interruptedExecutionErrorStructure; + RefPtr<Structure> staticScopeStructure; + RefPtr<Structure> stringStructure; + RefPtr<Structure> notAnObjectErrorStubStructure; + RefPtr<Structure> notAnObjectStructure; +#if !USE(ALTERNATE_JSIMMEDIATE) + RefPtr<Structure> numberStructure; +#endif IdentifierTable* identifierTable; CommonIdentifiers* propertyNames; @@ -113,10 +128,17 @@ namespace JSC { HashSet<JSObject*> arrayVisitedElements; - Heap heap; + ScopeNode* scopeNodeBeingReparsed; + Heap heap; +#if ENABLE(ASSEMBLER) + PassRefPtr<ExecutablePool> poolForSize(size_t n) { return m_executableAllocator.poolForSize(n); } +#endif private: JSGlobalData(bool isShared = false); +#if ENABLE(ASSEMBLER) + ExecutableAllocator m_executableAllocator; +#endif static JSGlobalData*& sharedInstanceInternal(); }; diff --git a/JavaScriptCore/runtime/JSGlobalObject.cpp b/JavaScriptCore/runtime/JSGlobalObject.cpp index 89c32fd..eb2b349 100644 --- a/JavaScriptCore/runtime/JSGlobalObject.cpp +++ b/JavaScriptCore/runtime/JSGlobalObject.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved. * Copyright (C) 2008 Cameron Zwarich (cwzwarich@uwaterloo.ca) * * Redistribution and use in source and binary forms, with or without @@ -49,7 +49,7 @@ #include "GlobalEvalFunction.h" #include "JSGlobalObjectFunctions.h" #include "JSLock.h" -#include "Machine.h" +#include "Interpreter.h" #include "MathObject.h" #include "NativeErrorConstructor.h" #include "NativeErrorPrototype.h" @@ -78,13 +78,13 @@ static const int initialTickCountThreshold = 255; // Preferred number of milliseconds between each timeout check static const int preferredScriptCheckTimeInterval = 1000; -static inline void markIfNeeded(JSValue* v) +static inline void markIfNeeded(JSValuePtr v) { - if (v && !v->marked()) - v->mark(); + if (v && !v.marked()) + v.mark(); } -static inline void markIfNeeded(const RefPtr<StructureID>& s) +static inline void markIfNeeded(const RefPtr<Structure>& s) { if (s) s->mark(); @@ -112,9 +112,9 @@ JSGlobalObject::~JSGlobalObject() HashSet<ProgramCodeBlock*>::const_iterator end = codeBlocks().end(); for (HashSet<ProgramCodeBlock*>::const_iterator it = codeBlocks().begin(); it != end; ++it) - (*it)->globalObject = 0; + (*it)->clearGlobalObject(); - RegisterFile& registerFile = globalData()->machine->registerFile(); + RegisterFile& registerFile = globalData()->interpreter->registerFile(); if (registerFile.globalObject() == this) { registerFile.setGlobalObject(0); registerFile.setNumGlobals(0); @@ -147,7 +147,7 @@ void JSGlobalObject::init(JSObject* thisValue) reset(prototype()); } -void JSGlobalObject::put(ExecState* exec, const Identifier& propertyName, JSValue* value, PutPropertySlot& slot) +void JSGlobalObject::put(ExecState* exec, const Identifier& propertyName, JSValuePtr value, PutPropertySlot& slot) { ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this)); @@ -156,18 +156,19 @@ void JSGlobalObject::put(ExecState* exec, const Identifier& propertyName, JSValu JSVariableObject::put(exec, propertyName, value, slot); } -void JSGlobalObject::putWithAttributes(ExecState* exec, const Identifier& propertyName, JSValue* value, unsigned attributes) +void JSGlobalObject::putWithAttributes(ExecState* exec, const Identifier& propertyName, JSValuePtr value, unsigned attributes) { ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this)); if (symbolTablePutWithAttributes(propertyName, value, attributes)) return; - JSValue* valueBefore = getDirect(propertyName); + JSValuePtr valueBefore = getDirect(propertyName); PutPropertySlot slot; JSVariableObject::put(exec, propertyName, value, slot); if (!valueBefore) { - if (JSValue* valueAfter = getDirect(propertyName)) + JSValuePtr valueAfter = getDirect(propertyName); + if (valueAfter) putDirect(propertyName, valueAfter, attributes); } } @@ -189,54 +190,54 @@ void JSGlobalObject::defineSetter(ExecState* exec, const Identifier& propertyNam static inline JSObject* lastInPrototypeChain(JSObject* object) { JSObject* o = object; - while (o->prototype()->isObject()) + while (o->prototype().isObject()) o = asObject(o->prototype()); return o; } -void JSGlobalObject::reset(JSValue* prototype) +void JSGlobalObject::reset(JSValuePtr prototype) { ExecState* exec = JSGlobalObject::globalExec(); // Prototypes - d()->functionPrototype = new (exec) FunctionPrototype(exec, FunctionPrototype::createStructureID(jsNull())); // The real prototype will be set once ObjectPrototype is created. - d()->prototypeFunctionStructure = PrototypeFunction::createStructureID(d()->functionPrototype); + d()->functionPrototype = new (exec) FunctionPrototype(exec, FunctionPrototype::createStructure(jsNull())); // The real prototype will be set once ObjectPrototype is created. + d()->prototypeFunctionStructure = PrototypeFunction::createStructure(d()->functionPrototype); d()->functionPrototype->addFunctionProperties(exec, d()->prototypeFunctionStructure.get()); - d()->objectPrototype = new (exec) ObjectPrototype(exec, ObjectPrototype::createStructureID(jsNull()), d()->prototypeFunctionStructure.get()); - d()->functionPrototype->structureID()->setPrototypeWithoutTransition(d()->objectPrototype); + d()->objectPrototype = new (exec) ObjectPrototype(exec, ObjectPrototype::createStructure(jsNull()), d()->prototypeFunctionStructure.get()); + d()->functionPrototype->structure()->setPrototypeWithoutTransition(d()->objectPrototype); d()->emptyObjectStructure = d()->objectPrototype->inheritorID(); - d()->functionStructure = JSFunction::createStructureID(d()->functionPrototype); - d()->callbackFunctionStructure = JSCallbackFunction::createStructureID(d()->functionPrototype); - d()->argumentsStructure = Arguments::createStructureID(d()->objectPrototype); - d()->callbackConstructorStructure = JSCallbackConstructor::createStructureID(d()->objectPrototype); - d()->callbackObjectStructure = JSCallbackObject<JSObject>::createStructureID(d()->objectPrototype); + d()->functionStructure = JSFunction::createStructure(d()->functionPrototype); + d()->callbackFunctionStructure = JSCallbackFunction::createStructure(d()->functionPrototype); + d()->argumentsStructure = Arguments::createStructure(d()->objectPrototype); + d()->callbackConstructorStructure = JSCallbackConstructor::createStructure(d()->objectPrototype); + d()->callbackObjectStructure = JSCallbackObject<JSObject>::createStructure(d()->objectPrototype); - d()->arrayPrototype = new (exec) ArrayPrototype(ArrayPrototype::createStructureID(d()->objectPrototype)); - d()->arrayStructure = JSArray::createStructureID(d()->arrayPrototype); - d()->regExpMatchesArrayStructure = RegExpMatchesArray::createStructureID(d()->arrayPrototype); + d()->arrayPrototype = new (exec) ArrayPrototype(ArrayPrototype::createStructure(d()->objectPrototype)); + d()->arrayStructure = JSArray::createStructure(d()->arrayPrototype); + d()->regExpMatchesArrayStructure = RegExpMatchesArray::createStructure(d()->arrayPrototype); - d()->stringPrototype = new (exec) StringPrototype(exec, StringPrototype::createStructureID(d()->objectPrototype)); - d()->stringObjectStructure = StringObject::createStructureID(d()->stringPrototype); + d()->stringPrototype = new (exec) StringPrototype(exec, StringPrototype::createStructure(d()->objectPrototype)); + d()->stringObjectStructure = StringObject::createStructure(d()->stringPrototype); - d()->booleanPrototype = new (exec) BooleanPrototype(exec, BooleanPrototype::createStructureID(d()->objectPrototype), d()->prototypeFunctionStructure.get()); - d()->booleanObjectStructure = BooleanObject::createStructureID(d()->booleanPrototype); + d()->booleanPrototype = new (exec) BooleanPrototype(exec, BooleanPrototype::createStructure(d()->objectPrototype), d()->prototypeFunctionStructure.get()); + d()->booleanObjectStructure = BooleanObject::createStructure(d()->booleanPrototype); - d()->numberPrototype = new (exec) NumberPrototype(exec, NumberPrototype::createStructureID(d()->objectPrototype), d()->prototypeFunctionStructure.get()); - d()->numberObjectStructure = NumberObject::createStructureID(d()->numberPrototype); + d()->numberPrototype = new (exec) NumberPrototype(exec, NumberPrototype::createStructure(d()->objectPrototype), d()->prototypeFunctionStructure.get()); + d()->numberObjectStructure = NumberObject::createStructure(d()->numberPrototype); - d()->datePrototype = new (exec) DatePrototype(exec, DatePrototype::createStructureID(d()->objectPrototype)); - d()->dateStructure = DateInstance::createStructureID(d()->datePrototype); + d()->datePrototype = new (exec) DatePrototype(exec, DatePrototype::createStructure(d()->objectPrototype)); + d()->dateStructure = DateInstance::createStructure(d()->datePrototype); - d()->regExpPrototype = new (exec) RegExpPrototype(exec, RegExpPrototype::createStructureID(d()->objectPrototype), d()->prototypeFunctionStructure.get()); - d()->regExpStructure = RegExpObject::createStructureID(d()->regExpPrototype); + d()->regExpPrototype = new (exec) RegExpPrototype(exec, RegExpPrototype::createStructure(d()->objectPrototype), d()->prototypeFunctionStructure.get()); + d()->regExpStructure = RegExpObject::createStructure(d()->regExpPrototype); - ErrorPrototype* errorPrototype = new (exec) ErrorPrototype(exec, ErrorPrototype::createStructureID(d()->objectPrototype), d()->prototypeFunctionStructure.get()); - d()->errorStructure = ErrorInstance::createStructureID(errorPrototype); + ErrorPrototype* errorPrototype = new (exec) ErrorPrototype(exec, ErrorPrototype::createStructure(d()->objectPrototype), d()->prototypeFunctionStructure.get()); + d()->errorStructure = ErrorInstance::createStructure(errorPrototype); - RefPtr<StructureID> nativeErrorPrototypeStructure = NativeErrorPrototype::createStructureID(errorPrototype); + RefPtr<Structure> nativeErrorPrototypeStructure = NativeErrorPrototype::createStructure(errorPrototype); NativeErrorPrototype* evalErrorPrototype = new (exec) NativeErrorPrototype(exec, nativeErrorPrototypeStructure, "EvalError", "EvalError"); NativeErrorPrototype* rangeErrorPrototype = new (exec) NativeErrorPrototype(exec, nativeErrorPrototypeStructure, "RangeError", "RangeError"); @@ -247,19 +248,19 @@ void JSGlobalObject::reset(JSValue* prototype) // Constructors - JSValue* objectConstructor = new (exec) ObjectConstructor(exec, ObjectConstructor::createStructureID(d()->functionPrototype), d()->objectPrototype); - JSValue* functionConstructor = new (exec) FunctionConstructor(exec, FunctionConstructor::createStructureID(d()->functionPrototype), d()->functionPrototype); - JSValue* arrayConstructor = new (exec) ArrayConstructor(exec, ArrayConstructor::createStructureID(d()->functionPrototype), d()->arrayPrototype); - JSValue* stringConstructor = new (exec) StringConstructor(exec, StringConstructor::createStructureID(d()->functionPrototype), d()->prototypeFunctionStructure.get(), d()->stringPrototype); - JSValue* booleanConstructor = new (exec) BooleanConstructor(exec, BooleanConstructor::createStructureID(d()->functionPrototype), d()->booleanPrototype); - JSValue* numberConstructor = new (exec) NumberConstructor(exec, NumberConstructor::createStructureID(d()->functionPrototype), d()->numberPrototype); - JSValue* dateConstructor = new (exec) DateConstructor(exec, DateConstructor::createStructureID(d()->functionPrototype), d()->prototypeFunctionStructure.get(), d()->datePrototype); + JSValuePtr objectConstructor = new (exec) ObjectConstructor(exec, ObjectConstructor::createStructure(d()->functionPrototype), d()->objectPrototype); + JSValuePtr functionConstructor = new (exec) FunctionConstructor(exec, FunctionConstructor::createStructure(d()->functionPrototype), d()->functionPrototype); + JSValuePtr arrayConstructor = new (exec) ArrayConstructor(exec, ArrayConstructor::createStructure(d()->functionPrototype), d()->arrayPrototype); + JSValuePtr stringConstructor = new (exec) StringConstructor(exec, StringConstructor::createStructure(d()->functionPrototype), d()->prototypeFunctionStructure.get(), d()->stringPrototype); + JSValuePtr booleanConstructor = new (exec) BooleanConstructor(exec, BooleanConstructor::createStructure(d()->functionPrototype), d()->booleanPrototype); + JSValuePtr numberConstructor = new (exec) NumberConstructor(exec, NumberConstructor::createStructure(d()->functionPrototype), d()->numberPrototype); + JSValuePtr dateConstructor = new (exec) DateConstructor(exec, DateConstructor::createStructure(d()->functionPrototype), d()->prototypeFunctionStructure.get(), d()->datePrototype); - d()->regExpConstructor = new (exec) RegExpConstructor(exec, RegExpConstructor::createStructureID(d()->functionPrototype), d()->regExpPrototype); + d()->regExpConstructor = new (exec) RegExpConstructor(exec, RegExpConstructor::createStructure(d()->functionPrototype), d()->regExpPrototype); - d()->errorConstructor = new (exec) ErrorConstructor(exec, ErrorConstructor::createStructureID(d()->functionPrototype), errorPrototype); + d()->errorConstructor = new (exec) ErrorConstructor(exec, ErrorConstructor::createStructure(d()->functionPrototype), errorPrototype); - RefPtr<StructureID> nativeErrorStructure = NativeErrorConstructor::createStructureID(d()->functionPrototype); + RefPtr<Structure> nativeErrorStructure = NativeErrorConstructor::createStructure(d()->functionPrototype); d()->evalErrorConstructor = new (exec) NativeErrorConstructor(exec, nativeErrorStructure, evalErrorPrototype); d()->rangeErrorConstructor = new (exec) NativeErrorConstructor(exec, nativeErrorStructure, rangeErrorPrototype); @@ -307,7 +308,7 @@ void JSGlobalObject::reset(JSValue* prototype) // Set global values. GlobalPropertyInfo staticGlobals[] = { - GlobalPropertyInfo(Identifier(exec, "Math"), new (exec) MathObject(exec, MathObject::createStructureID(d()->objectPrototype)), DontEnum | DontDelete), + GlobalPropertyInfo(Identifier(exec, "Math"), new (exec) MathObject(exec, MathObject::createStructure(d()->objectPrototype)), DontEnum | DontDelete), GlobalPropertyInfo(Identifier(exec, "NaN"), jsNaN(exec), DontEnum | DontDelete), GlobalPropertyInfo(Identifier(exec, "Infinity"), jsNumber(exec, Inf), DontEnum | DontDelete), GlobalPropertyInfo(Identifier(exec, "undefined"), jsUndefined(), DontEnum | DontDelete) @@ -317,7 +318,7 @@ void JSGlobalObject::reset(JSValue* prototype) // Set global functions. - d()->evalFunction = new (exec) GlobalEvalFunction(exec, GlobalEvalFunction::createStructureID(d()->functionPrototype), 1, exec->propertyNames().eval, globalFuncEval, this); + d()->evalFunction = new (exec) GlobalEvalFunction(exec, GlobalEvalFunction::createStructure(d()->functionPrototype), 1, exec->propertyNames().eval, globalFuncEval, this); putDirectFunctionWithoutTransition(exec, d()->evalFunction, DontEnum); putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, d()->prototypeFunctionStructure.get(), 2, Identifier(exec, "parseInt"), globalFuncParseInt), DontEnum); putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "parseFloat"), globalFuncParseFloat), DontEnum); @@ -330,14 +331,14 @@ void JSGlobalObject::reset(JSValue* prototype) putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "encodeURI"), globalFuncEncodeURI), DontEnum); putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "encodeURIComponent"), globalFuncEncodeURIComponent), DontEnum); #ifndef NDEBUG - putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "kjsprint"), globalFuncKJSPrint), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "jscprint"), globalFuncJSCPrint), DontEnum); #endif resetPrototype(prototype); } // Set prototype, and also insert the object prototype at the end of the chain. -void JSGlobalObject::resetPrototype(JSValue* prototype) +void JSGlobalObject::resetPrototype(JSValuePtr prototype) { setPrototype(prototype); lastInPrototypeChain(this)->setPrototype(d()->objectPrototype); @@ -345,17 +346,17 @@ void JSGlobalObject::resetPrototype(JSValue* prototype) void JSGlobalObject::setTimeoutTime(unsigned timeoutTime) { - globalData()->machine->setTimeoutTime(timeoutTime); + globalData()->interpreter->setTimeoutTime(timeoutTime); } void JSGlobalObject::startTimeoutCheck() { - globalData()->machine->startTimeoutCheck(); + globalData()->interpreter->startTimeoutCheck(); } void JSGlobalObject::stopTimeoutCheck() { - globalData()->machine->stopTimeoutCheck(); + globalData()->interpreter->stopTimeoutCheck(); } void JSGlobalObject::mark() @@ -366,7 +367,7 @@ void JSGlobalObject::mark() for (HashSet<ProgramCodeBlock*>::const_iterator it = codeBlocks().begin(); it != end; ++it) (*it)->mark(); - RegisterFile& registerFile = globalData()->machine->registerFile(); + RegisterFile& registerFile = globalData()->interpreter->registerFile(); if (registerFile.globalObject() == this) registerFile.markGlobals(&globalData()->heap); @@ -407,16 +408,6 @@ void JSGlobalObject::mark() } } -void JSGlobalObject::markCrossHeapDependentObjects() -{ - // Overridden by subclasses. -} - -JSGlobalObject* JSGlobalObject::toGlobalObject(ExecState*) const -{ - return const_cast<JSGlobalObject*>(this); -} - ExecState* JSGlobalObject::globalExec() { return CallFrame::create(d()->globalCallFrame + RegisterFile::CallFrameHeaderSize); diff --git a/JavaScriptCore/runtime/JSGlobalObject.h b/JavaScriptCore/runtime/JSGlobalObject.h index d8a072a..4a10f64 100644 --- a/JavaScriptCore/runtime/JSGlobalObject.h +++ b/JavaScriptCore/runtime/JSGlobalObject.h @@ -114,21 +114,21 @@ namespace JSC { DatePrototype* datePrototype; RegExpPrototype* regExpPrototype; - RefPtr<StructureID> argumentsStructure; - RefPtr<StructureID> arrayStructure; - RefPtr<StructureID> booleanObjectStructure; - RefPtr<StructureID> callbackConstructorStructure; - RefPtr<StructureID> callbackFunctionStructure; - RefPtr<StructureID> callbackObjectStructure; - RefPtr<StructureID> dateStructure; - RefPtr<StructureID> emptyObjectStructure; - RefPtr<StructureID> errorStructure; - RefPtr<StructureID> functionStructure; - RefPtr<StructureID> numberObjectStructure; - RefPtr<StructureID> prototypeFunctionStructure; - RefPtr<StructureID> regExpMatchesArrayStructure; - RefPtr<StructureID> regExpStructure; - RefPtr<StructureID> stringObjectStructure; + RefPtr<Structure> argumentsStructure; + RefPtr<Structure> arrayStructure; + RefPtr<Structure> booleanObjectStructure; + RefPtr<Structure> callbackConstructorStructure; + RefPtr<Structure> callbackFunctionStructure; + RefPtr<Structure> callbackObjectStructure; + RefPtr<Structure> dateStructure; + RefPtr<Structure> emptyObjectStructure; + RefPtr<Structure> errorStructure; + RefPtr<Structure> functionStructure; + RefPtr<Structure> numberObjectStructure; + RefPtr<Structure> prototypeFunctionStructure; + RefPtr<Structure> regExpMatchesArrayStructure; + RefPtr<Structure> regExpStructure; + RefPtr<Structure> stringObjectStructure; SymbolTable symbolTable; unsigned profileGroup; @@ -142,13 +142,13 @@ namespace JSC { void* operator new(size_t, JSGlobalData*); explicit JSGlobalObject() - : JSVariableObject(JSGlobalObject::createStructureID(jsNull()), new JSGlobalObjectData) + : JSVariableObject(JSGlobalObject::createStructure(jsNull()), new JSGlobalObjectData) { init(this); } protected: - JSGlobalObject(PassRefPtr<StructureID> structure, JSGlobalObjectData* data, JSObject* thisValue) + JSGlobalObject(PassRefPtr<Structure> structure, JSGlobalObjectData* data, JSObject* thisValue) : JSVariableObject(structure, data) { init(thisValue); @@ -158,12 +158,11 @@ namespace JSC { virtual ~JSGlobalObject(); virtual void mark(); - virtual void markCrossHeapDependentObjects(); virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&); virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&, bool& slotIsWriteable); - virtual void put(ExecState*, const Identifier&, JSValue*, PutPropertySlot&); - virtual void putWithAttributes(ExecState*, const Identifier& propertyName, JSValue* value, unsigned attributes); + virtual void put(ExecState*, const Identifier&, JSValuePtr, PutPropertySlot&); + virtual void putWithAttributes(ExecState*, const Identifier& propertyName, JSValuePtr value, unsigned attributes); virtual void defineGetter(ExecState*, const Identifier& propertyName, JSObject* getterFunc); virtual void defineSetter(ExecState*, const Identifier& propertyName, JSObject* setterFunc); @@ -196,21 +195,21 @@ namespace JSC { DatePrototype* datePrototype() const { return d()->datePrototype; } RegExpPrototype* regExpPrototype() const { return d()->regExpPrototype; } - StructureID* argumentsStructure() const { return d()->argumentsStructure.get(); } - StructureID* arrayStructure() const { return d()->arrayStructure.get(); } - StructureID* booleanObjectStructure() const { return d()->booleanObjectStructure.get(); } - StructureID* callbackConstructorStructure() const { return d()->callbackConstructorStructure.get(); } - StructureID* callbackFunctionStructure() const { return d()->callbackFunctionStructure.get(); } - StructureID* callbackObjectStructure() const { return d()->callbackObjectStructure.get(); } - StructureID* dateStructure() const { return d()->dateStructure.get(); } - StructureID* emptyObjectStructure() const { return d()->emptyObjectStructure.get(); } - StructureID* errorStructure() const { return d()->errorStructure.get(); } - StructureID* functionStructure() const { return d()->functionStructure.get(); } - StructureID* numberObjectStructure() const { return d()->numberObjectStructure.get(); } - StructureID* prototypeFunctionStructure() const { return d()->prototypeFunctionStructure.get(); } - StructureID* regExpMatchesArrayStructure() const { return d()->regExpMatchesArrayStructure.get(); } - StructureID* regExpStructure() const { return d()->regExpStructure.get(); } - StructureID* stringObjectStructure() const { return d()->stringObjectStructure.get(); } + Structure* argumentsStructure() const { return d()->argumentsStructure.get(); } + Structure* arrayStructure() const { return d()->arrayStructure.get(); } + Structure* booleanObjectStructure() const { return d()->booleanObjectStructure.get(); } + Structure* callbackConstructorStructure() const { return d()->callbackConstructorStructure.get(); } + Structure* callbackFunctionStructure() const { return d()->callbackFunctionStructure.get(); } + Structure* callbackObjectStructure() const { return d()->callbackObjectStructure.get(); } + Structure* dateStructure() const { return d()->dateStructure.get(); } + Structure* emptyObjectStructure() const { return d()->emptyObjectStructure.get(); } + Structure* errorStructure() const { return d()->errorStructure.get(); } + Structure* functionStructure() const { return d()->functionStructure.get(); } + Structure* numberObjectStructure() const { return d()->numberObjectStructure.get(); } + Structure* prototypeFunctionStructure() const { return d()->prototypeFunctionStructure.get(); } + Structure* regExpMatchesArrayStructure() const { return d()->regExpMatchesArrayStructure.get(); } + Structure* regExpStructure() const { return d()->regExpStructure.get(); } + Structure* stringObjectStructure() const { return d()->stringObjectStructure.get(); } void setProfileGroup(unsigned value) { d()->profileGroup = value; } unsigned profileGroup() const { return d()->profileGroup; } @@ -231,7 +230,6 @@ namespace JSC { ScopeChain& globalScopeChain() { return d()->globalScopeChain; } virtual bool isGlobalObject() const { return true; } - virtual JSGlobalObject* toGlobalObject(ExecState*) const; virtual ExecState* globalExec(); @@ -246,19 +244,19 @@ namespace JSC { void copyGlobalsFrom(RegisterFile&); void copyGlobalsTo(RegisterFile&); - void resetPrototype(JSValue* prototype); + void resetPrototype(JSValuePtr prototype); JSGlobalData* globalData() { return d()->globalData.get(); } JSGlobalObjectData* d() const { return static_cast<JSGlobalObjectData*>(JSVariableObject::d); } - static PassRefPtr<StructureID> createStructureID(JSValue* prototype) + static PassRefPtr<Structure> createStructure(JSValuePtr prototype) { - return StructureID::create(prototype, TypeInfo(ObjectType)); + return Structure::create(prototype, TypeInfo(ObjectType)); } protected: struct GlobalPropertyInfo { - GlobalPropertyInfo(const Identifier& i, JSValue* v, unsigned a) + GlobalPropertyInfo(const Identifier& i, JSValuePtr v, unsigned a) : identifier(i) , value(v) , attributes(a) @@ -266,7 +264,7 @@ namespace JSC { } const Identifier identifier; - JSValue* value; + JSValuePtr value; unsigned attributes; }; void addStaticGlobals(GlobalPropertyInfo*, int count); @@ -274,16 +272,16 @@ namespace JSC { private: // FIXME: Fold reset into init. void init(JSObject* thisValue); - void reset(JSValue* prototype); + void reset(JSValuePtr prototype); void setRegisters(Register* registers, Register* registerArray, size_t count); void* operator new(size_t); // can only be allocated with JSGlobalData }; - JSGlobalObject* asGlobalObject(JSValue*); + JSGlobalObject* asGlobalObject(JSValuePtr); - inline JSGlobalObject* asGlobalObject(JSValue* value) + inline JSGlobalObject* asGlobalObject(JSValuePtr value) { ASSERT(asObject(value)->isGlobalObject()); return static_cast<JSGlobalObject*>(asObject(value)); @@ -335,7 +333,7 @@ namespace JSC { return asGlobalObject(n->object); } - inline JSValue* StructureID::prototypeForLookup(ExecState* exec) + inline JSValuePtr Structure::prototypeForLookup(ExecState* exec) { if (typeInfo().type() == ObjectType) return m_prototype; @@ -357,7 +355,26 @@ namespace JSC { ASSERT(globalData().dynamicGlobalObject); return globalData().dynamicGlobalObject; } - + + class DynamicGlobalObjectScope : Noncopyable { + public: + DynamicGlobalObjectScope(CallFrame* callFrame, JSGlobalObject* dynamicGlobalObject) + : m_dynamicGlobalObjectSlot(callFrame->globalData().dynamicGlobalObject) + , m_savedDynamicGlobalObject(m_dynamicGlobalObjectSlot) + { + m_dynamicGlobalObjectSlot = dynamicGlobalObject; + } + + ~DynamicGlobalObjectScope() + { + m_dynamicGlobalObjectSlot = m_savedDynamicGlobalObject; + } + + private: + JSGlobalObject*& m_dynamicGlobalObjectSlot; + JSGlobalObject* m_savedDynamicGlobalObject; + }; + } // namespace JSC #endif // JSGlobalObject_h diff --git a/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp b/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp index 8bb1c6b..91ea130 100644 --- a/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp +++ b/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 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca) * Copyright (C) 2007 Maks Orlovich * @@ -25,16 +25,15 @@ #include "config.h" #include "JSGlobalObjectFunctions.h" -#include "ExecState.h" +#include "CallFrame.h" #include "GlobalEvalFunction.h" #include "JSGlobalObject.h" #include "JSString.h" -#include "Machine.h" +#include "Interpreter.h" #include "Parser.h" #include "dtoa.h" -#include "lexer.h" -#include "nodes.h" -#include <errno.h> +#include "Lexer.h" +#include "Nodes.h" #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -48,9 +47,9 @@ using namespace Unicode; namespace JSC { -static JSValue* encode(ExecState* exec, const ArgList& args, const char* doNotEscape) +static JSValuePtr encode(ExecState* exec, const ArgList& args, const char* doNotEscape) { - UString str = args.at(exec, 0)->toString(exec); + UString str = args.at(exec, 0).toString(exec); CString cstr = str.UTF8String(true); if (!cstr.c_str()) return throwError(exec, URIError, "String contained an illegal UTF-16 sequence."); @@ -70,10 +69,10 @@ static JSValue* encode(ExecState* exec, const ArgList& args, const char* doNotEs return jsString(exec, result); } -static JSValue* decode(ExecState* exec, const ArgList& args, const char* doNotUnescape, bool strict) +static JSValuePtr decode(ExecState* exec, const ArgList& args, const char* doNotUnescape, bool strict) { UString result = ""; - UString str = args.at(exec, 0)->toString(exec); + UString str = args.at(exec, 0).toString(exec); int k = 0; int len = str.size(); const UChar* d = str.data(); @@ -239,7 +238,7 @@ static double parseInt(const UString& s, int radix) if (number >= mantissaOverflowLowerBound) { if (radix == 10) - number = strtod(s.substr(firstDigitPosition, p - firstDigitPosition).ascii(), 0); + number = WTF::strtod(s.substr(firstDigitPosition, p - firstDigitPosition).ascii(), 0); else if (radix == 2 || radix == 4 || radix == 8 || radix == 16 || radix == 32) number = parseIntOverflow(s.substr(firstDigitPosition, p - firstDigitPosition).ascii(), p - firstDigitPosition, radix); } @@ -269,18 +268,18 @@ static double parseFloat(const UString& s) return s.toDouble(true /*tolerant*/, false /* NaN for empty string */); } -JSValue* globalFuncEval(ExecState* exec, JSObject* function, JSValue* thisValue, const ArgList& args) +JSValuePtr globalFuncEval(ExecState* exec, JSObject* function, JSValuePtr thisValue, const ArgList& args) { - JSObject* thisObject = thisValue->toThisObject(exec); - JSGlobalObject* globalObject = thisObject->toGlobalObject(exec); - if (!globalObject || globalObject->evalFunction() != function) + JSObject* thisObject = thisValue.toThisObject(exec); + JSObject* unwrappedObject = thisObject->unwrappedObject(); + if (!unwrappedObject->isGlobalObject() || static_cast<JSGlobalObject*>(unwrappedObject)->evalFunction() != function) return throwError(exec, EvalError, "The \"this\" value passed to eval must be the global object from which eval originated"); - JSValue* x = args.at(exec, 0); - if (!x->isString()) + JSValuePtr x = args.at(exec, 0); + if (!x.isString()) return x; - UString s = x->toString(exec); + UString s = x.toString(exec); int errLine; UString errMsg; @@ -291,43 +290,45 @@ JSValue* globalFuncEval(ExecState* exec, JSObject* function, JSValue* thisValue, if (!evalNode) return throwError(exec, SyntaxError, errMsg, errLine, source.provider()->asID(), NULL); - return exec->machine()->execute(evalNode.get(), exec, thisObject, globalObject->globalScopeChain().node(), exec->exceptionSlot()); + return exec->interpreter()->execute(evalNode.get(), exec, thisObject, static_cast<JSGlobalObject*>(unwrappedObject)->globalScopeChain().node(), exec->exceptionSlot()); } -JSValue* globalFuncParseInt(ExecState* exec, JSObject*, JSValue*, const ArgList& args) +JSValuePtr globalFuncParseInt(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) { - JSValue* value = args.at(exec, 0); - int32_t radix = args.at(exec, 1)->toInt32(exec); + JSValuePtr value = args.at(exec, 0); + int32_t radix = args.at(exec, 1).toInt32(exec); - if (value->isNumber() && (radix == 0 || radix == 10)) { - if (JSImmediate::isImmediate(value)) + if (value.isNumber() && (radix == 0 || radix == 10)) { + if (value.isInt32Fast()) return value; - double d = value->uncheckedGetNumber(); - if (!isfinite(d)) - return JSImmediate::zeroImmediate(); - return jsNumber(exec, floor(d)); + double d = value.uncheckedGetNumber(); + if (isfinite(d)) + return jsNumber(exec, floor(d)); + if (isnan(d) || isinf(d)) + return jsNaN(&exec->globalData()); + return js0(); } - return jsNumber(exec, parseInt(value->toString(exec), radix)); + return jsNumber(exec, parseInt(value.toString(exec), radix)); } -JSValue* globalFuncParseFloat(ExecState* exec, JSObject*, JSValue*, const ArgList& args) +JSValuePtr globalFuncParseFloat(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) { - return jsNumber(exec, parseFloat(args.at(exec, 0)->toString(exec))); + return jsNumber(exec, parseFloat(args.at(exec, 0).toString(exec))); } -JSValue* globalFuncIsNaN(ExecState* exec, JSObject*, JSValue*, const ArgList& args) +JSValuePtr globalFuncIsNaN(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) { - return jsBoolean(isnan(args.at(exec, 0)->toNumber(exec))); + return jsBoolean(isnan(args.at(exec, 0).toNumber(exec))); } -JSValue* globalFuncIsFinite(ExecState* exec, JSObject*, JSValue*, const ArgList& args) +JSValuePtr globalFuncIsFinite(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) { - double n = args.at(exec, 0)->toNumber(exec); + double n = args.at(exec, 0).toNumber(exec); return jsBoolean(!isnan(n) && !isinf(n)); } -JSValue* globalFuncDecodeURI(ExecState* exec, JSObject*, JSValue*, const ArgList& args) +JSValuePtr globalFuncDecodeURI(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) { static const char do_not_unescape_when_decoding_URI[] = "#$&+,/:;=?@"; @@ -335,12 +336,12 @@ JSValue* globalFuncDecodeURI(ExecState* exec, JSObject*, JSValue*, const ArgList return decode(exec, args, do_not_unescape_when_decoding_URI, true); } -JSValue* globalFuncDecodeURIComponent(ExecState* exec, JSObject*, JSValue*, const ArgList& args) +JSValuePtr globalFuncDecodeURIComponent(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) { return decode(exec, args, "", true); } -JSValue* globalFuncEncodeURI(ExecState* exec, JSObject*, JSValue*, const ArgList& args) +JSValuePtr globalFuncEncodeURI(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) { static const char do_not_escape_when_encoding_URI[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" @@ -351,7 +352,7 @@ JSValue* globalFuncEncodeURI(ExecState* exec, JSObject*, JSValue*, const ArgList return encode(exec, args, do_not_escape_when_encoding_URI); } -JSValue* globalFuncEncodeURIComponent(ExecState* exec, JSObject*, JSValue*, const ArgList& args) +JSValuePtr globalFuncEncodeURIComponent(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) { static const char do_not_escape_when_encoding_URI_component[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" @@ -362,7 +363,7 @@ JSValue* globalFuncEncodeURIComponent(ExecState* exec, JSObject*, JSValue*, cons return encode(exec, args, do_not_escape_when_encoding_URI_component); } -JSValue* globalFuncEscape(ExecState* exec, JSObject*, JSValue*, const ArgList& args) +JSValuePtr globalFuncEscape(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) { static const char do_not_escape[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" @@ -372,7 +373,7 @@ JSValue* globalFuncEscape(ExecState* exec, JSObject*, JSValue*, const ArgList& a UString result = ""; UString s; - UString str = args.at(exec, 0)->toString(exec); + UString str = args.at(exec, 0).toString(exec); const UChar* c = str.data(); for (int k = 0; k < str.size(); k++, c++) { int u = c[0]; @@ -393,10 +394,10 @@ JSValue* globalFuncEscape(ExecState* exec, JSObject*, JSValue*, const ArgList& a return jsString(exec, result); } -JSValue* globalFuncUnescape(ExecState* exec, JSObject*, JSValue*, const ArgList& args) +JSValuePtr globalFuncUnescape(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) { UString result = ""; - UString str = args.at(exec, 0)->toString(exec); + UString str = args.at(exec, 0).toString(exec); int k = 0; int len = str.size(); while (k < len) { @@ -421,10 +422,10 @@ JSValue* globalFuncUnescape(ExecState* exec, JSObject*, JSValue*, const ArgList& } #ifndef NDEBUG -JSValue* globalFuncKJSPrint(ExecState* exec, JSObject*, JSValue*, const ArgList& args) +JSValuePtr globalFuncJSCPrint(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) { CStringBuffer string; - args.at(exec, 0)->toString(exec).getCString(string); + args.at(exec, 0).toString(exec).getCString(string); puts(string.data()); return jsUndefined(); } diff --git a/JavaScriptCore/runtime/JSGlobalObjectFunctions.h b/JavaScriptCore/runtime/JSGlobalObjectFunctions.h index 8df700d..0929b17 100644 --- a/JavaScriptCore/runtime/JSGlobalObjectFunctions.h +++ b/JavaScriptCore/runtime/JSGlobalObjectFunctions.h @@ -1,6 +1,6 @@ /* * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) - * Copyright (C) 2003, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca) * Copyright (C) 2007 Maks Orlovich * @@ -24,34 +24,36 @@ #ifndef JSGlobalObjectFunctions_h #define JSGlobalObjectFunctions_h -#include "JSImmediate.h" // temporary until JSValue* becomes a class we can forward-declare +#include <wtf/unicode/Unicode.h> namespace JSC { class ArgList; class ExecState; class JSObject; + class JSValuePtr; // FIXME: These functions should really be in JSGlobalObject.cpp, but putting them there // is a 0.5% reduction. - JSValue* globalFuncEval(ExecState*, JSObject*, JSValue*, const ArgList&); - JSValue* globalFuncParseInt(ExecState*, JSObject*, JSValue*, const ArgList&); - JSValue* globalFuncParseFloat(ExecState*, JSObject*, JSValue*, const ArgList&); - JSValue* globalFuncIsNaN(ExecState*, JSObject*, JSValue*, const ArgList&); - JSValue* globalFuncIsFinite(ExecState*, JSObject*, JSValue*, const ArgList&); - JSValue* globalFuncDecodeURI(ExecState*, JSObject*, JSValue*, const ArgList&); - JSValue* globalFuncDecodeURIComponent(ExecState*, JSObject*, JSValue*, const ArgList&); - JSValue* globalFuncEncodeURI(ExecState*, JSObject*, JSValue*, const ArgList&); - JSValue* globalFuncEncodeURIComponent(ExecState*, JSObject*, JSValue*, const ArgList&); - JSValue* globalFuncEscape(ExecState*, JSObject*, JSValue*, const ArgList&); - JSValue* globalFuncUnescape(ExecState*, JSObject*, JSValue*, const ArgList&); + JSValuePtr globalFuncEval(ExecState*, JSObject*, JSValuePtr, const ArgList&); + JSValuePtr globalFuncParseInt(ExecState*, JSObject*, JSValuePtr, const ArgList&); + JSValuePtr globalFuncParseFloat(ExecState*, JSObject*, JSValuePtr, const ArgList&); + JSValuePtr globalFuncIsNaN(ExecState*, JSObject*, JSValuePtr, const ArgList&); + JSValuePtr globalFuncIsFinite(ExecState*, JSObject*, JSValuePtr, const ArgList&); + JSValuePtr globalFuncDecodeURI(ExecState*, JSObject*, JSValuePtr, const ArgList&); + JSValuePtr globalFuncDecodeURIComponent(ExecState*, JSObject*, JSValuePtr, const ArgList&); + JSValuePtr globalFuncEncodeURI(ExecState*, JSObject*, JSValuePtr, const ArgList&); + JSValuePtr globalFuncEncodeURIComponent(ExecState*, JSObject*, JSValuePtr, const ArgList&); + JSValuePtr globalFuncEscape(ExecState*, JSObject*, JSValuePtr, const ArgList&); + JSValuePtr globalFuncUnescape(ExecState*, JSObject*, JSValuePtr, const ArgList&); #ifndef NDEBUG - JSValue* globalFuncKJSPrint(ExecState*, JSObject*, JSValue*, const ArgList&); + JSValuePtr globalFuncJSCPrint(ExecState*, JSObject*, JSValuePtr, const ArgList&); #endif static const double mantissaOverflowLowerBound = 9007199254740992.0; double parseIntOverflow(const char*, int length, int radix); + bool isStrWhiteSpace(UChar); } // namespace JSC diff --git a/JavaScriptCore/runtime/JSImmediate.cpp b/JavaScriptCore/runtime/JSImmediate.cpp index e70d66a..c6cca80 100644 --- a/JavaScriptCore/runtime/JSImmediate.cpp +++ b/JavaScriptCore/runtime/JSImmediate.cpp @@ -32,20 +32,35 @@ namespace JSC { -JSObject* JSImmediate::toObject(JSValue* v, ExecState* exec) +JSObject* JSImmediate::toThisObject(JSValuePtr v, ExecState* exec) { ASSERT(isImmediate(v)); if (isNumber(v)) - return constructNumberFromImmediateNumber(exec, v); + return constructNumber(exec, v); if (isBoolean(v)) return constructBooleanFromImmediateBoolean(exec, v); + if (v.isNull()) + return exec->globalThisValue(); - JSNotAnObjectErrorStub* exception = createNotAnObjectErrorStub(exec, v->isNull()); + JSNotAnObjectErrorStub* exception = createNotAnObjectErrorStub(exec, v.isNull()); exec->setException(exception); return new (exec) JSNotAnObject(exec, exception); } -JSObject* JSImmediate::prototype(JSValue* v, ExecState* exec) +JSObject* JSImmediate::toObject(JSValuePtr v, ExecState* exec) +{ + ASSERT(isImmediate(v)); + if (isNumber(v)) + return constructNumber(exec, v); + if (isBoolean(v)) + return constructBooleanFromImmediateBoolean(exec, v); + + JSNotAnObjectErrorStub* exception = createNotAnObjectErrorStub(exec, v.isNull()); + exec->setException(exception); + return new (exec) JSNotAnObject(exec, exception); +} + +JSObject* JSImmediate::prototype(JSValuePtr v, ExecState* exec) { ASSERT(isImmediate(v)); if (isNumber(v)) @@ -53,23 +68,34 @@ JSObject* JSImmediate::prototype(JSValue* v, ExecState* exec) if (isBoolean(v)) return exec->lexicalGlobalObject()->booleanPrototype(); - JSNotAnObjectErrorStub* exception = createNotAnObjectErrorStub(exec, v->isNull()); + JSNotAnObjectErrorStub* exception = createNotAnObjectErrorStub(exec, v.isNull()); exec->setException(exception); return new (exec) JSNotAnObject(exec, exception); } -UString JSImmediate::toString(JSValue* v) +UString JSImmediate::toString(JSValuePtr v) { ASSERT(isImmediate(v)); - if (isNumber(v)) + if (isIntegerNumber(v)) return UString::from(getTruncatedInt32(v)); - if (v == jsBoolean(false)) +#if USE(ALTERNATE_JSIMMEDIATE) + if (isNumber(v)) { + ASSERT(isDoubleNumber(v)); + double value = doubleValue(v); + if (value == 0.0) // +0.0 or -0.0 + return "0"; + return UString::from(value); + } +#else + ASSERT(!isNumber(v)); +#endif + if (jsBoolean(false) == v) return "false"; - if (v == jsBoolean(true)) + if (jsBoolean(true) == v) return "true"; - if (v->isNull()) + if (v.isNull()) return "null"; - ASSERT(v == jsUndefined()); + ASSERT(v.isUndefined()); return "undefined"; } diff --git a/JavaScriptCore/runtime/JSImmediate.h b/JavaScriptCore/runtime/JSImmediate.h index 5214df5..3a44825 100644 --- a/JavaScriptCore/runtime/JSImmediate.h +++ b/JavaScriptCore/runtime/JSImmediate.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org) * * This library is free software; you can redistribute it and/or @@ -19,12 +19,14 @@ * */ -#ifndef KJS_JS_IMMEDIATE_H -#define KJS_JS_IMMEDIATE_H +#ifndef JSImmediate_h +#define JSImmediate_h #include <wtf/Assertions.h> #include <wtf/AlwaysInline.h> #include <wtf/MathExtras.h> +#include <wtf/StdLibExtras.h> +#include "JSValue.h" #include <limits> #include <limits.h> #include <stdarg.h> @@ -35,12 +37,48 @@ namespace JSC { class ExecState; class JSCell; + class JSFastMath; + class JSGlobalData; class JSObject; - class JSValue; class UString; - inline JSValue* noValue() { return 0; } - inline void* asPointer(JSValue* value) { return value; } + JSValuePtr js0(); + JSValuePtr jsNull(); + JSValuePtr jsBoolean(bool b); + JSValuePtr jsUndefined(); + JSValuePtr jsImpossibleValue(); + JSValuePtr jsNumber(ExecState* exec, double d); + JSValuePtr jsNumber(ExecState*, char i); + JSValuePtr jsNumber(ExecState*, unsigned char i); + JSValuePtr jsNumber(ExecState*, short i); + JSValuePtr jsNumber(ExecState*, unsigned short i); + JSValuePtr jsNumber(ExecState* exec, int i); + JSValuePtr jsNumber(ExecState* exec, unsigned i); + JSValuePtr jsNumber(ExecState* exec, long i); + JSValuePtr jsNumber(ExecState* exec, unsigned long i); + JSValuePtr jsNumber(ExecState* exec, long long i); + JSValuePtr jsNumber(ExecState* exec, unsigned long long i); + JSValuePtr jsNumber(JSGlobalData* globalData, double d); + JSValuePtr jsNumber(JSGlobalData* globalData, short i); + JSValuePtr jsNumber(JSGlobalData* globalData, unsigned short i); + JSValuePtr jsNumber(JSGlobalData* globalData, int i); + JSValuePtr jsNumber(JSGlobalData* globalData, unsigned i); + JSValuePtr jsNumber(JSGlobalData* globalData, long i); + JSValuePtr jsNumber(JSGlobalData* globalData, unsigned long i); + JSValuePtr jsNumber(JSGlobalData* globalData, long long i); + JSValuePtr jsNumber(JSGlobalData* globalData, unsigned long long i); + +#if USE(ALTERNATE_JSIMMEDIATE) + inline intptr_t reinterpretDoubleToIntptr(double value) + { + return WTF::bitwise_cast<intptr_t>(value); + } + + inline double reinterpretIntptrToDouble(intptr_t value) + { + return WTF::bitwise_cast<double>(value); + } +#endif /* * A JSValue* is either a pointer to a cell (a heap-allocated object) or an immediate (a type-tagged @@ -84,385 +122,716 @@ namespace JSC { * [ zero ] [ zero ] [ tag 'other' ] */ + /* + * On 64-bit platforms, we support an alternative encoding form for immediates, if + * USE(ALTERNATE_JSIMMEDIATE) is defined. When this format is used, double precision + * floating point values may also be encoded as JSImmediates. + * + * The encoding makes use of unused NaN space in the IEEE754 representation. Any value + * with the top 13 bits set represents a QNaN (with the sign bit set). QNaN values + * can encode a 51-bit payload. Hardware produced and C-library payloads typically + * have a payload of zero. We assume that non-zero payloads are available to encode + * pointer and integer values. Since any 64-bit bit pattern where the top 15 bits are + * all set represents a NaN with a non-zero payload, we can use this space in the NaN + * ranges to encode other values (however there are also other ranges of NaN space that + * could have been selected). This range of NaN space is represented by 64-bit numbers + * begining with the 16-bit hex patterns 0xFFFE and 0xFFFF - we rely on the fact that no + * valid double-precision numbers will begin fall in these ranges. + * + * The scheme we have implemented encodes double precision values by adding 2^48 to the + * 64-bit integer representation of the number. After this manipulation, no encoded + * double-precision value will begin with the pattern 0x0000 or 0xFFFF. + * + * The top 16-bits denote the type of the encoded JSImmediate: + * + * Pointer: 0000:PPPP:PPPP:PPPP + * 0001:****:****:**** + * Double:{ ... + * FFFE:****:****:**** + * Integer: FFFF:0000:IIII:IIII + * + * 32-bit signed integers are marked with the 16-bit tag 0xFFFF. The tag 0x0000 + * denotes a pointer, or another form of tagged immediate. Boolean, null and undefined + * values are encoded in the same manner as the default format. + */ + class JSImmediate { private: - friend class CTI; // Whooo! - - static const uintptr_t TagMask = 0x3u; // primary tag is 2 bits long - static const uintptr_t TagBitTypeInteger = 0x1u; // bottom bit set indicates integer, this dominates the following bit - static const uintptr_t TagBitTypeOther = 0x2u; // second bit set indicates immediate other than an integer - - static const uintptr_t ExtendedTagMask = 0xCu; // extended tag holds a further two bits - static const uintptr_t ExtendedTagBitBool = 0x4u; - static const uintptr_t ExtendedTagBitUndefined = 0x8u; - - static const uintptr_t FullTagTypeMask = TagMask | ExtendedTagMask; - static const uintptr_t FullTagTypeBool = TagBitTypeOther | ExtendedTagBitBool; - static const uintptr_t FullTagTypeUndefined = TagBitTypeOther | ExtendedTagBitUndefined; - static const uintptr_t FullTagTypeNull = TagBitTypeOther; + friend class JIT; + friend class JSValuePtr; + friend class JSFastMath; + friend JSValuePtr js0(); + friend JSValuePtr jsNull(); + friend JSValuePtr jsBoolean(bool b); + friend JSValuePtr jsUndefined(); + friend JSValuePtr jsImpossibleValue(); + friend JSValuePtr jsNumber(ExecState* exec, double d); + friend JSValuePtr jsNumber(ExecState*, char i); + friend JSValuePtr jsNumber(ExecState*, unsigned char i); + friend JSValuePtr jsNumber(ExecState*, short i); + friend JSValuePtr jsNumber(ExecState*, unsigned short i); + friend JSValuePtr jsNumber(ExecState* exec, int i); + friend JSValuePtr jsNumber(ExecState* exec, unsigned i); + friend JSValuePtr jsNumber(ExecState* exec, long i); + friend JSValuePtr jsNumber(ExecState* exec, unsigned long i); + friend JSValuePtr jsNumber(ExecState* exec, long long i); + friend JSValuePtr jsNumber(ExecState* exec, unsigned long long i); + friend JSValuePtr jsNumber(JSGlobalData* globalData, double d); + friend JSValuePtr jsNumber(JSGlobalData* globalData, short i); + friend JSValuePtr jsNumber(JSGlobalData* globalData, unsigned short i); + friend JSValuePtr jsNumber(JSGlobalData* globalData, int i); + friend JSValuePtr jsNumber(JSGlobalData* globalData, unsigned i); + friend JSValuePtr jsNumber(JSGlobalData* globalData, long i); + friend JSValuePtr jsNumber(JSGlobalData* globalData, unsigned long i); + friend JSValuePtr jsNumber(JSGlobalData* globalData, long long i); + friend JSValuePtr jsNumber(JSGlobalData* globalData, unsigned long long i); + +#if USE(ALTERNATE_JSIMMEDIATE) + // If all bits in the mask are set, this indicates an integer number, + // if any but not all are set this value is a double precision number. + static const intptr_t TagTypeNumber = 0xffff000000000000ll; + // This value is 2^48, used to encode doubles such that the encoded value will begin + // with a 16-bit pattern within the range 0x0001..0xFFFE. + static const intptr_t DoubleEncodeOffset = 0x1000000000000ll; +#else + static const intptr_t TagTypeNumber = 0x1; // bottom bit set indicates integer, this dominates the following bit +#endif + static const intptr_t TagBitTypeOther = 0x2; // second bit set indicates immediate other than an integer + static const intptr_t TagMask = TagTypeNumber | TagBitTypeOther; + + static const intptr_t ExtendedTagMask = 0xC; // extended tag holds a further two bits + static const intptr_t ExtendedTagBitBool = 0x4; + static const intptr_t ExtendedTagBitUndefined = 0x8; + + static const intptr_t FullTagTypeMask = TagMask | ExtendedTagMask; + static const intptr_t FullTagTypeBool = TagBitTypeOther | ExtendedTagBitBool; + static const intptr_t FullTagTypeUndefined = TagBitTypeOther | ExtendedTagBitUndefined; + static const intptr_t FullTagTypeNull = TagBitTypeOther; + +#if USE(ALTERNATE_JSIMMEDIATE) + static const int32_t IntegerPayloadShift = 0; +#else + static const int32_t IntegerPayloadShift = 1; +#endif + static const int32_t ExtendedPayloadShift = 4; - static const uint32_t IntegerPayloadShift = 1u; - static const uint32_t ExtendedPayloadShift = 4u; + static const intptr_t ExtendedPayloadBitBoolValue = 1 << ExtendedPayloadShift; - static const uintptr_t ExtendedPayloadBitBoolValue = 1 << ExtendedPayloadShift; + static const int32_t signBit = 0x80000000; - public: - static ALWAYS_INLINE bool isImmediate(JSValue* v) + static ALWAYS_INLINE bool isImmediate(JSValuePtr v) { return rawValue(v) & TagMask; } - static ALWAYS_INLINE bool isNumber(JSValue* v) + static ALWAYS_INLINE bool isNumber(JSValuePtr v) { - return rawValue(v) & TagBitTypeInteger; + return rawValue(v) & TagTypeNumber; + } + + static ALWAYS_INLINE bool isIntegerNumber(JSValuePtr v) + { +#if USE(ALTERNATE_JSIMMEDIATE) + return (rawValue(v) & TagTypeNumber) == TagTypeNumber; +#else + return isNumber(v); +#endif } - static ALWAYS_INLINE bool isPositiveNumber(JSValue* v) +#if USE(ALTERNATE_JSIMMEDIATE) + static ALWAYS_INLINE bool isDoubleNumber(JSValuePtr v) + { + return isNumber(v) && !isIntegerNumber(v); + } +#endif + + static ALWAYS_INLINE bool isPositiveIntegerNumber(JSValuePtr v) { // A single mask to check for the sign bit and the number tag all at once. - return (rawValue(v) & (0x80000000 | TagBitTypeInteger)) == TagBitTypeInteger; + return (rawValue(v) & (signBit | TagTypeNumber)) == TagTypeNumber; } - static ALWAYS_INLINE bool isBoolean(JSValue* v) + static ALWAYS_INLINE bool isBoolean(JSValuePtr v) { return (rawValue(v) & FullTagTypeMask) == FullTagTypeBool; } - static ALWAYS_INLINE bool isUndefinedOrNull(JSValue* v) + static ALWAYS_INLINE bool isUndefinedOrNull(JSValuePtr v) { // Undefined and null share the same value, bar the 'undefined' bit in the extended tag. return (rawValue(v) & ~ExtendedTagBitUndefined) == FullTagTypeNull; } - static bool isNegative(JSValue* v) - { - ASSERT(isNumber(v)); - return rawValue(v) & 0x80000000; - } - - static JSValue* from(char); - static JSValue* from(signed char); - static JSValue* from(unsigned char); - static JSValue* from(short); - static JSValue* from(unsigned short); - static JSValue* from(int); - static JSValue* from(unsigned); - static JSValue* from(long); - static JSValue* from(unsigned long); - static JSValue* from(long long); - static JSValue* from(unsigned long long); - static JSValue* from(double); - - static ALWAYS_INLINE bool isEitherImmediate(JSValue* v1, JSValue* v2) + static JSValuePtr from(char); + static JSValuePtr from(signed char); + static JSValuePtr from(unsigned char); + static JSValuePtr from(short); + static JSValuePtr from(unsigned short); + static JSValuePtr from(int); + static JSValuePtr from(unsigned); + static JSValuePtr from(long); + static JSValuePtr from(unsigned long); + static JSValuePtr from(long long); + static JSValuePtr from(unsigned long long); + static JSValuePtr from(double); + + static ALWAYS_INLINE bool isEitherImmediate(JSValuePtr v1, JSValuePtr v2) { return (rawValue(v1) | rawValue(v2)) & TagMask; } - static ALWAYS_INLINE bool isAnyImmediate(JSValue* v1, JSValue* v2, JSValue* v3) - { - return (rawValue(v1) | rawValue(v2) | rawValue(v3)) & TagMask; - } - - static ALWAYS_INLINE bool areBothImmediate(JSValue* v1, JSValue* v2) + static ALWAYS_INLINE bool areBothImmediate(JSValuePtr v1, JSValuePtr v2) { return isImmediate(v1) & isImmediate(v2); } - static ALWAYS_INLINE bool areBothImmediateNumbers(JSValue* v1, JSValue* v2) + static ALWAYS_INLINE bool areBothImmediateIntegerNumbers(JSValuePtr v1, JSValuePtr v2) { - return rawValue(v1) & rawValue(v2) & TagBitTypeInteger; - } - - static ALWAYS_INLINE JSValue* andImmediateNumbers(JSValue* v1, JSValue* v2) - { - ASSERT(areBothImmediateNumbers(v1, v2)); - return makeValue(rawValue(v1) & rawValue(v2)); - } - - static ALWAYS_INLINE JSValue* xorImmediateNumbers(JSValue* v1, JSValue* v2) - { - ASSERT(areBothImmediateNumbers(v1, v2)); - return makeValue((rawValue(v1) ^ rawValue(v2)) | TagBitTypeInteger); - } - - static ALWAYS_INLINE JSValue* orImmediateNumbers(JSValue* v1, JSValue* v2) - { - ASSERT(areBothImmediateNumbers(v1, v2)); - return makeValue(rawValue(v1) | rawValue(v2)); - } - - static ALWAYS_INLINE JSValue* rightShiftImmediateNumbers(JSValue* val, JSValue* shift) - { - ASSERT(areBothImmediateNumbers(val, shift)); - return makeValue((static_cast<intptr_t>(rawValue(val)) >> ((rawValue(shift) >> IntegerPayloadShift) & 0x1f)) | TagBitTypeInteger); - } - - static ALWAYS_INLINE bool canDoFastAdditiveOperations(JSValue* v) - { - // Number is non-negative and an operation involving two of these can't overflow. - // Checking for allowed negative numbers takes more time than it's worth on SunSpider. - return (rawValue(v) & (TagBitTypeInteger + (3u << 30))) == TagBitTypeInteger; - } - - static ALWAYS_INLINE JSValue* addImmediateNumbers(JSValue* v1, JSValue* v2) - { - ASSERT(canDoFastAdditiveOperations(v1)); - ASSERT(canDoFastAdditiveOperations(v2)); - return makeValue(rawValue(v1) + rawValue(v2) - TagBitTypeInteger); - } - - static ALWAYS_INLINE JSValue* subImmediateNumbers(JSValue* v1, JSValue* v2) - { - ASSERT(canDoFastAdditiveOperations(v1)); - ASSERT(canDoFastAdditiveOperations(v2)); - return makeValue(rawValue(v1) - rawValue(v2) + TagBitTypeInteger); - } - - static ALWAYS_INLINE JSValue* incImmediateNumber(JSValue* v) - { - ASSERT(canDoFastAdditiveOperations(v)); - return makeValue(rawValue(v) + (1 << IntegerPayloadShift)); - } - - static ALWAYS_INLINE JSValue* decImmediateNumber(JSValue* v) - { - ASSERT(canDoFastAdditiveOperations(v)); - return makeValue(rawValue(v) - (1 << IntegerPayloadShift)); +#if USE(ALTERNATE_JSIMMEDIATE) + return (rawValue(v1) & rawValue(v2) & TagTypeNumber) == TagTypeNumber; +#else + return rawValue(v1) & rawValue(v2) & TagTypeNumber; +#endif } - static double toDouble(JSValue*); - static bool toBoolean(JSValue*); - static JSObject* toObject(JSValue*, ExecState*); - static UString toString(JSValue*); + static double toDouble(JSValuePtr); + static bool toBoolean(JSValuePtr); + static JSObject* toObject(JSValuePtr, ExecState*); + static JSObject* toThisObject(JSValuePtr, ExecState*); + static UString toString(JSValuePtr); - static bool getUInt32(JSValue*, uint32_t&); - static bool getTruncatedInt32(JSValue*, int32_t&); - static bool getTruncatedUInt32(JSValue*, uint32_t&); + static bool getUInt32(JSValuePtr, uint32_t&); + static bool getTruncatedInt32(JSValuePtr, int32_t&); + static bool getTruncatedUInt32(JSValuePtr, uint32_t&); - static int32_t getTruncatedInt32(JSValue*); - static uint32_t getTruncatedUInt32(JSValue*); + static int32_t getTruncatedInt32(JSValuePtr); + static uint32_t getTruncatedUInt32(JSValuePtr); - static JSValue* trueImmediate(); - static JSValue* falseImmediate(); - static JSValue* undefinedImmediate(); - static JSValue* nullImmediate(); - static JSValue* zeroImmediate(); - static JSValue* oneImmediate(); + static JSValuePtr trueImmediate(); + static JSValuePtr falseImmediate(); + static JSValuePtr undefinedImmediate(); + static JSValuePtr nullImmediate(); + static JSValuePtr zeroImmediate(); + static JSValuePtr oneImmediate(); - static JSValue* impossibleValue(); + static JSValuePtr impossibleValue(); - static JSObject* prototype(JSValue*, ExecState*); + static JSObject* prototype(JSValuePtr, ExecState*); private: +#if USE(ALTERNATE_JSIMMEDIATE) + static const int minImmediateInt = ((-INT_MAX) - 1); + static const int maxImmediateInt = INT_MAX; +#else static const int minImmediateInt = ((-INT_MAX) - 1) >> IntegerPayloadShift; static const int maxImmediateInt = INT_MAX >> IntegerPayloadShift; +#endif static const unsigned maxImmediateUInt = maxImmediateInt; - static ALWAYS_INLINE JSValue* makeValue(uintptr_t integer) + static ALWAYS_INLINE JSValuePtr makeValue(intptr_t integer) { - return reinterpret_cast<JSValue*>(integer); + return JSValuePtr::makeImmediate(integer); } - static ALWAYS_INLINE JSValue* makeInt(int32_t value) + // With USE(ALTERNATE_JSIMMEDIATE) we want the argument to be zero extended, so the + // integer doesn't interfere with the tag bits in the upper word. In the default encoding, + // if intptr_t id larger then int32_t we sign extend the value through the upper word. +#if USE(ALTERNATE_JSIMMEDIATE) + static ALWAYS_INLINE JSValuePtr makeInt(uint32_t value) +#else + static ALWAYS_INLINE JSValuePtr makeInt(int32_t value) +#endif { - return makeValue((value << IntegerPayloadShift) | TagBitTypeInteger); + return makeValue((static_cast<intptr_t>(value) << IntegerPayloadShift) | TagTypeNumber); } - static ALWAYS_INLINE JSValue* makeBool(bool b) +#if USE(ALTERNATE_JSIMMEDIATE) + static ALWAYS_INLINE JSValuePtr makeDouble(double value) { - return makeValue((static_cast<uintptr_t>(b) << ExtendedPayloadShift) | FullTagTypeBool); + return makeValue(reinterpretDoubleToIntptr(value) + DoubleEncodeOffset); } +#endif - static ALWAYS_INLINE JSValue* makeUndefined() + static ALWAYS_INLINE JSValuePtr makeBool(bool b) + { + return makeValue((static_cast<intptr_t>(b) << ExtendedPayloadShift) | FullTagTypeBool); + } + + static ALWAYS_INLINE JSValuePtr makeUndefined() { return makeValue(FullTagTypeUndefined); } - static ALWAYS_INLINE JSValue* makeNull() + static ALWAYS_INLINE JSValuePtr makeNull() { return makeValue(FullTagTypeNull); } - - static ALWAYS_INLINE int32_t intValue(JSValue* v) + + template<typename T> + static JSValuePtr fromNumberOutsideIntegerRange(T); + +#if USE(ALTERNATE_JSIMMEDIATE) + static ALWAYS_INLINE double doubleValue(JSValuePtr v) { - return static_cast<int32_t>(static_cast<intptr_t>(rawValue(v)) >> IntegerPayloadShift); + return reinterpretIntptrToDouble(rawValue(v) - DoubleEncodeOffset); + } +#endif + + static ALWAYS_INLINE int32_t intValue(JSValuePtr v) + { + return static_cast<int32_t>(rawValue(v) >> IntegerPayloadShift); } - static ALWAYS_INLINE uint32_t uintValue(JSValue* v) + static ALWAYS_INLINE uint32_t uintValue(JSValuePtr v) { return static_cast<uint32_t>(rawValue(v) >> IntegerPayloadShift); } - static ALWAYS_INLINE bool boolValue(JSValue* v) + static ALWAYS_INLINE bool boolValue(JSValuePtr v) { return rawValue(v) & ExtendedPayloadBitBoolValue; } - static ALWAYS_INLINE uintptr_t rawValue(JSValue* v) + static ALWAYS_INLINE intptr_t rawValue(JSValuePtr v) { - return reinterpret_cast<uintptr_t>(v); + return v.immediateValue(); } static double nonInlineNaN(); }; - ALWAYS_INLINE JSValue* JSImmediate::trueImmediate() { return makeBool(true); } - ALWAYS_INLINE JSValue* JSImmediate::falseImmediate() { return makeBool(false); } - ALWAYS_INLINE JSValue* JSImmediate::undefinedImmediate() { return makeUndefined(); } - ALWAYS_INLINE JSValue* JSImmediate::nullImmediate() { return makeNull(); } - ALWAYS_INLINE JSValue* JSImmediate::zeroImmediate() { return makeInt(0); } - ALWAYS_INLINE JSValue* JSImmediate::oneImmediate() { return makeInt(1); } + ALWAYS_INLINE JSValuePtr JSImmediate::trueImmediate() { return makeBool(true); } + ALWAYS_INLINE JSValuePtr JSImmediate::falseImmediate() { return makeBool(false); } + ALWAYS_INLINE JSValuePtr JSImmediate::undefinedImmediate() { return makeUndefined(); } + ALWAYS_INLINE JSValuePtr JSImmediate::nullImmediate() { return makeNull(); } + ALWAYS_INLINE JSValuePtr JSImmediate::zeroImmediate() { return makeInt(0); } + ALWAYS_INLINE JSValuePtr JSImmediate::oneImmediate() { return makeInt(1); } // This value is impossible because 0x4 is not a valid pointer but a tag of 0 would indicate non-immediate - ALWAYS_INLINE JSValue* JSImmediate::impossibleValue() { return makeValue(0x4); } + ALWAYS_INLINE JSValuePtr JSImmediate::impossibleValue() { return makeValue(0x4); } + +#if USE(ALTERNATE_JSIMMEDIATE) + inline bool doubleToBoolean(double value) + { + return value < 0.0 || value > 0.0; + } - ALWAYS_INLINE bool JSImmediate::toBoolean(JSValue* v) + ALWAYS_INLINE bool JSImmediate::toBoolean(JSValuePtr v) + { + ASSERT(isImmediate(v)); + return isNumber(v) ? isIntegerNumber(v) ? v != zeroImmediate() + : doubleToBoolean(doubleValue(v)) : v == trueImmediate(); + } +#else + ALWAYS_INLINE bool JSImmediate::toBoolean(JSValuePtr v) { ASSERT(isImmediate(v)); - uintptr_t bits = rawValue(v); - return (bits & TagBitTypeInteger) - ? bits != TagBitTypeInteger // !0 ints - : bits == (FullTagTypeBool | ExtendedPayloadBitBoolValue); // bool true + return isIntegerNumber(v) ? v != zeroImmediate() : v == trueImmediate(); } +#endif - ALWAYS_INLINE uint32_t JSImmediate::getTruncatedUInt32(JSValue* v) + ALWAYS_INLINE uint32_t JSImmediate::getTruncatedUInt32(JSValuePtr v) { - ASSERT(isNumber(v)); + // FIXME: should probably be asserting isPositiveIntegerNumber here. + ASSERT(isIntegerNumber(v)); return intValue(v); } - ALWAYS_INLINE JSValue* JSImmediate::from(char i) +#if USE(ALTERNATE_JSIMMEDIATE) + template<typename T> + inline JSValuePtr JSImmediate::fromNumberOutsideIntegerRange(T value) + { + return makeDouble(static_cast<double>(value)); + } +#else + template<typename T> + inline JSValuePtr JSImmediate::fromNumberOutsideIntegerRange(T) + { + return noValue(); + } +#endif + + ALWAYS_INLINE JSValuePtr JSImmediate::from(char i) { return makeInt(i); } - ALWAYS_INLINE JSValue* JSImmediate::from(signed char i) + ALWAYS_INLINE JSValuePtr JSImmediate::from(signed char i) { return makeInt(i); } - ALWAYS_INLINE JSValue* JSImmediate::from(unsigned char i) + ALWAYS_INLINE JSValuePtr JSImmediate::from(unsigned char i) { return makeInt(i); } - ALWAYS_INLINE JSValue* JSImmediate::from(short i) + ALWAYS_INLINE JSValuePtr JSImmediate::from(short i) { return makeInt(i); } - ALWAYS_INLINE JSValue* JSImmediate::from(unsigned short i) + ALWAYS_INLINE JSValuePtr JSImmediate::from(unsigned short i) { return makeInt(i); } - ALWAYS_INLINE JSValue* JSImmediate::from(int i) + ALWAYS_INLINE JSValuePtr JSImmediate::from(int i) { +#if !USE(ALTERNATE_JSIMMEDIATE) if ((i < minImmediateInt) | (i > maxImmediateInt)) - return noValue(); + return fromNumberOutsideIntegerRange(i); +#endif return makeInt(i); } - ALWAYS_INLINE JSValue* JSImmediate::from(unsigned i) + ALWAYS_INLINE JSValuePtr JSImmediate::from(unsigned i) { if (i > maxImmediateUInt) - return noValue(); + return fromNumberOutsideIntegerRange(i); return makeInt(i); } - ALWAYS_INLINE JSValue* JSImmediate::from(long i) + ALWAYS_INLINE JSValuePtr JSImmediate::from(long i) { if ((i < minImmediateInt) | (i > maxImmediateInt)) - return noValue(); + return fromNumberOutsideIntegerRange(i); return makeInt(i); } - ALWAYS_INLINE JSValue* JSImmediate::from(unsigned long i) + ALWAYS_INLINE JSValuePtr JSImmediate::from(unsigned long i) { if (i > maxImmediateUInt) - return noValue(); + return fromNumberOutsideIntegerRange(i); return makeInt(i); } - ALWAYS_INLINE JSValue* JSImmediate::from(long long i) + ALWAYS_INLINE JSValuePtr JSImmediate::from(long long i) { if ((i < minImmediateInt) | (i > maxImmediateInt)) return noValue(); - return makeInt(static_cast<uintptr_t>(i)); + return makeInt(static_cast<intptr_t>(i)); } - ALWAYS_INLINE JSValue* JSImmediate::from(unsigned long long i) + ALWAYS_INLINE JSValuePtr JSImmediate::from(unsigned long long i) { if (i > maxImmediateUInt) - return noValue(); - return makeInt(static_cast<uintptr_t>(i)); + return fromNumberOutsideIntegerRange(i); + return makeInt(static_cast<intptr_t>(i)); } - ALWAYS_INLINE JSValue* JSImmediate::from(double d) + ALWAYS_INLINE JSValuePtr JSImmediate::from(double d) { const int intVal = static_cast<int>(d); - if ((intVal < minImmediateInt) | (intVal > maxImmediateInt)) - return noValue(); - // Check for data loss from conversion to int. if (intVal != d || (!intVal && signbit(d))) - return noValue(); + return fromNumberOutsideIntegerRange(d); - return makeInt(intVal); + return from(intVal); } - ALWAYS_INLINE int32_t JSImmediate::getTruncatedInt32(JSValue* v) + ALWAYS_INLINE int32_t JSImmediate::getTruncatedInt32(JSValuePtr v) { - ASSERT(isNumber(v)); + ASSERT(isIntegerNumber(v)); return intValue(v); } - ALWAYS_INLINE double JSImmediate::toDouble(JSValue* v) + ALWAYS_INLINE double JSImmediate::toDouble(JSValuePtr v) { ASSERT(isImmediate(v)); - int i; - if (isNumber(v)) - i = intValue(v); - else if (rawValue(v) == FullTagTypeUndefined) + + if (isIntegerNumber(v)) + return intValue(v); + +#if USE(ALTERNATE_JSIMMEDIATE) + if (isNumber(v)) { + ASSERT(isDoubleNumber(v)); + return doubleValue(v); + } +#else + ASSERT(!isNumber(v)); +#endif + + if (rawValue(v) == FullTagTypeUndefined) return nonInlineNaN(); - else - i = rawValue(v) >> ExtendedPayloadShift; - return i; + + ASSERT(JSImmediate::isBoolean(v) || (v == JSImmediate::nullImmediate())); + return rawValue(v) >> ExtendedPayloadShift; } - ALWAYS_INLINE bool JSImmediate::getUInt32(JSValue* v, uint32_t& i) + ALWAYS_INLINE bool JSImmediate::getUInt32(JSValuePtr v, uint32_t& i) { i = uintValue(v); - return isPositiveNumber(v); + return isPositiveIntegerNumber(v); } - ALWAYS_INLINE bool JSImmediate::getTruncatedInt32(JSValue* v, int32_t& i) + ALWAYS_INLINE bool JSImmediate::getTruncatedInt32(JSValuePtr v, int32_t& i) { i = intValue(v); - return isNumber(v); + return isIntegerNumber(v); } - ALWAYS_INLINE bool JSImmediate::getTruncatedUInt32(JSValue* v, uint32_t& i) + ALWAYS_INLINE bool JSImmediate::getTruncatedUInt32(JSValuePtr v, uint32_t& i) { return getUInt32(v, i); } - ALWAYS_INLINE JSValue* jsUndefined() + inline JSValuePtr js0() { - return JSImmediate::undefinedImmediate(); + return JSImmediate::zeroImmediate(); } - inline JSValue* jsNull() + inline JSValuePtr jsNull() { return JSImmediate::nullImmediate(); } - inline JSValue* jsBoolean(bool b) + inline JSValuePtr jsBoolean(bool b) { return b ? JSImmediate::trueImmediate() : JSImmediate::falseImmediate(); } -} // namespace JSC + inline JSValuePtr jsUndefined() + { + return JSImmediate::undefinedImmediate(); + } + + inline JSValuePtr jsImpossibleValue() + { + return JSImmediate::impossibleValue(); + } + + // These are identical logic to the JSValue functions above, and faster than jsNumber(number).toInt32(). + int32_t toInt32(double); + uint32_t toUInt32(double); + int32_t toInt32SlowCase(double, bool& ok); + uint32_t toUInt32SlowCase(double, bool& ok); + + inline bool JSValuePtr::isUndefined() const + { + return asValue() == jsUndefined(); + } + + inline bool JSValuePtr::isNull() const + { + return asValue() == jsNull(); + } + + inline bool JSValuePtr::isUndefinedOrNull() const + { + return JSImmediate::isUndefinedOrNull(asValue()); + } + + inline bool JSValuePtr::isBoolean() const + { + return JSImmediate::isBoolean(asValue()); + } + + inline bool JSValuePtr::getBoolean(bool& v) const + { + if (JSImmediate::isBoolean(asValue())) { + v = JSImmediate::toBoolean(asValue()); + return true; + } + + return false; + } + + inline bool JSValuePtr::getBoolean() const + { + return asValue() == jsBoolean(true); + } + + ALWAYS_INLINE int32_t JSValuePtr::toInt32(ExecState* exec) const + { + int32_t i; + if (getTruncatedInt32(i)) + return i; + bool ignored; + return toInt32SlowCase(toNumber(exec), ignored); + } + + inline uint32_t JSValuePtr::toUInt32(ExecState* exec) const + { + uint32_t i; + if (getTruncatedUInt32(i)) + return i; + bool ignored; + return toUInt32SlowCase(toNumber(exec), ignored); + } + + inline int32_t toInt32(double val) + { + if (!(val >= -2147483648.0 && val < 2147483648.0)) { + bool ignored; + return toInt32SlowCase(val, ignored); + } + return static_cast<int32_t>(val); + } + + inline uint32_t toUInt32(double val) + { + if (!(val >= 0.0 && val < 4294967296.0)) { + bool ignored; + return toUInt32SlowCase(val, ignored); + } + return static_cast<uint32_t>(val); + } + + inline int32_t JSValuePtr::toInt32(ExecState* exec, bool& ok) const + { + int32_t i; + if (getTruncatedInt32(i)) { + ok = true; + return i; + } + return toInt32SlowCase(toNumber(exec), ok); + } + + inline uint32_t JSValuePtr::toUInt32(ExecState* exec, bool& ok) const + { + uint32_t i; + if (getTruncatedUInt32(i)) { + ok = true; + return i; + } + return toUInt32SlowCase(toNumber(exec), ok); + } + + inline bool JSValuePtr::isCell() const + { + return !JSImmediate::isImmediate(asValue()); + } + + inline bool JSValuePtr::isInt32Fast() const + { + return JSImmediate::isIntegerNumber(asValue()); + } + + inline int32_t JSValuePtr::getInt32Fast() const + { + ASSERT(isInt32Fast()); + return JSImmediate::getTruncatedInt32(asValue()); + } + + inline bool JSValuePtr::isUInt32Fast() const + { + return JSImmediate::isPositiveIntegerNumber(asValue()); + } + + inline uint32_t JSValuePtr::getUInt32Fast() const + { + ASSERT(isUInt32Fast()); + return JSImmediate::getTruncatedUInt32(asValue()); + } + + inline JSValuePtr JSValuePtr::makeInt32Fast(int32_t i) + { + return JSImmediate::from(i); + } + inline bool JSValuePtr::areBothInt32Fast(JSValuePtr v1, JSValuePtr v2) + { + return JSImmediate::areBothImmediateIntegerNumbers(v1, v2); + } + + class JSFastMath { + public: + static ALWAYS_INLINE bool canDoFastBitwiseOperations(JSValuePtr v1, JSValuePtr v2) + { + return JSImmediate::areBothImmediateIntegerNumbers(v1, v2); + } + + static ALWAYS_INLINE JSValuePtr equal(JSValuePtr v1, JSValuePtr v2) + { + ASSERT(canDoFastBitwiseOperations(v1, v2)); + return jsBoolean(v1 == v2); + } + + static ALWAYS_INLINE JSValuePtr notEqual(JSValuePtr v1, JSValuePtr v2) + { + ASSERT(canDoFastBitwiseOperations(v1, v2)); + return jsBoolean(v1 != v2); + } + + static ALWAYS_INLINE JSValuePtr andImmediateNumbers(JSValuePtr v1, JSValuePtr v2) + { + ASSERT(canDoFastBitwiseOperations(v1, v2)); + return JSImmediate::makeValue(JSImmediate::rawValue(v1) & JSImmediate::rawValue(v2)); + } + + static ALWAYS_INLINE JSValuePtr xorImmediateNumbers(JSValuePtr v1, JSValuePtr v2) + { + ASSERT(canDoFastBitwiseOperations(v1, v2)); + return JSImmediate::makeValue((JSImmediate::rawValue(v1) ^ JSImmediate::rawValue(v2)) | JSImmediate::TagTypeNumber); + } + + static ALWAYS_INLINE JSValuePtr orImmediateNumbers(JSValuePtr v1, JSValuePtr v2) + { + ASSERT(canDoFastBitwiseOperations(v1, v2)); + return JSImmediate::makeValue(JSImmediate::rawValue(v1) | JSImmediate::rawValue(v2)); + } + + static ALWAYS_INLINE bool canDoFastRshift(JSValuePtr v1, JSValuePtr v2) + { + return JSImmediate::areBothImmediateIntegerNumbers(v1, v2); + } + + static ALWAYS_INLINE bool canDoFastUrshift(JSValuePtr v1, JSValuePtr v2) + { + return JSImmediate::areBothImmediateIntegerNumbers(v1, v2) && !(JSImmediate::rawValue(v1) & JSImmediate::signBit); + } + + static ALWAYS_INLINE JSValuePtr rightShiftImmediateNumbers(JSValuePtr val, JSValuePtr shift) + { + ASSERT(canDoFastRshift(val, shift) || canDoFastUrshift(val, shift)); +#if USE(ALTERNATE_JSIMMEDIATE) + return JSImmediate::makeValue(static_cast<intptr_t>(static_cast<uint32_t>(static_cast<int32_t>(JSImmediate::rawValue(val)) >> ((JSImmediate::rawValue(shift) >> JSImmediate::IntegerPayloadShift) & 0x1f))) | JSImmediate::TagTypeNumber); +#else + return JSImmediate::makeValue((JSImmediate::rawValue(val) >> ((JSImmediate::rawValue(shift) >> JSImmediate::IntegerPayloadShift) & 0x1f)) | JSImmediate::TagTypeNumber); #endif + } + + static ALWAYS_INLINE bool canDoFastAdditiveOperations(JSValuePtr v) + { + // Number is non-negative and an operation involving two of these can't overflow. + // Checking for allowed negative numbers takes more time than it's worth on SunSpider. + return (JSImmediate::rawValue(v) & (JSImmediate::TagTypeNumber + (JSImmediate::signBit | (JSImmediate::signBit >> 1)))) == JSImmediate::TagTypeNumber; + } + + static ALWAYS_INLINE bool canDoFastAdditiveOperations(JSValuePtr v1, JSValuePtr v2) + { + // Number is non-negative and an operation involving two of these can't overflow. + // Checking for allowed negative numbers takes more time than it's worth on SunSpider. + return canDoFastAdditiveOperations(v1) && canDoFastAdditiveOperations(v2); + } + + static ALWAYS_INLINE JSValuePtr addImmediateNumbers(JSValuePtr v1, JSValuePtr v2) + { + ASSERT(canDoFastAdditiveOperations(v1, v2)); + return JSImmediate::makeValue(JSImmediate::rawValue(v1) + JSImmediate::rawValue(v2) - JSImmediate::TagTypeNumber); + } + + static ALWAYS_INLINE JSValuePtr subImmediateNumbers(JSValuePtr v1, JSValuePtr v2) + { + ASSERT(canDoFastAdditiveOperations(v1, v2)); + return JSImmediate::makeValue(JSImmediate::rawValue(v1) - JSImmediate::rawValue(v2) + JSImmediate::TagTypeNumber); + } + + static ALWAYS_INLINE JSValuePtr incImmediateNumber(JSValuePtr v) + { + ASSERT(canDoFastAdditiveOperations(v)); + return JSImmediate::makeValue(JSImmediate::rawValue(v) + (1 << JSImmediate::IntegerPayloadShift)); + } + + static ALWAYS_INLINE JSValuePtr decImmediateNumber(JSValuePtr v) + { + ASSERT(canDoFastAdditiveOperations(v)); + return JSImmediate::makeValue(JSImmediate::rawValue(v) - (1 << JSImmediate::IntegerPayloadShift)); + } + }; + +} // namespace JSC + +#endif // JSImmediate_h diff --git a/JavaScriptCore/runtime/JSLock.cpp b/JavaScriptCore/runtime/JSLock.cpp index ee7fb3b..7ece5da 100644 --- a/JavaScriptCore/runtime/JSLock.cpp +++ b/JavaScriptCore/runtime/JSLock.cpp @@ -21,8 +21,8 @@ #include "config.h" #include "JSLock.h" -#include "collector.h" -#include "ExecState.h" +#include "Collector.h" +#include "CallFrame.h" #if ENABLE(JSC_MULTIPLE_THREADS) #include <pthread.h> @@ -119,11 +119,58 @@ bool JSLock::currentThreadIsHoldingLock() return !!pthread_getspecific(JSLockCount); } +// This is fairly nasty. We allow multiple threads to run on the same +// context, and we do not require any locking semantics in doing so - +// clients of the API may simply use the context from multiple threads +// concurently, and assume this will work. In order to make this work, +// We lock the context when a thread enters, and unlock it when it leaves. +// However we do not only unlock when the thread returns from its +// entry point (evaluate script or call function), we also unlock the +// context if the thread leaves JSC by making a call out to an external +// function through a callback. +// +// All threads using the context share the same JS stack (the RegisterFile). +// Whenever a thread calls into JSC it starts using the RegisterFile from the +// previous 'high water mark' - the maximum point the stack has ever grown to +// (returned by RegisterFile::end()). So if a first thread calls out to a +// callback, and a second thread enters JSC, then also exits by calling out +// to a callback, we can be left with stackframes from both threads in the +// RegisterFile. As such, a problem may occur should the first thread's +// callback complete first, and attempt to return to JSC. Were we to allow +// this to happen, and were its stack to grow further, then it may potentially +// write over the second thread's call frames. +// +// In avoid JS stack corruption we enforce a policy of only ever allowing two +// threads to use a JS context concurrently, and only allowing the second of +// these threads to execute until it has completed and fully returned from its +// outermost call into JSC. We enforce this policy using 'lockDropDepth'. The +// first time a thread exits it will call DropAllLocks - which will do as expected +// and drop locks allowing another thread to enter. Should another thread, or the +// same thread again, enter JSC (through evaluate script or call function), and exit +// again through a callback, then the locks will not be dropped when DropAllLocks +// is called (since lockDropDepth is non-zero). Since this thread is still holding +// the locks, only it will re able to re-enter JSC (either be returning from the +// callback, or by re-entering through another call to evaulate script or call +// function). +// +// This policy is slightly more restricive than it needs to be for correctness - +// we could validly allow futher entries into JSC from other threads, we only +// need ensure that callbacks return in the reverse chronological order of the +// order in which they were made - though implementing the less restrictive policy +// would likely increase complexity and overhead. +// +static unsigned lockDropDepth = 0; + JSLock::DropAllLocks::DropAllLocks(ExecState* exec) : m_lockingForReal(exec->globalData().isSharedInstance) { pthread_once(&createJSLockCountOnce, createJSLockCount); + if (lockDropDepth++) { + m_lockCount = 0; + return; + } + m_lockCount = JSLock::lockCount(); for (intptr_t i = 0; i < m_lockCount; i++) JSLock::unlock(m_lockingForReal); @@ -134,6 +181,11 @@ JSLock::DropAllLocks::DropAllLocks(bool lockingForReal) { pthread_once(&createJSLockCountOnce, createJSLockCount); + if (lockDropDepth++) { + m_lockCount = 0; + return; + } + // It is necessary to drop even "unreal" locks, because having a non-zero lock count // will prevent a real lock from being taken. @@ -146,6 +198,8 @@ JSLock::DropAllLocks::~DropAllLocks() { for (intptr_t i = 0; i < m_lockCount; i++) JSLock::lock(m_lockingForReal); + + --lockDropDepth; } #else diff --git a/JavaScriptCore/runtime/JSLock.h b/JavaScriptCore/runtime/JSLock.h index 0c22ff8..3dde358 100644 --- a/JavaScriptCore/runtime/JSLock.h +++ b/JavaScriptCore/runtime/JSLock.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2005, 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 @@ -18,8 +18,8 @@ * */ -#ifndef KJS_JSLock_h -#define KJS_JSLock_h +#ifndef JSLock_h +#define JSLock_h #include <wtf/Assertions.h> #include <wtf/Noncopyable.h> @@ -99,4 +99,4 @@ namespace JSC { } // namespace -#endif // KJS_JSLock_h +#endif // JSLock_h diff --git a/JavaScriptCore/runtime/JSNotAnObject.cpp b/JavaScriptCore/runtime/JSNotAnObject.cpp index c4ca8fd..67edfd1 100644 --- a/JavaScriptCore/runtime/JSNotAnObject.cpp +++ b/JavaScriptCore/runtime/JSNotAnObject.cpp @@ -37,45 +37,39 @@ namespace JSC { ASSERT_CLASS_FITS_IN_CELL(JSNotAnObject); // JSValue methods -JSValue* JSNotAnObject::toPrimitive(ExecState* exec, PreferredPrimitiveType) const +JSValuePtr JSNotAnObject::toPrimitive(ExecState* exec, PreferredPrimitiveType) const { - UNUSED_PARAM(exec); - ASSERT(exec->hadException() && exec->exception() == m_exception); + ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception); return m_exception; } -bool JSNotAnObject::getPrimitiveNumber(ExecState* exec, double&, JSValue*&) +bool JSNotAnObject::getPrimitiveNumber(ExecState* exec, double&, JSValuePtr&) { - UNUSED_PARAM(exec); - ASSERT(exec->hadException() && exec->exception() == m_exception); + ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception); return false; } bool JSNotAnObject::toBoolean(ExecState* exec) const { - UNUSED_PARAM(exec); - ASSERT(exec->hadException() && exec->exception() == m_exception); + ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception); return false; } double JSNotAnObject::toNumber(ExecState* exec) const { - UNUSED_PARAM(exec); - ASSERT(exec->hadException() && exec->exception() == m_exception); + ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception); return NaN; } UString JSNotAnObject::toString(ExecState* exec) const { - UNUSED_PARAM(exec); - ASSERT(exec->hadException() && exec->exception() == m_exception); + ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception); return ""; } JSObject* JSNotAnObject::toObject(ExecState* exec) const { - UNUSED_PARAM(exec); - ASSERT(exec->hadException() && exec->exception() == m_exception); + ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception); return m_exception; } @@ -90,48 +84,41 @@ void JSNotAnObject::mark() // JSObject methods bool JSNotAnObject::getOwnPropertySlot(ExecState* exec, const Identifier&, PropertySlot&) { - UNUSED_PARAM(exec); - ASSERT(exec->hadException() && exec->exception() == m_exception); + ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception); return false; } bool JSNotAnObject::getOwnPropertySlot(ExecState* exec, unsigned, PropertySlot&) { - UNUSED_PARAM(exec); - ASSERT(exec->hadException() && exec->exception() == m_exception); + ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception); return false; } -void JSNotAnObject::put(ExecState* exec, const Identifier& , JSValue*, PutPropertySlot&) +void JSNotAnObject::put(ExecState* exec, const Identifier& , JSValuePtr, PutPropertySlot&) { - UNUSED_PARAM(exec); - ASSERT(exec->hadException() && exec->exception() == m_exception); + ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception); } -void JSNotAnObject::put(ExecState* exec, unsigned, JSValue*) +void JSNotAnObject::put(ExecState* exec, unsigned, JSValuePtr) { - UNUSED_PARAM(exec); - ASSERT(exec->hadException() && exec->exception() == m_exception); + ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception); } bool JSNotAnObject::deleteProperty(ExecState* exec, const Identifier&) { - UNUSED_PARAM(exec); - ASSERT(exec->hadException() && exec->exception() == m_exception); + ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception); return false; } bool JSNotAnObject::deleteProperty(ExecState* exec, unsigned) { - UNUSED_PARAM(exec); - ASSERT(exec->hadException() && exec->exception() == m_exception); + ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception); return false; } void JSNotAnObject::getPropertyNames(ExecState* exec, PropertyNameArray&) { - UNUSED_PARAM(exec); - ASSERT(exec->hadException() && exec->exception() == m_exception); + ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception); } } // namespace JSC diff --git a/JavaScriptCore/runtime/JSNotAnObject.h b/JavaScriptCore/runtime/JSNotAnObject.h index b6e2931..c69593f 100644 --- a/JavaScriptCore/runtime/JSNotAnObject.h +++ b/JavaScriptCore/runtime/JSNotAnObject.h @@ -50,7 +50,7 @@ namespace JSC { }; // This unholy class is used to allow us to avoid multiple exception checks - // in certain SquirrelFish opcodes -- effectively it just silently consumes + // in certain SquirrelFish bytecodes -- effectively it just silently consumes // any operations performed on the result of a failed toObject call. class JSNotAnObject : public JSObject { public: @@ -60,15 +60,15 @@ namespace JSC { { } - static PassRefPtr<StructureID> createStructureID(JSValue* prototype) + static PassRefPtr<Structure> createStructure(JSValuePtr prototype) { - return StructureID::create(prototype, TypeInfo(ObjectType)); + return Structure::create(prototype, TypeInfo(ObjectType)); } private: // JSValue methods - virtual JSValue* toPrimitive(ExecState*, PreferredPrimitiveType) const; - virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue*&); + virtual JSValuePtr toPrimitive(ExecState*, PreferredPrimitiveType) const; + virtual bool getPrimitiveNumber(ExecState*, double& number, JSValuePtr&); virtual bool toBoolean(ExecState*) const; virtual double toNumber(ExecState*) const; virtual UString toString(ExecState*) const; @@ -81,8 +81,8 @@ namespace JSC { virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&); - virtual void put(ExecState*, const Identifier& propertyName, JSValue*, PutPropertySlot&); - virtual void put(ExecState*, unsigned propertyName, JSValue*); + virtual void put(ExecState*, const Identifier& propertyName, JSValuePtr, PutPropertySlot&); + virtual void put(ExecState*, unsigned propertyName, JSValuePtr); virtual bool deleteProperty(ExecState*, const Identifier& propertyName); virtual bool deleteProperty(ExecState*, unsigned propertyName); diff --git a/JavaScriptCore/runtime/JSNumberCell.cpp b/JavaScriptCore/runtime/JSNumberCell.cpp index 5b3f3bd..dd965d5 100644 --- a/JavaScriptCore/runtime/JSNumberCell.cpp +++ b/JavaScriptCore/runtime/JSNumberCell.cpp @@ -24,16 +24,18 @@ #include "JSNumberCell.h" #include "NumberObject.h" -#include "ustring.h" +#include "UString.h" namespace JSC { -JSValue* JSNumberCell::toPrimitive(ExecState*, PreferredPrimitiveType) const +#if !USE(ALTERNATE_JSIMMEDIATE) + +JSValuePtr JSNumberCell::toPrimitive(ExecState*, PreferredPrimitiveType) const { return const_cast<JSNumberCell*>(this); } -bool JSNumberCell::getPrimitiveNumber(ExecState*, double& number, JSValue*& value) +bool JSNumberCell::getPrimitiveNumber(ExecState*, double& number, JSValuePtr& value) { number = m_value; value = this; @@ -96,29 +98,29 @@ bool JSNumberCell::getTruncatedUInt32(uint32_t& uint32) const return true; } -JSValue* JSNumberCell::getJSNumber() +JSValuePtr JSNumberCell::getJSNumber() { return this; } -NEVER_INLINE JSValue* jsNumberCell(ExecState* exec, double d) +JSValuePtr jsNumberCell(ExecState* exec, double d) { return new (exec) JSNumberCell(exec, d); } -NEVER_INLINE JSValue* jsNaN(ExecState* exec) -{ - return new (exec) JSNumberCell(exec, NaN); -} - -NEVER_INLINE JSValue* jsNumberCell(JSGlobalData* globalData, double d) +JSValuePtr jsNumberCell(JSGlobalData* globalData, double d) { return new (globalData) JSNumberCell(globalData, d); } -NEVER_INLINE JSValue* jsNaN(JSGlobalData* globalData) +#else + +JSValuePtr jsNumberCell(ExecState*, double) { - return new (globalData) JSNumberCell(globalData, NaN); + ASSERT_NOT_REACHED(); + return noValue(); } +#endif + } // namespace JSC diff --git a/JavaScriptCore/runtime/JSNumberCell.h b/JavaScriptCore/runtime/JSNumberCell.h index e2f6990..d2377aa 100644 --- a/JavaScriptCore/runtime/JSNumberCell.h +++ b/JavaScriptCore/runtime/JSNumberCell.h @@ -23,15 +23,22 @@ #ifndef JSNumberCell_h #define JSNumberCell_h -#include "ExecState.h" +#include "CallFrame.h" #include "JSCell.h" #include "JSImmediate.h" -#include "collector.h" -#include "ustring.h" +#include "Collector.h" +#include "UString.h" #include <stddef.h> // for size_t namespace JSC { + extern const double NaN; + extern const double Inf; + + JSValuePtr jsNumberCell(ExecState*, double); + +#if !USE(ALTERNATE_JSIMMEDIATE) + class Identifier; class JSCell; class JSObject; @@ -42,16 +49,14 @@ namespace JSC { struct Instruction; class JSNumberCell : public JSCell { - friend class CTI; - friend JSValue* jsNumberCell(JSGlobalData*, double); - friend JSValue* jsNaN(JSGlobalData*); - friend JSValue* jsNumberCell(ExecState*, double); - friend JSValue* jsNaN(ExecState*); + friend class JIT; + friend JSValuePtr jsNumberCell(JSGlobalData*, double); + friend JSValuePtr jsNumberCell(ExecState*, double); public: double value() const { return m_value; } - virtual JSValue* toPrimitive(ExecState*, PreferredPrimitiveType) const; - virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue*& value); + virtual JSValuePtr toPrimitive(ExecState*, PreferredPrimitiveType) const; + virtual bool getPrimitiveNumber(ExecState*, double& number, JSValuePtr& value); virtual bool toBoolean(ExecState*) const; virtual double toNumber(ExecState*) const; virtual UString toString(ExecState*) const; @@ -59,10 +64,7 @@ namespace JSC { virtual UString toThisString(ExecState*) const; virtual JSObject* toThisObject(ExecState*) const; - virtual JSValue* getJSNumber(); - - int32_t toInt32() const; - uint32_t toUInt32() const; + virtual JSValuePtr getJSNumber(); void* operator new(size_t size, ExecState* exec) { @@ -82,22 +84,17 @@ namespace JSC { #endif } - static PassRefPtr<StructureID> createStructureID(JSValue* proto) { return StructureID::create(proto, TypeInfo(NumberType, NeedsThisConversion)); } - - JSNumberCell(JSGlobalData* globalData) - : JSCell(globalData->numberStructureID.get()) - { - } + static PassRefPtr<Structure> createStructure(JSValuePtr proto) { return Structure::create(proto, TypeInfo(NumberType, NeedsThisConversion)); } private: JSNumberCell(JSGlobalData* globalData, double value) - : JSCell(globalData->numberStructureID.get()) + : JSCell(globalData->numberStructure.get()) , m_value(value) { } JSNumberCell(ExecState* exec, double value) - : JSCell(exec->globalData().numberStructureID.get()) + : JSCell(exec->globalData().numberStructure.get()) , m_value(value) { } @@ -109,157 +106,342 @@ namespace JSC { double m_value; }; - extern const double NaN; - extern const double Inf; - - JSNumberCell* asNumberCell(JSValue*); + JSValuePtr jsNumberCell(JSGlobalData*, double); - JSValue* jsNumberCell(JSGlobalData*, double); - JSValue* jsNaN(JSGlobalData*); - JSValue* jsNumberCell(ExecState*, double); - JSValue* jsNaN(ExecState*); - - inline JSNumberCell* asNumberCell(JSValue* value) + inline bool isNumberCell(JSValuePtr v) { - ASSERT(asCell(value)->isNumber()); - return static_cast<JSNumberCell*>(asCell(value)); + return v.isCell() && v.asCell()->isNumber(); } - ALWAYS_INLINE JSValue* jsNumber(ExecState* exec, double d) + inline JSNumberCell* asNumberCell(JSValuePtr v) { - JSValue* v = JSImmediate::from(d); - return v ? v : jsNumberCell(exec, d); + ASSERT(isNumberCell(v)); + return static_cast<JSNumberCell*>(v.asCell()); } - ALWAYS_INLINE JSValue* jsNumber(ExecState* exec, short i) + ALWAYS_INLINE JSValuePtr jsNumber(ExecState* exec, double d) { - JSValue* v = JSImmediate::from(i); - return v ? v : jsNumberCell(exec, i); - } - - ALWAYS_INLINE JSValue* jsNumber(ExecState* exec, unsigned short i) - { - JSValue* v = JSImmediate::from(i); - return v ? v : jsNumberCell(exec, i); + JSValuePtr v = JSImmediate::from(d); + return v ? v : jsNumberCell(exec, d); } - ALWAYS_INLINE JSValue* jsNumber(ExecState* exec, int i) + ALWAYS_INLINE JSValuePtr jsNumber(ExecState* exec, int i) { - JSValue* v = JSImmediate::from(i); + JSValuePtr v = JSImmediate::from(i); return v ? v : jsNumberCell(exec, i); } - ALWAYS_INLINE JSValue* jsNumber(ExecState* exec, unsigned i) + ALWAYS_INLINE JSValuePtr jsNumber(ExecState* exec, unsigned i) { - JSValue* v = JSImmediate::from(i); + JSValuePtr v = JSImmediate::from(i); return v ? v : jsNumberCell(exec, i); } - ALWAYS_INLINE JSValue* jsNumber(ExecState* exec, long i) + ALWAYS_INLINE JSValuePtr jsNumber(ExecState* exec, long i) { - JSValue* v = JSImmediate::from(i); + JSValuePtr v = JSImmediate::from(i); return v ? v : jsNumberCell(exec, i); } - ALWAYS_INLINE JSValue* jsNumber(ExecState* exec, unsigned long i) + ALWAYS_INLINE JSValuePtr jsNumber(ExecState* exec, unsigned long i) { - JSValue* v = JSImmediate::from(i); + JSValuePtr v = JSImmediate::from(i); return v ? v : jsNumberCell(exec, i); } - ALWAYS_INLINE JSValue* jsNumber(ExecState* exec, long long i) + ALWAYS_INLINE JSValuePtr jsNumber(ExecState* exec, long long i) { - JSValue* v = JSImmediate::from(i); + JSValuePtr v = JSImmediate::from(i); return v ? v : jsNumberCell(exec, static_cast<double>(i)); } - ALWAYS_INLINE JSValue* jsNumber(ExecState* exec, unsigned long long i) + ALWAYS_INLINE JSValuePtr jsNumber(ExecState* exec, unsigned long long i) { - JSValue* v = JSImmediate::from(i); + JSValuePtr v = JSImmediate::from(i); return v ? v : jsNumberCell(exec, static_cast<double>(i)); } - ALWAYS_INLINE JSValue* jsNumber(JSGlobalData* globalData, double d) + ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData* globalData, double d) { - JSValue* v = JSImmediate::from(d); + JSValuePtr v = JSImmediate::from(d); return v ? v : jsNumberCell(globalData, d); } - ALWAYS_INLINE JSValue* jsNumber(JSGlobalData* globalData, short i) + ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData* globalData, int i) { - JSValue* v = JSImmediate::from(i); + JSValuePtr v = JSImmediate::from(i); return v ? v : jsNumberCell(globalData, i); } - ALWAYS_INLINE JSValue* jsNumber(JSGlobalData* globalData, unsigned short i) + ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData* globalData, unsigned i) { - JSValue* v = JSImmediate::from(i); + JSValuePtr v = JSImmediate::from(i); return v ? v : jsNumberCell(globalData, i); } - ALWAYS_INLINE JSValue* jsNumber(JSGlobalData* globalData, int i) + ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData* globalData, long i) { - JSValue* v = JSImmediate::from(i); + JSValuePtr v = JSImmediate::from(i); return v ? v : jsNumberCell(globalData, i); } - ALWAYS_INLINE JSValue* jsNumber(JSGlobalData* globalData, unsigned i) + ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData* globalData, unsigned long i) { - JSValue* v = JSImmediate::from(i); + JSValuePtr v = JSImmediate::from(i); return v ? v : jsNumberCell(globalData, i); } - ALWAYS_INLINE JSValue* jsNumber(JSGlobalData* globalData, long i) + ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData* globalData, long long i) { - JSValue* v = JSImmediate::from(i); - return v ? v : jsNumberCell(globalData, i); + JSValuePtr v = JSImmediate::from(i); + return v ? v : jsNumberCell(globalData, static_cast<double>(i)); } - ALWAYS_INLINE JSValue* jsNumber(JSGlobalData* globalData, unsigned long i) + ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData* globalData, unsigned long long i) { - JSValue* v = JSImmediate::from(i); - return v ? v : jsNumberCell(globalData, i); + JSValuePtr v = JSImmediate::from(i); + return v ? v : jsNumberCell(globalData, static_cast<double>(i)); } - ALWAYS_INLINE JSValue* jsNumber(JSGlobalData* globalData, long long i) + inline bool JSValuePtr::isDoubleNumber() const { - JSValue* v = JSImmediate::from(i); - return v ? v : jsNumberCell(globalData, static_cast<double>(i)); + return isNumberCell(asValue()); } - ALWAYS_INLINE JSValue* jsNumber(JSGlobalData* globalData, unsigned long long i) + inline double JSValuePtr::getDoubleNumber() const { - JSValue* v = JSImmediate::from(i); - return v ? v : jsNumberCell(globalData, static_cast<double>(i)); + return asNumberCell(asValue())->value(); + } + + inline bool JSValuePtr::isNumber() const + { + return JSImmediate::isNumber(asValue()) || isDoubleNumber(); + } + + inline double JSValuePtr::uncheckedGetNumber() const + { + ASSERT(isNumber()); + return JSImmediate::isImmediate(asValue()) ? JSImmediate::toDouble(asValue()) : getDoubleNumber(); + } + +#else + + ALWAYS_INLINE JSValuePtr jsNumber(ExecState*, double d) + { + JSValuePtr v = JSImmediate::from(d); + ASSERT(v); + return v; + } + + ALWAYS_INLINE JSValuePtr jsNumber(ExecState*, int i) + { + JSValuePtr v = JSImmediate::from(i); + ASSERT(v); + return v; + } + + ALWAYS_INLINE JSValuePtr jsNumber(ExecState*, unsigned i) + { + JSValuePtr v = JSImmediate::from(i); + ASSERT(v); + return v; + } + + ALWAYS_INLINE JSValuePtr jsNumber(ExecState*, long i) + { + JSValuePtr v = JSImmediate::from(i); + ASSERT(v); + return v; + } + + ALWAYS_INLINE JSValuePtr jsNumber(ExecState*, unsigned long i) + { + JSValuePtr v = JSImmediate::from(i); + ASSERT(v); + return v; + } + + ALWAYS_INLINE JSValuePtr jsNumber(ExecState*, long long i) + { + JSValuePtr v = JSImmediate::from(static_cast<double>(i)); + ASSERT(v); + return v; + } + + ALWAYS_INLINE JSValuePtr jsNumber(ExecState*, unsigned long long i) + { + JSValuePtr v = JSImmediate::from(static_cast<double>(i)); + ASSERT(v); + return v; + } + + ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData*, double d) + { + JSValuePtr v = JSImmediate::from(d); + ASSERT(v); + return v; + } + + ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData*, int i) + { + JSValuePtr v = JSImmediate::from(i); + ASSERT(v); + return v; + } + + ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData*, unsigned i) + { + JSValuePtr v = JSImmediate::from(i); + ASSERT(v); + return v; + } + + ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData*, long i) + { + JSValuePtr v = JSImmediate::from(i); + ASSERT(v); + return v; + } + + ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData*, unsigned long i) + { + JSValuePtr v = JSImmediate::from(i); + ASSERT(v); + return v; + } + + ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData*, long long i) + { + JSValuePtr v = JSImmediate::from(static_cast<double>(i)); + ASSERT(v); + return v; + } + + ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData*, unsigned long long i) + { + JSValuePtr v = JSImmediate::from(static_cast<double>(i)); + ASSERT(v); + return v; + } + + inline bool JSValuePtr::isDoubleNumber() const + { + return JSImmediate::isDoubleNumber(asValue()); + } + + inline double JSValuePtr::getDoubleNumber() const + { + return JSImmediate::doubleValue(asValue()); + } + + inline bool JSValuePtr::isNumber() const + { + return JSImmediate::isNumber(asValue()); + } + + inline double JSValuePtr::uncheckedGetNumber() const + { + ASSERT(isNumber()); + return JSImmediate::toDouble(asValue()); + } + +#endif + + ALWAYS_INLINE JSValuePtr jsNumber(ExecState*, char i) + { + ASSERT(JSImmediate::from(i)); + return JSImmediate::from(i); + } + + ALWAYS_INLINE JSValuePtr jsNumber(ExecState*, unsigned char i) + { + ASSERT(JSImmediate::from(i)); + return JSImmediate::from(i); + } + + ALWAYS_INLINE JSValuePtr jsNumber(ExecState*, short i) + { + ASSERT(JSImmediate::from(i)); + return JSImmediate::from(i); + } + + ALWAYS_INLINE JSValuePtr jsNumber(ExecState*, unsigned short i) + { + ASSERT(JSImmediate::from(i)); + return JSImmediate::from(i); + } + + ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData*, short i) + { + ASSERT(JSImmediate::from(i)); + return JSImmediate::from(i); + } + + ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData*, unsigned short i) + { + ASSERT(JSImmediate::from(i)); + return JSImmediate::from(i); + } + + inline JSValuePtr jsNaN(ExecState* exec) + { + return jsNumber(exec, NaN); + } + + inline JSValuePtr jsNaN(JSGlobalData* globalData) + { + return jsNumber(globalData, NaN); } // --- JSValue inlines ---------------------------- - inline double JSValue::uncheckedGetNumber() const + ALWAYS_INLINE JSValuePtr JSValuePtr::toJSNumber(ExecState* exec) const { - ASSERT(JSImmediate::isImmediate(asValue()) || asCell()->isNumber()); - return JSImmediate::isImmediate(asValue()) ? JSImmediate::toDouble(asValue()) : asNumberCell(asValue())->value(); + return isNumber() ? asValue() : jsNumber(exec, this->toNumber(exec)); } - inline int32_t JSNumberCell::toInt32() const + inline bool JSValuePtr::getNumber(double &result) const { - if (m_value >= -2147483648.0 && m_value < 2147483648.0) - return static_cast<int32_t>(m_value); - bool scratch; - return JSC::toInt32SlowCase(m_value, scratch); + if (isInt32Fast()) + result = getInt32Fast(); + else if (LIKELY(isDoubleNumber())) + result = getDoubleNumber(); + else { + ASSERT(!isNumber()); + return false; + } + return true; } - inline uint32_t JSNumberCell::toUInt32() const + inline bool JSValuePtr::numberToInt32(int32_t& arg) { - if (m_value >= 0.0 && m_value < 4294967296.0) - return static_cast<uint32_t>(m_value); - bool scratch; - return JSC::toUInt32SlowCase(m_value, scratch); + if (isInt32Fast()) + arg = getInt32Fast(); + else if (LIKELY(isDoubleNumber())) + arg = JSC::toInt32(getDoubleNumber()); + else { + ASSERT(!isNumber()); + return false; + } + return true; } - ALWAYS_INLINE JSValue* JSValue::toJSNumber(ExecState* exec) const + inline bool JSValuePtr::numberToUInt32(uint32_t& arg) { - return JSImmediate::isNumber(asValue()) ? asValue() : jsNumber(exec, this->toNumber(exec)); + if (isUInt32Fast()) + arg = getUInt32Fast(); + else if (LIKELY(isDoubleNumber())) + arg = JSC::toUInt32(getDoubleNumber()); + else if (isInt32Fast()) { + // FIXME: I think this case can be merged with the uint case; toUInt32SlowCase + // on a negative value is equivalent to simple static_casting. + bool ignored; + arg = toUInt32SlowCase(getInt32Fast(), ignored); + } else { + ASSERT(!isNumber()); + return false; + } + return true; } } // namespace JSC diff --git a/JavaScriptCore/runtime/JSObject.cpp b/JavaScriptCore/runtime/JSObject.cpp index 82c1c63..e9e95f6 100644 --- a/JavaScriptCore/runtime/JSObject.cpp +++ b/JavaScriptCore/runtime/JSObject.cpp @@ -31,9 +31,9 @@ #include "NativeErrorConstructor.h" #include "ObjectPrototype.h" #include "PropertyNameArray.h" -#include "lookup.h" -#include "nodes.h" -#include "operations.h" +#include "Lookup.h" +#include "Nodes.h" +#include "Operations.h" #include <math.h> #include <wtf/Assertions.h> @@ -67,13 +67,13 @@ void JSObject::mark() JSOBJECT_MARK_BEGIN(); JSCell::mark(); - m_structureID->mark(); + m_structure->mark(); - size_t storageSize = m_structureID->propertyStorageSize(); + size_t storageSize = m_structure->propertyStorageSize(); for (size_t i = 0; i < storageSize; ++i) { - JSValue* v = m_propertyStorage[i]; - if (!v->marked()) - v->mark(); + JSValuePtr v = m_propertyStorage[i]; + if (!v.marked()) + v.mark(); } JSOBJECT_MARK_END(); @@ -98,47 +98,47 @@ static void throwSetterError(ExecState* exec) } // ECMA 8.6.2.2 -void JSObject::put(ExecState* exec, const Identifier& propertyName, JSValue* value, PutPropertySlot& slot) +void JSObject::put(ExecState* exec, const Identifier& propertyName, JSValuePtr value, PutPropertySlot& slot) { ASSERT(value); ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this)); if (propertyName == exec->propertyNames().underscoreProto) { - JSObject* proto = value->getObject(); - // Setting __proto__ to a non-object, non-null value is silently ignored to match Mozilla. - if (!proto && !value->isNull()) + if (!value.isObject() && !value.isNull()) return; - - while (proto) { - if (proto == this) { + + JSValuePtr nextPrototypeValue = value; + while (nextPrototypeValue && nextPrototypeValue.isObject()) { + JSObject* nextPrototype = asObject(nextPrototypeValue)->unwrappedObject(); + if (nextPrototype == this) { throwError(exec, GeneralError, "cyclic __proto__ value"); return; } - proto = proto->prototype() ? proto->prototype()->getObject() : 0; + nextPrototypeValue = nextPrototype->prototype(); } - + setPrototype(value); return; } - + // Check if there are any setters or getters in the prototype chain - JSValue* prototype; - for (JSObject* obj = this; !obj->structureID()->hasGetterSetterProperties(); obj = asObject(prototype)) { + JSValuePtr prototype; + for (JSObject* obj = this; !obj->structure()->hasGetterSetterProperties(); obj = asObject(prototype)) { prototype = obj->prototype(); - if (prototype->isNull()) { + if (prototype.isNull()) { putDirect(propertyName, value, 0, true, slot); return; } } unsigned attributes; - if ((m_structureID->get(propertyName, attributes) != WTF::notFound) && attributes & ReadOnly) + if ((m_structure->get(propertyName, attributes) != WTF::notFound) && attributes & ReadOnly) return; for (JSObject* obj = this; ; obj = asObject(prototype)) { - if (JSValue* gs = obj->getDirect(propertyName)) { - if (gs->isGetterSetter()) { + if (JSValuePtr gs = obj->getDirect(propertyName)) { + if (gs.isGetterSetter()) { JSObject* setterFunc = asGetterSetter(gs)->setter(); if (!setterFunc) { throwSetterError(exec); @@ -159,7 +159,7 @@ void JSObject::put(ExecState* exec, const Identifier& propertyName, JSValue* val } prototype = obj->prototype(); - if (prototype->isNull()) + if (prototype.isNull()) break; } @@ -167,18 +167,18 @@ void JSObject::put(ExecState* exec, const Identifier& propertyName, JSValue* val return; } -void JSObject::put(ExecState* exec, unsigned propertyName, JSValue* value) +void JSObject::put(ExecState* exec, unsigned propertyName, JSValuePtr value) { PutPropertySlot slot; put(exec, Identifier::from(exec, propertyName), value, slot); } -void JSObject::putWithAttributes(ExecState*, const Identifier& propertyName, JSValue* value, unsigned attributes) +void JSObject::putWithAttributes(ExecState*, const Identifier& propertyName, JSValuePtr value, unsigned attributes) { putDirect(propertyName, value, attributes); } -void JSObject::putWithAttributes(ExecState* exec, unsigned propertyName, JSValue* value, unsigned attributes) +void JSObject::putWithAttributes(ExecState* exec, unsigned propertyName, JSValuePtr value, unsigned attributes) { putWithAttributes(exec, Identifier::from(exec, propertyName), value, attributes); } @@ -199,7 +199,7 @@ bool JSObject::hasProperty(ExecState* exec, unsigned propertyName) const bool JSObject::deleteProperty(ExecState* exec, const Identifier& propertyName) { unsigned attributes; - if (m_structureID->get(propertyName, attributes) != WTF::notFound) { + if (m_structure->get(propertyName, attributes) != WTF::notFound) { if ((attributes & DontDelete)) return false; removeDirect(propertyName); @@ -226,11 +226,11 @@ bool JSObject::deleteProperty(ExecState* exec, unsigned propertyName) return deleteProperty(exec, Identifier::from(exec, propertyName)); } -static ALWAYS_INLINE JSValue* callDefaultValueFunction(ExecState* exec, const JSObject* object, const Identifier& propertyName) +static ALWAYS_INLINE JSValuePtr callDefaultValueFunction(ExecState* exec, const JSObject* object, const Identifier& propertyName) { - JSValue* function = object->get(exec, propertyName); + JSValuePtr function = object->get(exec, propertyName); CallData callData; - CallType callType = function->getCallData(callData); + CallType callType = function.getCallData(callData); if (callType == CallTypeNone) return exec->exception(); @@ -239,35 +239,39 @@ static ALWAYS_INLINE JSValue* callDefaultValueFunction(ExecState* exec, const JS if (exec->hadException()) return exec->exception(); - JSValue* result = call(exec, function, callType, callData, const_cast<JSObject*>(object), exec->emptyList()); - ASSERT(!result->isGetterSetter()); + JSValuePtr result = call(exec, function, callType, callData, const_cast<JSObject*>(object), exec->emptyList()); + ASSERT(!result.isGetterSetter()); if (exec->hadException()) return exec->exception(); - if (result->isObject()) + if (result.isObject()) return noValue(); return result; } -bool JSObject::getPrimitiveNumber(ExecState* exec, double& number, JSValue*& result) +bool JSObject::getPrimitiveNumber(ExecState* exec, double& number, JSValuePtr& result) { result = defaultValue(exec, PreferNumber); - number = result->toNumber(exec); - return !result->isString(); + number = result.toNumber(exec); + return !result.isString(); } // ECMA 8.6.2.6 -JSValue* JSObject::defaultValue(ExecState* exec, PreferredPrimitiveType hint) const +JSValuePtr JSObject::defaultValue(ExecState* exec, PreferredPrimitiveType hint) const { // Must call toString first for Date objects. if ((hint == PreferString) || (hint != PreferNumber && prototype() == exec->lexicalGlobalObject()->datePrototype())) { - if (JSValue* value = callDefaultValueFunction(exec, this, exec->propertyNames().toString)) + JSValuePtr value = callDefaultValueFunction(exec, this, exec->propertyNames().toString); + if (value) return value; - if (JSValue* value = callDefaultValueFunction(exec, this, exec->propertyNames().valueOf)) + value = callDefaultValueFunction(exec, this, exec->propertyNames().valueOf); + if (value) return value; } else { - if (JSValue* value = callDefaultValueFunction(exec, this, exec->propertyNames().valueOf)) + JSValuePtr value = callDefaultValueFunction(exec, this, exec->propertyNames().valueOf); + if (value) return value; - if (JSValue* value = callDefaultValueFunction(exec, this, exec->propertyNames().toString)) + value = callDefaultValueFunction(exec, this, exec->propertyNames().toString); + if (value) return value; } @@ -289,9 +293,9 @@ const HashEntry* JSObject::findPropertyHashEntry(ExecState* exec, const Identifi void JSObject::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunction) { - JSValue* object = getDirect(propertyName); - if (object && object->isGetterSetter()) { - ASSERT(m_structureID->hasGetterSetterProperties()); + JSValuePtr object = getDirect(propertyName); + if (object && object.isGetterSetter()) { + ASSERT(m_structure->hasGetterSetterProperties()); asGetterSetter(object)->setGetter(getterFunction); return; } @@ -300,25 +304,25 @@ void JSObject::defineGetter(ExecState* exec, const Identifier& propertyName, JSO GetterSetter* getterSetter = new (exec) GetterSetter; putDirect(propertyName, getterSetter, None, true, slot); - // putDirect will change our StructureID if we add a new property. For - // getters and setters, though, we also need to change our StructureID + // putDirect will change our Structure if we add a new property. For + // getters and setters, though, we also need to change our Structure // if we override an existing non-getter or non-setter. if (slot.type() != PutPropertySlot::NewProperty) { - if (!m_structureID->isDictionary()) { - RefPtr<StructureID> structureID = StructureID::getterSetterTransition(m_structureID); - setStructureID(structureID.release()); + if (!m_structure->isDictionary()) { + RefPtr<Structure> structure = Structure::getterSetterTransition(m_structure); + setStructure(structure.release()); } } - m_structureID->setHasGetterSetterProperties(true); + m_structure->setHasGetterSetterProperties(true); getterSetter->setGetter(getterFunction); } void JSObject::defineSetter(ExecState* exec, const Identifier& propertyName, JSObject* setterFunction) { - JSValue* object = getDirect(propertyName); - if (object && object->isGetterSetter()) { - ASSERT(m_structureID->hasGetterSetterProperties()); + JSValuePtr object = getDirect(propertyName); + if (object && object.isGetterSetter()) { + ASSERT(m_structure->hasGetterSetterProperties()); asGetterSetter(object)->setSetter(setterFunction); return; } @@ -327,27 +331,26 @@ void JSObject::defineSetter(ExecState* exec, const Identifier& propertyName, JSO GetterSetter* getterSetter = new (exec) GetterSetter; putDirect(propertyName, getterSetter, None, true, slot); - // putDirect will change our StructureID if we add a new property. For - // getters and setters, though, we also need to change our StructureID + // putDirect will change our Structure if we add a new property. For + // getters and setters, though, we also need to change our Structure // if we override an existing non-getter or non-setter. if (slot.type() != PutPropertySlot::NewProperty) { - if (!m_structureID->isDictionary()) { - RefPtr<StructureID> structureID = StructureID::getterSetterTransition(m_structureID); - setStructureID(structureID.release()); + if (!m_structure->isDictionary()) { + RefPtr<Structure> structure = Structure::getterSetterTransition(m_structure); + setStructure(structure.release()); } } - m_structureID->setHasGetterSetterProperties(true); + m_structure->setHasGetterSetterProperties(true); getterSetter->setSetter(setterFunction); } -JSValue* JSObject::lookupGetter(ExecState*, const Identifier& propertyName) +JSValuePtr JSObject::lookupGetter(ExecState*, const Identifier& propertyName) { JSObject* object = this; while (true) { - JSValue* value = object->getDirect(propertyName); - if (value) { - if (!value->isGetterSetter()) + if (JSValuePtr value = object->getDirect(propertyName)) { + if (!value.isGetterSetter()) return jsUndefined(); JSObject* functionObject = asGetterSetter(value)->getter(); if (!functionObject) @@ -355,19 +358,18 @@ JSValue* JSObject::lookupGetter(ExecState*, const Identifier& propertyName) return functionObject; } - if (!object->prototype() || !object->prototype()->isObject()) + if (!object->prototype() || !object->prototype().isObject()) return jsUndefined(); object = asObject(object->prototype()); } } -JSValue* JSObject::lookupSetter(ExecState*, const Identifier& propertyName) +JSValuePtr JSObject::lookupSetter(ExecState*, const Identifier& propertyName) { JSObject* object = this; while (true) { - JSValue* value = object->getDirect(propertyName); - if (value) { - if (!value->isGetterSetter()) + if (JSValuePtr value = object->getDirect(propertyName)) { + if (!value.isGetterSetter()) return jsUndefined(); JSObject* functionObject = asGetterSetter(value)->setter(); if (!functionObject) @@ -375,25 +377,25 @@ JSValue* JSObject::lookupSetter(ExecState*, const Identifier& propertyName) return functionObject; } - if (!object->prototype() || !object->prototype()->isObject()) + if (!object->prototype() || !object->prototype().isObject()) return jsUndefined(); object = asObject(object->prototype()); } } -bool JSObject::hasInstance(ExecState* exec, JSValue* value, JSValue* proto) +bool JSObject::hasInstance(ExecState* exec, JSValuePtr value, JSValuePtr proto) { - if (!proto->isObject()) { + if (!proto.isObject()) { throwError(exec, TypeError, "instanceof called on an object with an invalid prototype property."); return false; } - if (!value->isObject()) + if (!value.isObject()) return false; JSObject* object = asObject(value); - while ((object = object->prototype()->getObject())) { - if (object == proto) + while ((object = object->prototype().getObject())) { + if (proto == object) return true; } return false; @@ -409,7 +411,7 @@ bool JSObject::propertyIsEnumerable(ExecState* exec, const Identifier& propertyN bool JSObject::getPropertyAttributes(ExecState* exec, const Identifier& propertyName, unsigned& attributes) const { - if (m_structureID->get(propertyName, attributes) != WTF::notFound) + if (m_structure->get(propertyName, attributes) != WTF::notFound) return true; // Look in the static hashtable of properties @@ -424,7 +426,7 @@ bool JSObject::getPropertyAttributes(ExecState* exec, const Identifier& property void JSObject::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames) { - m_structureID->getEnumerablePropertyNames(exec, propertyNames, this); + m_structure->getEnumerablePropertyNames(exec, propertyNames, this); } bool JSObject::toBoolean(ExecState*) const @@ -434,18 +436,18 @@ bool JSObject::toBoolean(ExecState*) const double JSObject::toNumber(ExecState* exec) const { - JSValue* primitive = toPrimitive(exec, PreferNumber); - if (exec->hadException()) // should be picked up soon in nodes.cpp + JSValuePtr primitive = toPrimitive(exec, PreferNumber); + if (exec->hadException()) // should be picked up soon in Nodes.cpp return 0.0; - return primitive->toNumber(exec); + return primitive.toNumber(exec); } UString JSObject::toString(ExecState* exec) const { - JSValue* primitive = toPrimitive(exec, PreferString); + JSValuePtr primitive = toPrimitive(exec, PreferString); if (exec->hadException()) return ""; - return primitive->toString(exec); + return primitive.toString(exec); } JSObject* JSObject::toObject(ExecState*) const @@ -458,25 +460,25 @@ JSObject* JSObject::toThisObject(ExecState*) const return const_cast<JSObject*>(this); } -JSGlobalObject* JSObject::toGlobalObject(ExecState*) const +JSObject* JSObject::unwrappedObject() { - return 0; + return this; } void JSObject::removeDirect(const Identifier& propertyName) { size_t offset; - if (m_structureID->isDictionary()) { - offset = m_structureID->removePropertyWithoutTransition(propertyName); + if (m_structure->isDictionary()) { + offset = m_structure->removePropertyWithoutTransition(propertyName); if (offset != WTF::notFound) m_propertyStorage[offset] = jsUndefined(); return; } - RefPtr<StructureID> structureID = StructureID::removePropertyTransition(m_structureID, propertyName, offset); + RefPtr<Structure> structure = Structure::removePropertyTransition(m_structure, propertyName, offset); if (offset != WTF::notFound) m_propertyStorage[offset] = jsUndefined(); - setStructureID(structureID.release()); + setStructure(structure.release()); } void JSObject::putDirectFunction(ExecState* exec, InternalFunction* function, unsigned attr) @@ -489,7 +491,7 @@ void JSObject::putDirectFunctionWithoutTransition(ExecState* exec, InternalFunct putDirectWithoutTransition(Identifier(exec, function->name(&exec->globalData())), function, attr); } -NEVER_INLINE void JSObject::fillGetterPropertySlot(PropertySlot& slot, JSValue** location) +NEVER_INLINE void JSObject::fillGetterPropertySlot(PropertySlot& slot, JSValuePtr* location) { if (JSObject* getterFunction = asGetterSetter(*location)->getter()) slot.setGetterSlot(getterFunction); @@ -497,9 +499,9 @@ NEVER_INLINE void JSObject::fillGetterPropertySlot(PropertySlot& slot, JSValue** slot.setUndefined(); } -StructureID* JSObject::createInheritorID() +Structure* JSObject::createInheritorID() { - m_inheritorID = JSObject::createStructureID(this); + m_inheritorID = JSObject::createStructure(this); return m_inheritorID.get(); } diff --git a/JavaScriptCore/runtime/JSObject.h b/JavaScriptCore/runtime/JSObject.h index d280b64..20242ce 100644 --- a/JavaScriptCore/runtime/JSObject.h +++ b/JavaScriptCore/runtime/JSObject.h @@ -26,18 +26,18 @@ #include "ArgList.h" #include "ClassInfo.h" #include "CommonIdentifiers.h" -#include "ExecState.h" +#include "CallFrame.h" #include "JSNumberCell.h" #include "PropertySlot.h" #include "PutPropertySlot.h" #include "ScopeChain.h" -#include "StructureID.h" +#include "Structure.h" namespace JSC { class InternalFunction; class PropertyNameArray; - class StructureID; + class Structure; struct HashEntry; struct HashTable; @@ -51,15 +51,15 @@ namespace JSC { Function = 1 << 4, // property is a function - only used by static hashtables }; - typedef JSValue** PropertyStorage; + typedef JSValuePtr* PropertyStorage; class JSObject : public JSCell { friend class BatchedTransitionOptimizer; - friend class CTI; + friend class JIT; friend class JSCell; public: - explicit JSObject(PassRefPtr<StructureID>); + explicit JSObject(PassRefPtr<Structure>); virtual void mark(); @@ -69,18 +69,18 @@ namespace JSC { bool inherits(const ClassInfo* classInfo) const { return JSCell::isObject(classInfo); } - JSValue* prototype() const; - void setPrototype(JSValue* prototype); + JSValuePtr prototype() const; + void setPrototype(JSValuePtr prototype); - void setStructureID(PassRefPtr<StructureID>); - StructureID* inheritorID(); + void setStructure(PassRefPtr<Structure>); + Structure* inheritorID(); PropertyStorage& propertyStorage() { return m_propertyStorage; } virtual UString className() const; - JSValue* get(ExecState*, const Identifier& propertyName) const; - JSValue* get(ExecState*, unsigned propertyName) const; + JSValuePtr get(ExecState*, const Identifier& propertyName) const; + JSValuePtr get(ExecState*, unsigned propertyName) const; bool getPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); bool getPropertySlot(ExecState*, unsigned propertyName, PropertySlot&); @@ -88,11 +88,11 @@ namespace JSC { virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&); - virtual void put(ExecState*, const Identifier& propertyName, JSValue* value, PutPropertySlot&); - virtual void put(ExecState*, unsigned propertyName, JSValue* value); + virtual void put(ExecState*, const Identifier& propertyName, JSValuePtr value, PutPropertySlot&); + virtual void put(ExecState*, unsigned propertyName, JSValuePtr value); - virtual void putWithAttributes(ExecState*, const Identifier& propertyName, JSValue* value, unsigned attributes); - virtual void putWithAttributes(ExecState*, unsigned propertyName, JSValue* value, unsigned attributes); + virtual void putWithAttributes(ExecState*, const Identifier& propertyName, JSValuePtr value, unsigned attributes); + virtual void putWithAttributes(ExecState*, unsigned propertyName, JSValuePtr value, unsigned attributes); bool propertyIsEnumerable(ExecState*, const Identifier& propertyName) const; @@ -103,78 +103,79 @@ namespace JSC { virtual bool deleteProperty(ExecState*, const Identifier& propertyName); virtual bool deleteProperty(ExecState*, unsigned propertyName); - virtual JSValue* defaultValue(ExecState*, PreferredPrimitiveType) const; + virtual JSValuePtr defaultValue(ExecState*, PreferredPrimitiveType) const; - virtual bool hasInstance(ExecState*, JSValue*, JSValue* prototypeProperty); + virtual bool hasInstance(ExecState*, JSValuePtr, JSValuePtr prototypeProperty); virtual void getPropertyNames(ExecState*, PropertyNameArray&); - virtual JSValue* toPrimitive(ExecState*, PreferredPrimitiveType = NoPreference) const; - virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue*& value); + virtual JSValuePtr toPrimitive(ExecState*, PreferredPrimitiveType = NoPreference) const; + virtual bool getPrimitiveNumber(ExecState*, double& number, JSValuePtr& value); virtual bool toBoolean(ExecState*) const; virtual double toNumber(ExecState*) const; virtual UString toString(ExecState*) const; virtual JSObject* toObject(ExecState*) const; virtual JSObject* toThisObject(ExecState*) const; - virtual JSGlobalObject* toGlobalObject(ExecState*) const; + virtual JSObject* unwrappedObject(); virtual bool getPropertyAttributes(ExecState*, const Identifier& propertyName, unsigned& attributes) const; // This get function only looks at the property map. - JSValue* getDirect(const Identifier& propertyName) const + JSValuePtr getDirect(const Identifier& propertyName) const { - size_t offset = m_structureID->get(propertyName); + size_t offset = m_structure->get(propertyName); return offset != WTF::notFound ? m_propertyStorage[offset] : noValue(); } - JSValue** getDirectLocation(const Identifier& propertyName) + JSValuePtr* getDirectLocation(const Identifier& propertyName) { - size_t offset = m_structureID->get(propertyName); + size_t offset = m_structure->get(propertyName); return offset != WTF::notFound ? locationForOffset(offset) : 0; } - JSValue** getDirectLocation(const Identifier& propertyName, unsigned& attributes) + JSValuePtr* getDirectLocation(const Identifier& propertyName, unsigned& attributes) { - size_t offset = m_structureID->get(propertyName, attributes); + size_t offset = m_structure->get(propertyName, attributes); return offset != WTF::notFound ? locationForOffset(offset) : 0; } - size_t offsetForLocation(JSValue** location) + size_t offsetForLocation(JSValuePtr* location) { return location - m_propertyStorage; } - JSValue** locationForOffset(size_t offset) + JSValuePtr* locationForOffset(size_t offset) { return &m_propertyStorage[offset]; } - void transitionTo(StructureID*); + void transitionTo(Structure*); void removeDirect(const Identifier& propertyName); - bool hasCustomProperties() { return !m_structureID->isEmpty(); } - bool hasGetterSetterProperties() { return m_structureID->hasGetterSetterProperties(); } + bool hasCustomProperties() { return !m_structure->isEmpty(); } + bool hasGetterSetterProperties() { return m_structure->hasGetterSetterProperties(); } - void putDirect(const Identifier& propertyName, JSValue* value, unsigned attr = 0); - void putDirect(const Identifier& propertyName, JSValue* value, unsigned attr, bool checkReadOnly, PutPropertySlot& slot); + void putDirect(const Identifier& propertyName, JSValuePtr value, unsigned attr = 0); + void putDirect(const Identifier& propertyName, JSValuePtr value, unsigned attr, bool checkReadOnly, PutPropertySlot& slot); void putDirectFunction(ExecState* exec, InternalFunction* function, unsigned attr = 0); - void putDirectWithoutTransition(const Identifier& propertyName, JSValue* value, unsigned attr = 0); + void putDirectWithoutTransition(const Identifier& propertyName, JSValuePtr value, unsigned attr = 0); void putDirectFunctionWithoutTransition(ExecState* exec, InternalFunction* function, unsigned attr = 0); // Fast access to known property offsets. - JSValue* getDirectOffset(size_t offset) { return m_propertyStorage[offset]; } - void putDirectOffset(size_t offset, JSValue* value) { m_propertyStorage[offset] = value; } + JSValuePtr getDirectOffset(size_t offset) { return m_propertyStorage[offset]; } + void putDirectOffset(size_t offset, JSValuePtr value) { m_propertyStorage[offset] = value; } - void fillGetterPropertySlot(PropertySlot&, JSValue** location); + void fillGetterPropertySlot(PropertySlot&, JSValuePtr* location); virtual void defineGetter(ExecState*, const Identifier& propertyName, JSObject* getterFunction); virtual void defineSetter(ExecState*, const Identifier& propertyName, JSObject* setterFunction); - virtual JSValue* lookupGetter(ExecState*, const Identifier& propertyName); - virtual JSValue* lookupSetter(ExecState*, const Identifier& propertyName); + virtual JSValuePtr lookupGetter(ExecState*, const Identifier& propertyName); + virtual JSValuePtr lookupSetter(ExecState*, const Identifier& propertyName); virtual bool isGlobalObject() const { return false; } virtual bool isVariableObject() const { return false; } + virtual bool isActivationObject() const { return false; } virtual bool isWatchdogException() const { return false; } virtual bool isNotAnObjectErrorStub() const { return false; } @@ -185,9 +186,9 @@ namespace JSC { static const size_t inlineStorageCapacity = 2; static const size_t nonInlineBaseStorageCapacity = 16; - static PassRefPtr<StructureID> createStructureID(JSValue* prototype) + static PassRefPtr<Structure> createStructure(JSValuePtr prototype) { - return StructureID::create(prototype, TypeInfo(ObjectType, HasStandardGetOwnPropertySlot)); + return Structure::create(prototype, TypeInfo(ObjectType, HasStandardGetOwnPropertySlot)); } protected: @@ -197,61 +198,61 @@ namespace JSC { bool inlineGetOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); const HashEntry* findPropertyHashEntry(ExecState*, const Identifier& propertyName) const; - StructureID* createInheritorID(); + Structure* createInheritorID(); - RefPtr<StructureID> m_inheritorID; + RefPtr<Structure> m_inheritorID; PropertyStorage m_propertyStorage; - JSValue* m_inlineStorage[inlineStorageCapacity]; + JSValuePtr m_inlineStorage[inlineStorageCapacity]; }; - JSObject* asObject(JSValue*); + JSObject* asObject(JSValuePtr); JSObject* constructEmptyObject(ExecState*); -inline JSObject* asObject(JSValue* value) +inline JSObject* asObject(JSValuePtr value) { ASSERT(asCell(value)->isObject()); return static_cast<JSObject*>(asCell(value)); } -inline JSObject::JSObject(PassRefPtr<StructureID> structureID) - : JSCell(structureID.releaseRef()) // ~JSObject balances this ref() +inline JSObject::JSObject(PassRefPtr<Structure> structure) + : JSCell(structure.releaseRef()) // ~JSObject balances this ref() , m_propertyStorage(m_inlineStorage) { - ASSERT(m_structureID); - ASSERT(m_structureID->propertyStorageCapacity() == inlineStorageCapacity); - ASSERT(m_structureID->isEmpty()); - ASSERT(prototype()->isNull() || Heap::heap(this) == Heap::heap(prototype())); + ASSERT(m_structure); + ASSERT(m_structure->propertyStorageCapacity() == inlineStorageCapacity); + ASSERT(m_structure->isEmpty()); + ASSERT(prototype().isNull() || Heap::heap(this) == Heap::heap(prototype())); } inline JSObject::~JSObject() { - ASSERT(m_structureID); + ASSERT(m_structure); if (m_propertyStorage != m_inlineStorage) delete [] m_propertyStorage; - m_structureID->deref(); + m_structure->deref(); } -inline JSValue* JSObject::prototype() const +inline JSValuePtr JSObject::prototype() const { - return m_structureID->storedPrototype(); + return m_structure->storedPrototype(); } -inline void JSObject::setPrototype(JSValue* prototype) +inline void JSObject::setPrototype(JSValuePtr prototype) { ASSERT(prototype); - RefPtr<StructureID> newStructureID = StructureID::changePrototypeTransition(m_structureID, prototype); - setStructureID(newStructureID.release()); + RefPtr<Structure> newStructure = Structure::changePrototypeTransition(m_structure, prototype); + setStructure(newStructure.release()); } -inline void JSObject::setStructureID(PassRefPtr<StructureID> structureID) +inline void JSObject::setStructure(PassRefPtr<Structure> structure) { - m_structureID->deref(); - m_structureID = structureID.releaseRef(); // ~JSObject balances this ref() + m_structure->deref(); + m_structure = structure.releaseRef(); // ~JSObject balances this ref() } -inline StructureID* JSObject::inheritorID() +inline Structure* JSObject::inheritorID() { if (m_inheritorID) return m_inheritorID.get(); @@ -268,15 +269,15 @@ inline bool JSCell::isObject(const ClassInfo* info) const } // this method is here to be after the inline declaration of JSCell::isObject -inline bool JSValue::isObject(const ClassInfo* classInfo) const +inline bool JSValuePtr::isObject(const ClassInfo* classInfo) const { - return !JSImmediate::isImmediate(asValue()) && asCell()->isObject(classInfo); + return isCell() && asCell()->isObject(classInfo); } ALWAYS_INLINE bool JSObject::inlineGetOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) { - if (JSValue** location = getDirectLocation(propertyName)) { - if (m_structureID->hasGetterSetterProperties() && location[0]->isGetterSetter()) + if (JSValuePtr* location = getDirectLocation(propertyName)) { + if (m_structure->hasGetterSetterProperties() && location[0].isGetterSetter()) fillGetterPropertySlot(slot, location); else slot.setValueSlot(this, location, offsetForLocation(location)); @@ -295,8 +296,8 @@ ALWAYS_INLINE bool JSObject::inlineGetOwnPropertySlot(ExecState* exec, const Ide ALWAYS_INLINE bool JSObject::getOwnPropertySlotForWrite(ExecState* exec, const Identifier& propertyName, PropertySlot& slot, bool& slotIsWriteable) { unsigned attributes; - if (JSValue** location = getDirectLocation(propertyName, attributes)) { - if (m_structureID->hasGetterSetterProperties() && location[0]->isGetterSetter()) { + if (JSValuePtr* location = getDirectLocation(propertyName, attributes)) { + if (m_structure->hasGetterSetterProperties() && location[0].isGetterSetter()) { slotIsWriteable = false; fillGetterPropertySlot(slot, location); } else { @@ -326,7 +327,7 @@ ALWAYS_INLINE bool JSObject::getOwnPropertySlot(ExecState* exec, const Identifie ALWAYS_INLINE bool JSCell::fastGetOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) { - if (structureID()->typeInfo().hasStandardGetOwnPropertySlot()) + if (structure()->typeInfo().hasStandardGetOwnPropertySlot()) return asObject(this)->inlineGetOwnPropertySlot(exec, propertyName, slot); return getOwnPropertySlot(exec, propertyName, slot); } @@ -339,8 +340,8 @@ inline bool JSObject::getPropertySlot(ExecState* exec, const Identifier& propert while (true) { if (object->fastGetOwnPropertySlot(exec, propertyName, slot)) return true; - JSValue* prototype = object->prototype(); - if (!prototype->isObject()) + JSValuePtr prototype = object->prototype(); + if (!prototype.isObject()) return false; object = asObject(prototype); } @@ -352,14 +353,14 @@ inline bool JSObject::getPropertySlot(ExecState* exec, unsigned propertyName, Pr while (true) { if (object->getOwnPropertySlot(exec, propertyName, slot)) return true; - JSValue* prototype = object->prototype(); - if (!prototype->isObject()) + JSValuePtr prototype = object->prototype(); + if (!prototype.isObject()) return false; object = asObject(prototype); } } -inline JSValue* JSObject::get(ExecState* exec, const Identifier& propertyName) const +inline JSValuePtr JSObject::get(ExecState* exec, const Identifier& propertyName) const { PropertySlot slot(this); if (const_cast<JSObject*>(this)->getPropertySlot(exec, propertyName, slot)) @@ -368,7 +369,7 @@ inline JSValue* JSObject::get(ExecState* exec, const Identifier& propertyName) c return jsUndefined(); } -inline JSValue* JSObject::get(ExecState* exec, unsigned propertyName) const +inline JSValuePtr JSObject::get(ExecState* exec, unsigned propertyName) const { PropertySlot slot(this); if (const_cast<JSObject*>(this)->getPropertySlot(exec, propertyName, slot)) @@ -377,19 +378,19 @@ inline JSValue* JSObject::get(ExecState* exec, unsigned propertyName) const return jsUndefined(); } -inline void JSObject::putDirect(const Identifier& propertyName, JSValue* value, unsigned attr) +inline void JSObject::putDirect(const Identifier& propertyName, JSValuePtr value, unsigned attr) { PutPropertySlot slot; putDirect(propertyName, value, attr, false, slot); } -inline void JSObject::putDirect(const Identifier& propertyName, JSValue* value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot) +inline void JSObject::putDirect(const Identifier& propertyName, JSValuePtr value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot) { ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this)); - if (m_structureID->isDictionary()) { + if (m_structure->isDictionary()) { unsigned currentAttributes; - size_t offset = m_structureID->get(propertyName, currentAttributes); + size_t offset = m_structure->get(propertyName, currentAttributes); if (offset != WTF::notFound) { if (checkReadOnly && currentAttributes & ReadOnly) return; @@ -398,19 +399,33 @@ inline void JSObject::putDirect(const Identifier& propertyName, JSValue* value, return; } - size_t currentCapacity = m_structureID->propertyStorageCapacity(); - offset = m_structureID->addPropertyWithoutTransition(propertyName, attributes); - if (currentCapacity != m_structureID->propertyStorageCapacity()) - allocatePropertyStorage(currentCapacity, m_structureID->propertyStorageCapacity()); + size_t currentCapacity = m_structure->propertyStorageCapacity(); + offset = m_structure->addPropertyWithoutTransition(propertyName, attributes); + if (currentCapacity != m_structure->propertyStorageCapacity()) + allocatePropertyStorage(currentCapacity, m_structure->propertyStorageCapacity()); - ASSERT(offset < m_structureID->propertyStorageCapacity()); + ASSERT(offset < m_structure->propertyStorageCapacity()); m_propertyStorage[offset] = value; slot.setNewProperty(this, offset); return; } + size_t offset; + size_t currentCapacity = m_structure->propertyStorageCapacity(); + if (RefPtr<Structure> structure = Structure::addPropertyTransitionToExistingStructure(m_structure, propertyName, attributes, offset)) { + if (currentCapacity != structure->propertyStorageCapacity()) + allocatePropertyStorage(currentCapacity, structure->propertyStorageCapacity()); + + ASSERT(offset < structure->propertyStorageCapacity()); + m_propertyStorage[offset] = value; + slot.setNewProperty(this, offset); + slot.setWasTransition(true); + setStructure(structure.release()); + return; + } + unsigned currentAttributes; - size_t offset = m_structureID->get(propertyName, currentAttributes); + offset = m_structure->get(propertyName, currentAttributes); if (offset != WTF::notFound) { if (checkReadOnly && currentAttributes & ReadOnly) return; @@ -419,48 +434,47 @@ inline void JSObject::putDirect(const Identifier& propertyName, JSValue* value, return; } - size_t currentCapacity = m_structureID->propertyStorageCapacity(); - RefPtr<StructureID> structureID = StructureID::addPropertyTransition(m_structureID, propertyName, attributes, offset); - if (currentCapacity != structureID->propertyStorageCapacity()) - allocatePropertyStorage(currentCapacity, structureID->propertyStorageCapacity()); + RefPtr<Structure> structure = Structure::addPropertyTransition(m_structure, propertyName, attributes, offset); + if (currentCapacity != structure->propertyStorageCapacity()) + allocatePropertyStorage(currentCapacity, structure->propertyStorageCapacity()); - ASSERT(offset < structureID->propertyStorageCapacity()); + ASSERT(offset < structure->propertyStorageCapacity()); m_propertyStorage[offset] = value; slot.setNewProperty(this, offset); slot.setWasTransition(true); - setStructureID(structureID.release()); + setStructure(structure.release()); } -inline void JSObject::putDirectWithoutTransition(const Identifier& propertyName, JSValue* value, unsigned attributes) +inline void JSObject::putDirectWithoutTransition(const Identifier& propertyName, JSValuePtr value, unsigned attributes) { - size_t currentCapacity = m_structureID->propertyStorageCapacity(); - size_t offset = m_structureID->addPropertyWithoutTransition(propertyName, attributes); - if (currentCapacity != m_structureID->propertyStorageCapacity()) - allocatePropertyStorage(currentCapacity, m_structureID->propertyStorageCapacity()); + size_t currentCapacity = m_structure->propertyStorageCapacity(); + size_t offset = m_structure->addPropertyWithoutTransition(propertyName, attributes); + if (currentCapacity != m_structure->propertyStorageCapacity()) + allocatePropertyStorage(currentCapacity, m_structure->propertyStorageCapacity()); m_propertyStorage[offset] = value; } -inline void JSObject::transitionTo(StructureID* newStructureID) +inline void JSObject::transitionTo(Structure* newStructure) { - if (m_structureID->propertyStorageCapacity() != newStructureID->propertyStorageCapacity()) - allocatePropertyStorage(m_structureID->propertyStorageCapacity(), newStructureID->propertyStorageCapacity()); - setStructureID(newStructureID); + if (m_structure->propertyStorageCapacity() != newStructure->propertyStorageCapacity()) + allocatePropertyStorage(m_structure->propertyStorageCapacity(), newStructure->propertyStorageCapacity()); + setStructure(newStructure); } -inline JSValue* JSObject::toPrimitive(ExecState* exec, PreferredPrimitiveType preferredType) const +inline JSValuePtr JSObject::toPrimitive(ExecState* exec, PreferredPrimitiveType preferredType) const { return defaultValue(exec, preferredType); } -inline JSValue* JSValue::get(ExecState* exec, const Identifier& propertyName) const +inline JSValuePtr JSValuePtr::get(ExecState* exec, const Identifier& propertyName) const { - PropertySlot slot(this); + PropertySlot slot(asValue()); return get(exec, propertyName, slot); } -inline JSValue* JSValue::get(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) const +inline JSValuePtr JSValuePtr::get(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) const { - if (UNLIKELY(JSImmediate::isImmediate(asValue()))) { + if (UNLIKELY(!isCell())) { JSObject* prototype = JSImmediate::prototype(asValue(), exec); if (!prototype->getPropertySlot(exec, propertyName, slot)) return jsUndefined(); @@ -471,22 +485,22 @@ inline JSValue* JSValue::get(ExecState* exec, const Identifier& propertyName, Pr if (cell->fastGetOwnPropertySlot(exec, propertyName, slot)) return slot.getValue(exec, propertyName); ASSERT(cell->isObject()); - JSValue* prototype = static_cast<JSObject*>(cell)->prototype(); - if (!prototype->isObject()) + JSValuePtr prototype = static_cast<JSObject*>(cell)->prototype(); + if (!prototype.isObject()) return jsUndefined(); cell = asObject(prototype); } } -inline JSValue* JSValue::get(ExecState* exec, unsigned propertyName) const +inline JSValuePtr JSValuePtr::get(ExecState* exec, unsigned propertyName) const { - PropertySlot slot(this); + PropertySlot slot(asValue()); return get(exec, propertyName, slot); } -inline JSValue* JSValue::get(ExecState* exec, unsigned propertyName, PropertySlot& slot) const +inline JSValuePtr JSValuePtr::get(ExecState* exec, unsigned propertyName, PropertySlot& slot) const { - if (UNLIKELY(JSImmediate::isImmediate(asValue()))) { + if (UNLIKELY(!isCell())) { JSObject* prototype = JSImmediate::prototype(asValue(), exec); if (!prototype->getPropertySlot(exec, propertyName, slot)) return jsUndefined(); @@ -497,25 +511,25 @@ inline JSValue* JSValue::get(ExecState* exec, unsigned propertyName, PropertySlo if (cell->getOwnPropertySlot(exec, propertyName, slot)) return slot.getValue(exec, propertyName); ASSERT(cell->isObject()); - JSValue* prototype = static_cast<JSObject*>(cell)->prototype(); - if (!prototype->isObject()) + JSValuePtr prototype = static_cast<JSObject*>(cell)->prototype(); + if (!prototype.isObject()) return jsUndefined(); - cell = prototype->asCell(); + cell = prototype.asCell(); } } -inline void JSValue::put(ExecState* exec, const Identifier& propertyName, JSValue* value, PutPropertySlot& slot) +inline void JSValuePtr::put(ExecState* exec, const Identifier& propertyName, JSValuePtr value, PutPropertySlot& slot) { - if (UNLIKELY(JSImmediate::isImmediate(asValue()))) { + if (UNLIKELY(!isCell())) { JSImmediate::toObject(asValue(), exec)->put(exec, propertyName, value, slot); return; } asCell()->put(exec, propertyName, value, slot); } -inline void JSValue::put(ExecState* exec, unsigned propertyName, JSValue* value) +inline void JSValuePtr::put(ExecState* exec, unsigned propertyName, JSValuePtr value) { - if (UNLIKELY(JSImmediate::isImmediate(asValue()))) { + if (UNLIKELY(!isCell())) { JSImmediate::toObject(asValue(), exec)->put(exec, propertyName, value); return; } @@ -526,8 +540,8 @@ ALWAYS_INLINE void JSObject::allocatePropertyStorageInline(size_t oldSize, size_ { ASSERT(newSize > oldSize); - JSValue** oldPropertyStorage = m_propertyStorage; - m_propertyStorage = new JSValue*[newSize]; + JSValuePtr* oldPropertyStorage = m_propertyStorage; + m_propertyStorage = new JSValuePtr[newSize]; for (unsigned i = 0; i < oldSize; ++i) m_propertyStorage[i] = oldPropertyStorage[i]; diff --git a/JavaScriptCore/runtime/JSPropertyNameIterator.cpp b/JavaScriptCore/runtime/JSPropertyNameIterator.cpp index 55f4ced..ec8efea 100644 --- a/JavaScriptCore/runtime/JSPropertyNameIterator.cpp +++ b/JavaScriptCore/runtime/JSPropertyNameIterator.cpp @@ -37,13 +37,13 @@ JSPropertyNameIterator::~JSPropertyNameIterator() { } -JSValue* JSPropertyNameIterator::toPrimitive(ExecState*, PreferredPrimitiveType) const +JSValuePtr JSPropertyNameIterator::toPrimitive(ExecState*, PreferredPrimitiveType) const { ASSERT_NOT_REACHED(); return noValue(); } -bool JSPropertyNameIterator::getPrimitiveNumber(ExecState*, double&, JSValue*&) +bool JSPropertyNameIterator::getPrimitiveNumber(ExecState*, double&, JSValuePtr&) { ASSERT_NOT_REACHED(); return false; diff --git a/JavaScriptCore/runtime/JSPropertyNameIterator.h b/JavaScriptCore/runtime/JSPropertyNameIterator.h index 1853999..a6d6cd2 100644 --- a/JavaScriptCore/runtime/JSPropertyNameIterator.h +++ b/JavaScriptCore/runtime/JSPropertyNameIterator.h @@ -40,12 +40,12 @@ namespace JSC { class JSPropertyNameIterator : public JSCell { public: - static JSPropertyNameIterator* create(ExecState*, JSValue*); + static JSPropertyNameIterator* create(ExecState*, JSValuePtr); virtual ~JSPropertyNameIterator(); - virtual JSValue* toPrimitive(ExecState*, PreferredPrimitiveType) const; - virtual bool getPrimitiveNumber(ExecState*, double&, JSValue*&); + virtual JSValuePtr toPrimitive(ExecState*, PreferredPrimitiveType) const; + virtual bool getPrimitiveNumber(ExecState*, double&, JSValuePtr&); virtual bool toBoolean(ExecState*) const; virtual double toNumber(ExecState*) const; virtual UString toString(ExecState*) const; @@ -53,7 +53,7 @@ namespace JSC { virtual void mark(); - JSValue* next(ExecState*); + JSValuePtr next(ExecState*); void invalidate(); private: @@ -83,23 +83,23 @@ inline JSPropertyNameIterator::JSPropertyNameIterator(JSObject* object, PassRefP { } -inline JSPropertyNameIterator* JSPropertyNameIterator::create(ExecState* exec, JSValue* v) +inline JSPropertyNameIterator* JSPropertyNameIterator::create(ExecState* exec, JSValuePtr v) { - if (v->isUndefinedOrNull()) + if (v.isUndefinedOrNull()) return new (exec) JSPropertyNameIterator; - JSObject* o = v->toObject(exec); + JSObject* o = v.toObject(exec); PropertyNameArray propertyNames(exec); o->getPropertyNames(exec, propertyNames); return new (exec) JSPropertyNameIterator(o, propertyNames.releaseData()); } -inline JSValue* JSPropertyNameIterator::next(ExecState* exec) +inline JSValuePtr JSPropertyNameIterator::next(ExecState* exec) { if (m_position == m_end) return noValue(); - if (m_data->cachedStructureID() == m_object->structureID() && structureIDChainsAreEqual(m_data->cachedPrototypeChain(), m_object->structureID()->cachedPrototypeChain())) + if (m_data->cachedStructure() == m_object->structure() && structureChainsAreEqual(m_data->cachedPrototypeChain(), m_object->structure()->cachedPrototypeChain())) return jsOwnedString(exec, (*m_position++).ustring()); do { diff --git a/JavaScriptCore/runtime/JSStaticScopeObject.cpp b/JavaScriptCore/runtime/JSStaticScopeObject.cpp index 0698250..4196822 100644 --- a/JavaScriptCore/runtime/JSStaticScopeObject.cpp +++ b/JavaScriptCore/runtime/JSStaticScopeObject.cpp @@ -44,7 +44,7 @@ JSObject* JSStaticScopeObject::toThisObject(ExecState* exec) const return exec->globalThisValue(); } -void JSStaticScopeObject::put(ExecState*, const Identifier& propertyName, JSValue* value, PutPropertySlot&) +void JSStaticScopeObject::put(ExecState*, const Identifier& propertyName, JSValuePtr value, PutPropertySlot&) { if (symbolTablePut(propertyName, value)) return; @@ -52,7 +52,7 @@ void JSStaticScopeObject::put(ExecState*, const Identifier& propertyName, JSValu ASSERT_NOT_REACHED(); } -void JSStaticScopeObject::putWithAttributes(ExecState*, const Identifier& propertyName, JSValue* value, unsigned attributes) +void JSStaticScopeObject::putWithAttributes(ExecState*, const Identifier& propertyName, JSValuePtr value, unsigned attributes) { if (symbolTablePutWithAttributes(propertyName, value, attributes)) return; diff --git a/JavaScriptCore/runtime/JSStaticScopeObject.h b/JavaScriptCore/runtime/JSStaticScopeObject.h index b152862..e1400b7 100644 --- a/JavaScriptCore/runtime/JSStaticScopeObject.h +++ b/JavaScriptCore/runtime/JSStaticScopeObject.h @@ -43,8 +43,8 @@ namespace JSC{ }; public: - JSStaticScopeObject(ExecState* exec, const Identifier& ident, JSValue* value, unsigned attributes) - : JSVariableObject(exec->globalData().staticScopeStructureID, new JSStaticScopeObjectData()) + JSStaticScopeObject(ExecState* exec, const Identifier& ident, JSValuePtr value, unsigned attributes) + : JSVariableObject(exec->globalData().staticScopeStructure, new JSStaticScopeObjectData()) { d()->registerStore = value; symbolTable().add(ident.ustring().rep(), SymbolTableEntry(-1, attributes)); @@ -55,10 +55,10 @@ namespace JSC{ virtual JSObject* toThisObject(ExecState*) const; virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&); virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&, bool& slotIsWriteable); - virtual void put(ExecState*, const Identifier&, JSValue*, PutPropertySlot&); - void putWithAttributes(ExecState*, const Identifier&, JSValue*, unsigned attributes); + virtual void put(ExecState*, const Identifier&, JSValuePtr, PutPropertySlot&); + void putWithAttributes(ExecState*, const Identifier&, JSValuePtr, unsigned attributes); - static PassRefPtr<StructureID> createStructureID(JSValue* proto) { return StructureID::create(proto, TypeInfo(ObjectType, NeedsThisConversion)); } + static PassRefPtr<Structure> createStructure(JSValuePtr proto) { return Structure::create(proto, TypeInfo(ObjectType, NeedsThisConversion)); } private: JSStaticScopeObjectData* d() { return static_cast<JSStaticScopeObjectData*>(JSVariableObject::d); } diff --git a/JavaScriptCore/runtime/JSString.cpp b/JavaScriptCore/runtime/JSString.cpp index 49503d5..48391de 100644 --- a/JavaScriptCore/runtime/JSString.cpp +++ b/JavaScriptCore/runtime/JSString.cpp @@ -30,12 +30,12 @@ namespace JSC { -JSValue* JSString::toPrimitive(ExecState*, PreferredPrimitiveType) const +JSValuePtr JSString::toPrimitive(ExecState*, PreferredPrimitiveType) const { return const_cast<JSString*>(this); } -bool JSString::getPrimitiveNumber(ExecState*, double& number, JSValue*& value) +bool JSString::getPrimitiveNumber(ExecState*, double& number, JSValuePtr& value) { value = this; number = m_value.toDouble(); @@ -90,7 +90,7 @@ bool JSString::getOwnPropertySlot(ExecState* exec, const Identifier& propertyNam return true; slot.setBase(this); JSObject* object; - for (JSValue* prototype = exec->lexicalGlobalObject()->stringPrototype(); !prototype->isNull(); prototype = object->prototype()) { + for (JSValuePtr prototype = exec->lexicalGlobalObject()->stringPrototype(); !prototype.isNull(); prototype = object->prototype()) { object = asObject(prototype); if (object->getOwnPropertySlot(exec, propertyName, slot)) return true; diff --git a/JavaScriptCore/runtime/JSString.h b/JavaScriptCore/runtime/JSString.h index b6275e7..e4baa73 100644 --- a/JavaScriptCore/runtime/JSString.h +++ b/JavaScriptCore/runtime/JSString.h @@ -24,10 +24,10 @@ #define JSString_h #include "CommonIdentifiers.h" -#include "ExecState.h" +#include "CallFrame.h" +#include "Identifier.h" #include "JSNumberCell.h" #include "PropertySlot.h" -#include "identifier.h" namespace JSC { @@ -59,12 +59,12 @@ namespace JSC { JSString* jsOwnedString(ExecState*, const UString&); class JSString : public JSCell { - friend class CTI; - friend class Machine; + friend class JIT; + friend class Interpreter; public: JSString(JSGlobalData* globalData, const UString& value) - : JSCell(globalData->stringStructureID.get()) + : JSCell(globalData->stringStructure.get()) , m_value(value) { Heap::heap(this)->reportExtraMemoryCost(value.cost()); @@ -72,12 +72,12 @@ namespace JSC { enum HasOtherOwnerType { HasOtherOwner }; JSString(JSGlobalData* globalData, const UString& value, HasOtherOwnerType) - : JSCell(globalData->stringStructureID.get()) + : JSCell(globalData->stringStructure.get()) , m_value(value) { } JSString(JSGlobalData* globalData, PassRefPtr<UString::Rep> value, HasOtherOwnerType) - : JSCell(globalData->stringStructureID.get()) + : JSCell(globalData->stringStructure.get()) , m_value(value) { } @@ -90,7 +90,7 @@ namespace JSC { bool canGetIndex(unsigned i) { return i < static_cast<unsigned>(m_value.size()); } JSString* getIndex(JSGlobalData*, unsigned); - static PassRefPtr<StructureID> createStructureID(JSValue* proto) { return StructureID::create(proto, TypeInfo(StringType, NeedsThisConversion)); } + static PassRefPtr<Structure> createStructure(JSValuePtr proto) { return Structure::create(proto, TypeInfo(StringType, NeedsThisConversion)); } private: enum VPtrStealingHackType { VPtrStealingHack }; @@ -99,8 +99,8 @@ namespace JSC { { } - virtual JSValue* toPrimitive(ExecState*, PreferredPrimitiveType) const; - virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue*& value); + virtual JSValuePtr toPrimitive(ExecState*, PreferredPrimitiveType) const; + virtual bool getPrimitiveNumber(ExecState*, double& number, JSValuePtr& value); virtual bool toBoolean(ExecState*) const; virtual double toNumber(ExecState*) const; virtual JSObject* toObject(ExecState*) const; @@ -117,9 +117,9 @@ namespace JSC { UString m_value; }; - JSString* asString(JSValue*); + JSString* asString(JSValuePtr); - inline JSString* asString(JSValue* value) + inline JSString* asString(JSValuePtr value) { ASSERT(asCell(value)->isString()); return static_cast<JSString*>(asCell(value)); @@ -204,7 +204,7 @@ namespace JSC { // --- JSValue inlines ---------------------------- - inline JSString* JSValue::toThisJSString(ExecState* exec) + inline JSString* JSValuePtr::toThisJSString(ExecState* exec) { return JSImmediate::isImmediate(asValue()) ? jsString(exec, JSImmediate::toString(asValue())) : asCell()->toThisJSString(exec); } diff --git a/JavaScriptCore/runtime/JSType.h b/JavaScriptCore/runtime/JSType.h index f0fa28f..68f2890 100644 --- a/JavaScriptCore/runtime/JSType.h +++ b/JavaScriptCore/runtime/JSType.h @@ -1,6 +1,5 @@ /* - * This file is part of the KDE libraries - * Copyright (C) 2006 Apple Computer, Inc + * 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 @@ -19,8 +18,8 @@ * */ -#ifndef KJS_JSTYPE_H -#define KJS_JSTYPE_H +#ifndef JSType_h +#define JSType_h namespace JSC { diff --git a/JavaScriptCore/runtime/JSValue.cpp b/JavaScriptCore/runtime/JSValue.cpp index 73580b0..f549bff 100644 --- a/JavaScriptCore/runtime/JSValue.cpp +++ b/JavaScriptCore/runtime/JSValue.cpp @@ -31,20 +31,18 @@ namespace JSC { static const double D32 = 4294967296.0; // ECMA 9.4 -double JSValue::toInteger(ExecState* exec) const +double JSValuePtr::toInteger(ExecState* exec) const { - int32_t i; - if (getTruncatedInt32(i)) - return i; + if (isInt32Fast()) + return getInt32Fast(); double d = toNumber(exec); return isnan(d) ? 0.0 : trunc(d); } -double JSValue::toIntegerPreserveNaN(ExecState* exec) const +double JSValuePtr::toIntegerPreserveNaN(ExecState* exec) const { - int32_t i; - if (getTruncatedInt32(i)) - return i; + if (isInt32Fast()) + return getInt32Fast(); return trunc(toNumber(exec)); } @@ -68,11 +66,6 @@ int32_t toInt32SlowCase(double d, bool& ok) return static_cast<int32_t>(d32); } -int32_t JSValue::toInt32SlowCase(ExecState* exec, bool& ok) const -{ - return JSC::toInt32SlowCase(toNumber(exec), ok); -} - uint32_t toUInt32SlowCase(double d, bool& ok) { ok = true; @@ -91,14 +84,4 @@ uint32_t toUInt32SlowCase(double d, bool& ok) return static_cast<uint32_t>(d32); } -uint32_t JSValue::toUInt32SlowCase(ExecState* exec, bool& ok) const -{ - return JSC::toUInt32SlowCase(toNumber(exec), ok); -} - -float JSValue::toFloat(ExecState* exec) const -{ - return static_cast<float>(toNumber(exec)); -} - } // namespace JSC diff --git a/JavaScriptCore/runtime/JSValue.h b/JavaScriptCore/runtime/JSValue.h index 059a5e6..1172a1b 100644 --- a/JavaScriptCore/runtime/JSValue.h +++ b/JavaScriptCore/runtime/JSValue.h @@ -20,37 +20,87 @@ * */ +#include <stddef.h> // for size_t +#include <stdint.h> + #ifndef JSValue_h #define JSValue_h #include "CallData.h" #include "ConstructData.h" -#include "JSImmediate.h" -#include "ustring.h" -#include <stddef.h> // for size_t - -// The magic number 0x4000 is not important here, it is being subtracted back out (avoiding using zero since this -// can have unexpected effects in this type of macro, particularly where multiple-inheritance is involved). -#define OBJECT_OFFSET(class, member) (reinterpret_cast<ptrdiff_t>(&(reinterpret_cast<class*>(0x4000)->member)) - 0x4000) namespace JSC { class Identifier; + class JSCell; + class JSObject; class JSString; class PropertySlot; class PutPropertySlot; + class UString; struct ClassInfo; struct Instruction; enum PreferredPrimitiveType { NoPreference, PreferNumber, PreferString }; - class JSValue : Noncopyable { - protected: - JSValue() { } - virtual ~JSValue() { } + class JSImmediate; + class JSValueEncodedAsPointer; + + class JSValuePtr { + friend class JSImmediate; + static JSValuePtr makeImmediate(intptr_t value) + { + return JSValuePtr(reinterpret_cast<JSCell*>(value)); + } + + intptr_t immediateValue() + { + return reinterpret_cast<intptr_t>(m_ptr); + } + public: + JSValuePtr() + : m_ptr(0) + { + } + + JSValuePtr(JSCell* ptr) + : m_ptr(ptr) + { + } + + JSValuePtr(const JSCell* ptr) + : m_ptr(const_cast<JSCell*>(ptr)) + { + } + + operator bool() const + { + return m_ptr; + } + + bool operator==(const JSValuePtr other) const + { + return m_ptr == other.m_ptr; + } + + bool operator!=(const JSValuePtr other) const + { + return m_ptr != other.m_ptr; + } + + static JSValueEncodedAsPointer* encode(JSValuePtr value) + { + return reinterpret_cast<JSValueEncodedAsPointer*>(value.m_ptr); + } + + static JSValuePtr decode(JSValueEncodedAsPointer* ptr) + { + return JSValuePtr(reinterpret_cast<JSCell*>(ptr)); + } + // Querying the type. bool isUndefined() const; bool isNull() const; @@ -65,7 +115,7 @@ namespace JSC { // Extracting the value. bool getBoolean(bool&) const; bool getBoolean() const; // false if not a boolean - double getNumber() const; // NaN if not a number + bool getNumber(double&) const; double uncheckedGetNumber() const; bool getString(UString&) const; UString getString() const; // null string if not a string @@ -80,163 +130,92 @@ namespace JSC { bool getTruncatedUInt32(uint32_t&) const; // Basic conversions. - JSValue* toPrimitive(ExecState*, PreferredPrimitiveType = NoPreference) const; - bool getPrimitiveNumber(ExecState*, double& number, JSValue*&); + JSValuePtr toPrimitive(ExecState*, PreferredPrimitiveType = NoPreference) const; + bool getPrimitiveNumber(ExecState*, double& number, JSValuePtr&); bool toBoolean(ExecState*) const; // toNumber conversion is expected to be side effect free if an exception has // been set in the ExecState already. double toNumber(ExecState*) const; - JSValue* toJSNumber(ExecState*) const; // Fast path for when you expect that the value is an immediate number. - + JSValuePtr toJSNumber(ExecState*) const; // Fast path for when you expect that the value is an immediate number. UString toString(ExecState*) const; JSObject* toObject(ExecState*) const; // Integer conversions. + // 'x.numberToInt32(output)' is equivalent to 'x.isNumber() && x.toInt32(output)' double toInteger(ExecState*) const; double toIntegerPreserveNaN(ExecState*) const; int32_t toInt32(ExecState*) const; int32_t toInt32(ExecState*, bool& ok) const; + bool numberToInt32(int32_t& arg); uint32_t toUInt32(ExecState*) const; uint32_t toUInt32(ExecState*, bool& ok) const; - - // Floating point conversions. - float toFloat(ExecState*) const; + bool numberToUInt32(uint32_t& arg); + + // Fast integer operations; these values return results where the value is trivially available + // in a convenient form, for use in optimizations. No assumptions should be made based on the + // results of these operations, for example !isInt32Fast() does not necessarily indicate the + // result of getNumber will not be 0. + bool isInt32Fast() const; + int32_t getInt32Fast() const; + bool isUInt32Fast() const; + uint32_t getUInt32Fast() const; + static JSValuePtr makeInt32Fast(int32_t); + static bool areBothInt32Fast(JSValuePtr, JSValuePtr); + + // Floating point conversions (this is a convenience method for webcore; + // signle precision float is not a representation used in JS or JSC). + float toFloat(ExecState* exec) const { return static_cast<float>(toNumber(exec)); } // Garbage collection. void mark(); bool marked() const; // Object operations, with the toObject operation included. - JSValue* get(ExecState*, const Identifier& propertyName) const; - JSValue* get(ExecState*, const Identifier& propertyName, PropertySlot&) const; - JSValue* get(ExecState*, unsigned propertyName) const; - JSValue* get(ExecState*, unsigned propertyName, PropertySlot&) const; - void put(ExecState*, const Identifier& propertyName, JSValue*, PutPropertySlot&); - void put(ExecState*, unsigned propertyName, JSValue*); - bool deleteProperty(ExecState*, const Identifier& propertyName); - bool deleteProperty(ExecState*, unsigned propertyName); + JSValuePtr get(ExecState*, const Identifier& propertyName) const; + JSValuePtr get(ExecState*, const Identifier& propertyName, PropertySlot&) const; + JSValuePtr get(ExecState*, unsigned propertyName) const; + JSValuePtr get(ExecState*, unsigned propertyName, PropertySlot&) const; + void put(ExecState*, const Identifier& propertyName, JSValuePtr, PutPropertySlot&); + void put(ExecState*, unsigned propertyName, JSValuePtr); bool needsThisConversion() const; JSObject* toThisObject(ExecState*) const; UString toThisString(ExecState*) const; JSString* toThisJSString(ExecState*); - JSValue* getJSNumber(); // 0 if this is not a JSNumber or number object + static bool equal(ExecState* exec, JSValuePtr v1, JSValuePtr v2); + static bool equalSlowCase(ExecState* exec, JSValuePtr v1, JSValuePtr v2); + static bool equalSlowCaseInline(ExecState* exec, JSValuePtr v1, JSValuePtr v2); + static bool strictEqual(JSValuePtr v1, JSValuePtr v2); + static bool strictEqualSlowCase(JSValuePtr v1, JSValuePtr v2); + static bool strictEqualSlowCaseInline(JSValuePtr v1, JSValuePtr v2); - JSValue* asValue() const; + JSValuePtr getJSNumber(); // noValue() if this is not a JSNumber or number object + bool isCell() const; JSCell* asCell() const; private: - bool getPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); - bool getPropertySlot(ExecState*, unsigned propertyName, PropertySlot&); - int32_t toInt32SlowCase(ExecState*, bool& ok) const; - uint32_t toUInt32SlowCase(ExecState*, bool& ok) const; - }; - - // These are identical logic to the JSValue functions above, and faster than jsNumber(number)->toInt32(). - int32_t toInt32(double); - uint32_t toUInt32(double); - int32_t toInt32SlowCase(double, bool& ok); - uint32_t toUInt32SlowCase(double, bool& ok); - - inline JSValue* JSValue::asValue() const - { - return const_cast<JSValue*>(this); - } - - inline bool JSValue::isUndefined() const - { - return asValue() == jsUndefined(); - } - - inline bool JSValue::isNull() const - { - return asValue() == jsNull(); - } - - inline bool JSValue::isUndefinedOrNull() const - { - return JSImmediate::isUndefinedOrNull(asValue()); - } - - inline bool JSValue::isBoolean() const - { - return JSImmediate::isBoolean(asValue()); - } - - inline bool JSValue::getBoolean(bool& v) const - { - if (JSImmediate::isBoolean(asValue())) { - v = JSImmediate::toBoolean(asValue()); - return true; - } - - return false; - } - - inline bool JSValue::getBoolean() const - { - return asValue() == jsBoolean(true); - } + inline const JSValuePtr asValue() const { return *this; } - ALWAYS_INLINE int32_t JSValue::toInt32(ExecState* exec) const - { - int32_t i; - if (getTruncatedInt32(i)) - return i; - bool ok; - return toInt32SlowCase(exec, ok); - } + bool isDoubleNumber() const; + double getDoubleNumber() const; - inline uint32_t JSValue::toUInt32(ExecState* exec) const - { - uint32_t i; - if (getTruncatedUInt32(i)) - return i; - bool ok; - return toUInt32SlowCase(exec, ok); - } - - inline int32_t toInt32(double val) - { - if (!(val >= -2147483648.0 && val < 2147483648.0)) { - bool ignored; - return toInt32SlowCase(val, ignored); - } - return static_cast<int32_t>(val); - } + JSCell* m_ptr; + }; - inline uint32_t toUInt32(double val) + inline JSValuePtr noValue() { - if (!(val >= 0.0 && val < 4294967296.0)) { - bool ignored; - return toUInt32SlowCase(val, ignored); - } - return static_cast<uint32_t>(val); + return JSValuePtr(); } - inline int32_t JSValue::toInt32(ExecState* exec, bool& ok) const - { - int32_t i; - if (getTruncatedInt32(i)) { - ok = true; - return i; - } - return toInt32SlowCase(exec, ok); - } + inline bool operator==(const JSValuePtr a, const JSCell* b) { return a == JSValuePtr(b); } + inline bool operator==(const JSCell* a, const JSValuePtr b) { return JSValuePtr(a) == b; } - inline uint32_t JSValue::toUInt32(ExecState* exec, bool& ok) const - { - uint32_t i; - if (getTruncatedUInt32(i)) { - ok = true; - return i; - } - return toUInt32SlowCase(exec, ok); - } + inline bool operator!=(const JSValuePtr a, const JSCell* b) { return a != JSValuePtr(b); } + inline bool operator!=(const JSCell* a, const JSValuePtr b) { return JSValuePtr(a) != b; } } // namespace JSC diff --git a/JavaScriptCore/runtime/JSVariableObject.h b/JavaScriptCore/runtime/JSVariableObject.h index 1194517..9bf5c4f 100644 --- a/JavaScriptCore/runtime/JSVariableObject.h +++ b/JavaScriptCore/runtime/JSVariableObject.h @@ -41,10 +41,12 @@ namespace JSC { class Register; class JSVariableObject : public JSObject { + friend class JIT; + public: SymbolTable& symbolTable() const { return *d->symbolTable; } - virtual void putWithAttributes(ExecState*, const Identifier&, JSValue*, unsigned attributes) = 0; + virtual void putWithAttributes(ExecState*, const Identifier&, JSValuePtr, unsigned attributes) = 0; virtual bool deleteProperty(ExecState*, const Identifier&); virtual void getPropertyNames(ExecState*, PropertyNameArray&); @@ -72,18 +74,13 @@ namespace JSC { Register* registers; // "r" in the register file. OwnArrayPtr<Register> registerArray; // Independent copy of registers, used when a variable object copies its registers out of the register file. - static inline ptrdiff_t offsetOf_registers() - { - return OBJECT_OFFSET(JSVariableObjectData, registers); - } - private: JSVariableObjectData(const JSVariableObjectData&); JSVariableObjectData& operator=(const JSVariableObjectData&); }; - JSVariableObject(PassRefPtr<StructureID> structureID, JSVariableObjectData* data) - : JSObject(structureID) + JSVariableObject(PassRefPtr<Structure> structure, JSVariableObjectData* data) + : JSObject(structure) , d(data) // Subclass owns this pointer. { } @@ -93,21 +90,10 @@ namespace JSC { bool symbolTableGet(const Identifier&, PropertySlot&); bool symbolTableGet(const Identifier&, PropertySlot&, bool& slotIsWriteable); - bool symbolTablePut(const Identifier&, JSValue*); - bool symbolTablePutWithAttributes(const Identifier&, JSValue*, unsigned attributes); + bool symbolTablePut(const Identifier&, JSValuePtr); + bool symbolTablePutWithAttributes(const Identifier&, JSValuePtr, unsigned attributes); JSVariableObjectData* d; - - public: - static inline ptrdiff_t offsetOf_d() - { - return OBJECT_OFFSET(JSVariableObject, d); - } - - static inline ptrdiff_t offsetOf_Data_registers() - { - return JSVariableObjectData::offsetOf_registers(); - } }; inline bool JSVariableObject::symbolTableGet(const Identifier& propertyName, PropertySlot& slot) @@ -131,7 +117,7 @@ namespace JSC { return false; } - inline bool JSVariableObject::symbolTablePut(const Identifier& propertyName, JSValue* value) + inline bool JSVariableObject::symbolTablePut(const Identifier& propertyName, JSValuePtr value) { ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this)); @@ -144,7 +130,7 @@ namespace JSC { return true; } - inline bool JSVariableObject::symbolTablePutWithAttributes(const Identifier& propertyName, JSValue* value, unsigned attributes) + inline bool JSVariableObject::symbolTablePutWithAttributes(const Identifier& propertyName, JSValuePtr value, unsigned attributes) { ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this)); diff --git a/JavaScriptCore/runtime/JSWrapperObject.cpp b/JavaScriptCore/runtime/JSWrapperObject.cpp index c791d93..fb57018 100644 --- a/JavaScriptCore/runtime/JSWrapperObject.cpp +++ b/JavaScriptCore/runtime/JSWrapperObject.cpp @@ -29,8 +29,8 @@ ASSERT_CLASS_FITS_IN_CELL(JSWrapperObject); void JSWrapperObject::mark() { JSObject::mark(); - if (m_internalValue && !m_internalValue->marked()) - m_internalValue->mark(); + if (m_internalValue && !m_internalValue.marked()) + m_internalValue.mark(); } } // namespace JSC diff --git a/JavaScriptCore/runtime/JSWrapperObject.h b/JavaScriptCore/runtime/JSWrapperObject.h index 5e4ba17..7381128 100644 --- a/JavaScriptCore/runtime/JSWrapperObject.h +++ b/JavaScriptCore/runtime/JSWrapperObject.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2006 Maks Orlovich - * Copyright (C) 2006, 2008 Apple Inc. All rights reserved. + * 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 @@ -19,8 +19,8 @@ * */ -#ifndef KJS_JSWrapperObject_h -#define KJS_JSWrapperObject_h +#ifndef JSWrapperObject_h +#define JSWrapperObject_h #include "JSObject.h" @@ -30,31 +30,31 @@ namespace JSC { // Number, Boolean and Date which are wrappers for primitive types. class JSWrapperObject : public JSObject { protected: - explicit JSWrapperObject(PassRefPtr<StructureID>); + explicit JSWrapperObject(PassRefPtr<Structure>); public: - JSValue* internalValue() const { return m_internalValue; } - void setInternalValue(JSValue*); + JSValuePtr internalValue() const { return m_internalValue; } + void setInternalValue(JSValuePtr); virtual void mark(); private: - JSValue* m_internalValue; + JSValuePtr m_internalValue; }; - inline JSWrapperObject::JSWrapperObject(PassRefPtr<StructureID> structure) + inline JSWrapperObject::JSWrapperObject(PassRefPtr<Structure> structure) : JSObject(structure) , m_internalValue(noValue()) { } - inline void JSWrapperObject::setInternalValue(JSValue* value) + inline void JSWrapperObject::setInternalValue(JSValuePtr value) { ASSERT(value); - ASSERT(!value->isObject()); + ASSERT(!value.isObject()); m_internalValue = value; } } // namespace JSC -#endif // KJS_JSWrapperObject_h +#endif // JSWrapperObject_h diff --git a/JavaScriptCore/kjs/lookup.cpp b/JavaScriptCore/runtime/Lookup.cpp index 41ac725..98133a8 100644 --- a/JavaScriptCore/kjs/lookup.cpp +++ b/JavaScriptCore/runtime/Lookup.cpp @@ -18,7 +18,7 @@ */ #include "config.h" -#include "lookup.h" +#include "Lookup.h" #include "PrototypeFunction.h" @@ -26,6 +26,7 @@ namespace JSC { void HashTable::createTable(JSGlobalData* globalData) const { +#if ENABLE(PERFECT_HASH_SIZE) ASSERT(!table); HashEntry* entries = new HashEntry[hashSizeMask + 1]; for (int i = 0; i <= hashSizeMask; ++i) @@ -37,12 +38,41 @@ void HashTable::createTable(JSGlobalData* globalData) const entries[hashIndex].initialize(identifier, values[i].attributes, values[i].value1, values[i].value2); } table = entries; +#else + ASSERT(!table); + int linkIndex = compactHashSizeMask + 1; + HashEntry* entries = new HashEntry[compactSize]; + for (int i = 0; i < compactSize; ++i) + entries[i].setKey(0); + for (int i = 0; values[i].key; ++i) { + UString::Rep* identifier = Identifier::add(globalData, values[i].key).releaseRef(); + int hashIndex = identifier->computedHash() & compactHashSizeMask; + HashEntry* entry = &entries[hashIndex]; + + if (entry->key()) { + while (entry->next()) { + entry = entry->next(); + } + ASSERT(linkIndex < compactSize); + entry->setNext(&entries[linkIndex++]); + entry = entry->next(); + } + + entry->initialize(identifier, values[i].attributes, values[i].value1, values[i].value2); + } + table = entries; +#endif } void HashTable::deleteTable() const { if (table) { - for (int i = 0; i != hashSizeMask + 1; ++i) { +#if ENABLE(PERFECT_HASH_SIZE) + int max = hashSizeMask + 1; +#else + int max = compactSize; +#endif + for (int i = 0; i != max; ++i) { if (UString::Rep* key = table[i].key()) key->deref(); } @@ -54,7 +84,7 @@ void HashTable::deleteTable() const void setUpStaticFunctionSlot(ExecState* exec, const HashEntry* entry, JSObject* thisObj, const Identifier& propertyName, PropertySlot& slot) { ASSERT(entry->attributes() & Function); - JSValue** location = thisObj->getDirectLocation(propertyName); + JSValuePtr* location = thisObj->getDirectLocation(propertyName); if (!location) { PrototypeFunction* function = new (exec) PrototypeFunction(exec, entry->functionLength(), propertyName, entry->function()); diff --git a/JavaScriptCore/kjs/lookup.h b/JavaScriptCore/runtime/Lookup.h index a547613..55c3221 100644 --- a/JavaScriptCore/kjs/lookup.h +++ b/JavaScriptCore/runtime/Lookup.h @@ -1,6 +1,6 @@ /* * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) - * Copyright (C) 2003, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2003, 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 Lesser General Public @@ -18,18 +18,22 @@ * */ -#ifndef KJS_lookup_h -#define KJS_lookup_h +#ifndef Lookup_h +#define Lookup_h -#include "ExecState.h" +#include "CallFrame.h" +#include "Identifier.h" #include "JSFunction.h" #include "JSGlobalObject.h" #include "JSObject.h" #include "PropertySlot.h" -#include "identifier.h" #include <stdio.h> #include <wtf/Assertions.h> +// Set ENABLE_PERFECT_HASH_SIZE to 0 to save memory at the +// cost of speed. Test your platform as results may vary. +#define ENABLE_PERFECT_HASH_SIZE 1 + namespace JSC { // Hash table generated by the create_hash_table script. @@ -41,9 +45,9 @@ namespace JSC { }; // FIXME: There is no reason this get function can't be simpler. - // ie. typedef JSValue* (*GetFunction)(ExecState*, JSObject* baseObject) + // ie. typedef JSValuePtr (*GetFunction)(ExecState*, JSObject* baseObject) typedef PropertySlot::GetValueFunc GetFunction; - typedef void (*PutFunction)(ExecState*, JSObject* baseObject, JSValue* value); + typedef void (*PutFunction)(ExecState*, JSObject* baseObject, JSValuePtr value); class HashEntry { public: @@ -53,6 +57,9 @@ namespace JSC { m_attributes = attributes; m_u.store.value1 = v1; m_u.store.value2 = v2; +#if !ENABLE(PERFECT_HASH_SIZE) + m_next = 0; +#endif } void setKey(UString::Rep* key) { m_key = key; } @@ -68,6 +75,11 @@ namespace JSC { intptr_t lexerValue() const { ASSERT(!m_attributes); return m_u.lexer.value; } +#if !ENABLE(PERFECT_HASH_SIZE) + void setNext(HashEntry *next) { m_next = next; } + HashEntry* next() const { return m_next; } +#endif + private: UString::Rep* m_key; unsigned char m_attributes; // JSObject attributes @@ -90,10 +102,19 @@ namespace JSC { intptr_t unused; } lexer; } m_u; + +#if !ENABLE(PERFECT_HASH_SIZE) + HashEntry* m_next; +#endif }; struct HashTable { +#if ENABLE(PERFECT_HASH_SIZE) int hashSizeMask; // Precomputed size for the hash table (minus 1). +#else + int compactSize; + int compactHashSizeMask; +#endif const HashTableValue* values; // Fixed values generated by script. mutable const HashEntry* table; // Table allocated at runtime. @@ -127,11 +148,28 @@ namespace JSC { private: ALWAYS_INLINE const HashEntry* entry(const Identifier& identifier) const { +#if ENABLE(PERFECT_HASH_SIZE) ASSERT(table); const HashEntry* entry = &table[identifier.ustring().rep()->computedHash() & hashSizeMask]; if (entry->key() != identifier.ustring().rep()) return 0; return entry; +#else + ASSERT(table); + + const HashEntry* entry = &table[identifier.ustring().rep()->computedHash() & compactHashSizeMask]; + + if (!entry->key()) + return 0; + + do { + if (entry->key() == identifier.ustring().rep()) + return entry; + entry = entry->next(); + } while (entry); + + return 0; +#endif } // Convert the hash table keys to identifiers. @@ -205,7 +243,7 @@ namespace JSC { * is found it sets the value and returns true, else it returns false. */ template <class ThisImp> - inline bool lookupPut(ExecState* exec, const Identifier& propertyName, JSValue* value, const HashTable* table, ThisImp* thisObj) + inline bool lookupPut(ExecState* exec, const Identifier& propertyName, JSValuePtr value, const HashTable* table, ThisImp* thisObj) { const HashEntry* entry = table->entry(exec, propertyName); @@ -227,7 +265,7 @@ namespace JSC { * then it calls put() on the ParentImp class. */ template <class ThisImp, class ParentImp> - inline void lookupPut(ExecState* exec, const Identifier& propertyName, JSValue* value, const HashTable* table, ThisImp* thisObj, PutPropertySlot& slot) + inline void lookupPut(ExecState* exec, const Identifier& propertyName, JSValuePtr value, const HashTable* table, ThisImp* thisObj, PutPropertySlot& slot) { if (!lookupPut<ThisImp>(exec, propertyName, value, table, thisObj)) thisObj->ParentImp::put(exec, propertyName, value, slot); // not found: forward to parent @@ -235,4 +273,4 @@ namespace JSC { } // namespace JSC -#endif // KJS_lookup_h +#endif // Lookup_h diff --git a/JavaScriptCore/runtime/MathObject.cpp b/JavaScriptCore/runtime/MathObject.cpp index 8b972d3..f9b7653 100644 --- a/JavaScriptCore/runtime/MathObject.cpp +++ b/JavaScriptCore/runtime/MathObject.cpp @@ -22,33 +22,35 @@ #include "MathObject.h" #include "ObjectPrototype.h" -#include "operations.h" +#include "Operations.h" #include <time.h> #include <wtf/Assertions.h> #include <wtf/MathExtras.h> +#include <wtf/RandomNumber.h> +#include <wtf/RandomNumberSeed.h> namespace JSC { ASSERT_CLASS_FITS_IN_CELL(MathObject); -static JSValue* mathProtoFuncAbs(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* mathProtoFuncACos(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* mathProtoFuncASin(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* mathProtoFuncATan(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* mathProtoFuncATan2(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* mathProtoFuncCeil(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* mathProtoFuncCos(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* mathProtoFuncExp(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* mathProtoFuncFloor(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* mathProtoFuncLog(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* mathProtoFuncMax(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* mathProtoFuncMin(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* mathProtoFuncPow(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* mathProtoFuncRandom(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* mathProtoFuncRound(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* mathProtoFuncSin(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* mathProtoFuncSqrt(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* mathProtoFuncTan(ExecState*, JSObject*, JSValue*, const ArgList&); +static JSValuePtr mathProtoFuncAbs(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr mathProtoFuncACos(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr mathProtoFuncASin(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr mathProtoFuncATan(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr mathProtoFuncATan2(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr mathProtoFuncCeil(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr mathProtoFuncCos(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr mathProtoFuncExp(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr mathProtoFuncFloor(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr mathProtoFuncLog(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr mathProtoFuncMax(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr mathProtoFuncMin(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr mathProtoFuncPow(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr mathProtoFuncRandom(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr mathProtoFuncRound(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr mathProtoFuncSin(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr mathProtoFuncSqrt(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr mathProtoFuncTan(ExecState*, JSObject*, JSValuePtr, const ArgList&); } @@ -83,7 +85,7 @@ const ClassInfo MathObject::info = { "Math", 0, 0, ExecState::mathTable }; @end */ -MathObject::MathObject(ExecState* exec, PassRefPtr<StructureID> structure) +MathObject::MathObject(ExecState* exec, PassRefPtr<Structure> structure) : JSObject(structure) { putDirectWithoutTransition(Identifier(exec, "E"), jsNumber(exec, exp(1.0)), DontDelete | DontEnum | ReadOnly); @@ -94,6 +96,7 @@ MathObject::MathObject(ExecState* exec, PassRefPtr<StructureID> structure) putDirectWithoutTransition(Identifier(exec, "PI"), jsNumber(exec, piDouble), DontDelete | DontEnum | ReadOnly); putDirectWithoutTransition(Identifier(exec, "SQRT1_2"), jsNumber(exec, sqrt(0.5)), DontDelete | DontEnum | ReadOnly); putDirectWithoutTransition(Identifier(exec, "SQRT2"), jsNumber(exec, sqrt(2.0)), DontDelete | DontEnum | ReadOnly); + WTF::initializeWeakRandomNumberGenerator(); } // ECMA 15.8 @@ -112,62 +115,62 @@ bool MathObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyN // ------------------------------ Functions -------------------------------- -JSValue* mathProtoFuncAbs(ExecState* exec, JSObject*, JSValue*, const ArgList& args) +JSValuePtr mathProtoFuncAbs(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) { - return jsNumber(exec, fabs(args.at(exec, 0)->toNumber(exec))); + return jsNumber(exec, fabs(args.at(exec, 0).toNumber(exec))); } -JSValue* mathProtoFuncACos(ExecState* exec, JSObject*, JSValue*, const ArgList& args) +JSValuePtr mathProtoFuncACos(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) { - return jsNumber(exec, acos(args.at(exec, 0)->toNumber(exec))); + return jsNumber(exec, acos(args.at(exec, 0).toNumber(exec))); } -JSValue* mathProtoFuncASin(ExecState* exec, JSObject*, JSValue*, const ArgList& args) +JSValuePtr mathProtoFuncASin(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) { - return jsNumber(exec, asin(args.at(exec, 0)->toNumber(exec))); + return jsNumber(exec, asin(args.at(exec, 0).toNumber(exec))); } -JSValue* mathProtoFuncATan(ExecState* exec, JSObject*, JSValue*, const ArgList& args) +JSValuePtr mathProtoFuncATan(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) { - return jsNumber(exec, atan(args.at(exec, 0)->toNumber(exec))); + return jsNumber(exec, atan(args.at(exec, 0).toNumber(exec))); } -JSValue* mathProtoFuncATan2(ExecState* exec, JSObject*, JSValue*, const ArgList& args) +JSValuePtr mathProtoFuncATan2(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) { - return jsNumber(exec, atan2(args.at(exec, 0)->toNumber(exec), args.at(exec, 1)->toNumber(exec))); + return jsNumber(exec, atan2(args.at(exec, 0).toNumber(exec), args.at(exec, 1).toNumber(exec))); } -JSValue* mathProtoFuncCeil(ExecState* exec, JSObject*, JSValue*, const ArgList& args) +JSValuePtr mathProtoFuncCeil(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) { - return jsNumber(exec, ceil(args.at(exec, 0)->toNumber(exec))); + return jsNumber(exec, ceil(args.at(exec, 0).toNumber(exec))); } -JSValue* mathProtoFuncCos(ExecState* exec, JSObject*, JSValue*, const ArgList& args) +JSValuePtr mathProtoFuncCos(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) { - return jsNumber(exec, cos(args.at(exec, 0)->toNumber(exec))); + return jsNumber(exec, cos(args.at(exec, 0).toNumber(exec))); } -JSValue* mathProtoFuncExp(ExecState* exec, JSObject*, JSValue*, const ArgList& args) +JSValuePtr mathProtoFuncExp(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) { - return jsNumber(exec, exp(args.at(exec, 0)->toNumber(exec))); + return jsNumber(exec, exp(args.at(exec, 0).toNumber(exec))); } -JSValue* mathProtoFuncFloor(ExecState* exec, JSObject*, JSValue*, const ArgList& args) +JSValuePtr mathProtoFuncFloor(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) { - return jsNumber(exec, floor(args.at(exec, 0)->toNumber(exec))); + return jsNumber(exec, floor(args.at(exec, 0).toNumber(exec))); } -JSValue* mathProtoFuncLog(ExecState* exec, JSObject*, JSValue*, const ArgList& args) +JSValuePtr mathProtoFuncLog(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) { - return jsNumber(exec, log(args.at(exec, 0)->toNumber(exec))); + return jsNumber(exec, log(args.at(exec, 0).toNumber(exec))); } -JSValue* mathProtoFuncMax(ExecState* exec, JSObject*, JSValue*, const ArgList& args) +JSValuePtr mathProtoFuncMax(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) { unsigned argsCount = args.size(); double result = -Inf; for (unsigned k = 0; k < argsCount; ++k) { - double val = args.at(exec, k)->toNumber(exec); + double val = args.at(exec, k).toNumber(exec); if (isnan(val)) { result = NaN; break; @@ -178,12 +181,12 @@ JSValue* mathProtoFuncMax(ExecState* exec, JSObject*, JSValue*, const ArgList& a return jsNumber(exec, result); } -JSValue* mathProtoFuncMin(ExecState* exec, JSObject*, JSValue*, const ArgList& args) +JSValuePtr mathProtoFuncMin(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) { unsigned argsCount = args.size(); double result = +Inf; for (unsigned k = 0; k < argsCount; ++k) { - double val = args.at(exec, k)->toNumber(exec); + double val = args.at(exec, k).toNumber(exec); if (isnan(val)) { result = NaN; break; @@ -194,12 +197,12 @@ JSValue* mathProtoFuncMin(ExecState* exec, JSObject*, JSValue*, const ArgList& a return jsNumber(exec, result); } -JSValue* mathProtoFuncPow(ExecState* exec, JSObject*, JSValue*, const ArgList& args) +JSValuePtr mathProtoFuncPow(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) { // ECMA 15.8.2.1.13 - double arg = args.at(exec, 0)->toNumber(exec); - double arg2 = args.at(exec, 1)->toNumber(exec); + double arg = args.at(exec, 0).toNumber(exec); + double arg2 = args.at(exec, 1).toNumber(exec); if (isnan(arg2)) return jsNaN(exec); @@ -208,40 +211,32 @@ JSValue* mathProtoFuncPow(ExecState* exec, JSObject*, JSValue*, const ArgList& a return jsNumber(exec, pow(arg, arg2)); } -JSValue* mathProtoFuncRandom(ExecState* exec, JSObject*, JSValue*, const ArgList&) +JSValuePtr mathProtoFuncRandom(ExecState* exec, JSObject*, JSValuePtr, const ArgList&) { -#if !ENABLE(JSC_MULTIPLE_THREADS) - static bool didInitRandom; - if (!didInitRandom) { - wtf_random_init(); - didInitRandom = true; - } -#endif - - return jsNumber(exec, wtf_random()); + return jsNumber(exec, WTF::weakRandomNumber()); } -JSValue* mathProtoFuncRound(ExecState* exec, JSObject*, JSValue*, const ArgList& args) +JSValuePtr mathProtoFuncRound(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) { - double arg = args.at(exec, 0)->toNumber(exec); + double arg = args.at(exec, 0).toNumber(exec); if (signbit(arg) && arg >= -0.5) return jsNumber(exec, -0.0); return jsNumber(exec, floor(arg + 0.5)); } -JSValue* mathProtoFuncSin(ExecState* exec, JSObject*, JSValue*, const ArgList& args) +JSValuePtr mathProtoFuncSin(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) { - return jsNumber(exec, sin(args.at(exec, 0)->toNumber(exec))); + return jsNumber(exec, sin(args.at(exec, 0).toNumber(exec))); } -JSValue* mathProtoFuncSqrt(ExecState* exec, JSObject*, JSValue*, const ArgList& args) +JSValuePtr mathProtoFuncSqrt(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) { - return jsNumber(exec, sqrt(args.at(exec, 0)->toNumber(exec))); + return jsNumber(exec, sqrt(args.at(exec, 0).toNumber(exec))); } -JSValue* mathProtoFuncTan(ExecState* exec, JSObject*, JSValue*, const ArgList& args) +JSValuePtr mathProtoFuncTan(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) { - return jsNumber(exec, tan(args.at(exec, 0)->toNumber(exec))); + return jsNumber(exec, tan(args.at(exec, 0).toNumber(exec))); } } // namespace JSC diff --git a/JavaScriptCore/runtime/MathObject.h b/JavaScriptCore/runtime/MathObject.h index 704b10e..d6163fd 100644 --- a/JavaScriptCore/runtime/MathObject.h +++ b/JavaScriptCore/runtime/MathObject.h @@ -27,16 +27,16 @@ namespace JSC { class MathObject : public JSObject { public: - MathObject(ExecState*, PassRefPtr<StructureID>); + MathObject(ExecState*, PassRefPtr<Structure>); virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&); virtual const ClassInfo* classInfo() const { return &info; } static const ClassInfo info; - static PassRefPtr<StructureID> createStructureID(JSValue* prototype) + static PassRefPtr<Structure> createStructure(JSValuePtr prototype) { - return StructureID::create(prototype, TypeInfo(ObjectType)); + return Structure::create(prototype, TypeInfo(ObjectType)); } }; diff --git a/JavaScriptCore/runtime/NativeErrorConstructor.cpp b/JavaScriptCore/runtime/NativeErrorConstructor.cpp index 05159f0..eee9890 100644 --- a/JavaScriptCore/runtime/NativeErrorConstructor.cpp +++ b/JavaScriptCore/runtime/NativeErrorConstructor.cpp @@ -23,6 +23,7 @@ #include "ErrorInstance.h" #include "JSFunction.h" +#include "JSString.h" #include "NativeErrorPrototype.h" namespace JSC { @@ -31,9 +32,9 @@ ASSERT_CLASS_FITS_IN_CELL(NativeErrorConstructor); const ClassInfo NativeErrorConstructor::info = { "Function", &InternalFunction::info, 0, 0 }; -NativeErrorConstructor::NativeErrorConstructor(ExecState* exec, PassRefPtr<StructureID> structure, NativeErrorPrototype* nativeErrorPrototype) - : InternalFunction(&exec->globalData(), structure, Identifier(exec, nativeErrorPrototype->getDirect(exec->propertyNames().name)->getString())) - , m_errorStructure(ErrorInstance::createStructureID(nativeErrorPrototype)) +NativeErrorConstructor::NativeErrorConstructor(ExecState* exec, PassRefPtr<Structure> structure, NativeErrorPrototype* nativeErrorPrototype) + : InternalFunction(&exec->globalData(), structure, Identifier(exec, nativeErrorPrototype->getDirect(exec->propertyNames().name).getString())) + , m_errorStructure(ErrorInstance::createStructure(nativeErrorPrototype)) { putDirect(exec->propertyNames().length, jsNumber(exec, 1), DontDelete | ReadOnly | DontEnum); // ECMA 15.11.7.5 putDirect(exec->propertyNames().prototype, nativeErrorPrototype, DontDelete | ReadOnly | DontEnum); @@ -42,8 +43,8 @@ NativeErrorConstructor::NativeErrorConstructor(ExecState* exec, PassRefPtr<Struc ErrorInstance* NativeErrorConstructor::construct(ExecState* exec, const ArgList& args) { ErrorInstance* object = new (exec) ErrorInstance(m_errorStructure); - if (!args.at(exec, 0)->isUndefined()) - object->putDirect(exec->propertyNames().message, jsString(exec, args.at(exec, 0)->toString(exec))); + if (!args.at(exec, 0).isUndefined()) + object->putDirect(exec->propertyNames().message, jsString(exec, args.at(exec, 0).toString(exec))); return object; } @@ -58,7 +59,7 @@ ConstructType NativeErrorConstructor::getConstructData(ConstructData& constructD return ConstructTypeHost; } -static JSValue* callNativeErrorConstructor(ExecState* exec, JSObject* constructor, JSValue*, const ArgList& args) +static JSValuePtr callNativeErrorConstructor(ExecState* exec, JSObject* constructor, JSValuePtr, const ArgList& args) { return static_cast<NativeErrorConstructor*>(constructor)->construct(exec, args); } diff --git a/JavaScriptCore/runtime/NativeErrorConstructor.h b/JavaScriptCore/runtime/NativeErrorConstructor.h index 85acbb9..118d1f4 100644 --- a/JavaScriptCore/runtime/NativeErrorConstructor.h +++ b/JavaScriptCore/runtime/NativeErrorConstructor.h @@ -31,7 +31,7 @@ namespace JSC { class NativeErrorConstructor : public InternalFunction { public: - NativeErrorConstructor(ExecState*, PassRefPtr<StructureID>, NativeErrorPrototype*); + NativeErrorConstructor(ExecState*, PassRefPtr<Structure>, NativeErrorPrototype*); static const ClassInfo info; @@ -43,7 +43,7 @@ namespace JSC { virtual const ClassInfo* classInfo() const { return &info; } - RefPtr<StructureID> m_errorStructure; + RefPtr<Structure> m_errorStructure; }; } // namespace JSC diff --git a/JavaScriptCore/runtime/NativeErrorPrototype.cpp b/JavaScriptCore/runtime/NativeErrorPrototype.cpp index 9403aa9..84190a0 100644 --- a/JavaScriptCore/runtime/NativeErrorPrototype.cpp +++ b/JavaScriptCore/runtime/NativeErrorPrototype.cpp @@ -23,13 +23,13 @@ #include "ErrorPrototype.h" #include "JSString.h" -#include "ustring.h" +#include "UString.h" namespace JSC { ASSERT_CLASS_FITS_IN_CELL(NativeErrorPrototype); -NativeErrorPrototype::NativeErrorPrototype(ExecState* exec, PassRefPtr<StructureID> structure, const UString& name, const UString& message) +NativeErrorPrototype::NativeErrorPrototype(ExecState* exec, PassRefPtr<Structure> structure, const UString& name, const UString& message) : JSObject(structure) { putDirect(exec->propertyNames().name, jsString(exec, name), 0); diff --git a/JavaScriptCore/runtime/NativeErrorPrototype.h b/JavaScriptCore/runtime/NativeErrorPrototype.h index 719cb90..77bfe8a 100644 --- a/JavaScriptCore/runtime/NativeErrorPrototype.h +++ b/JavaScriptCore/runtime/NativeErrorPrototype.h @@ -27,7 +27,7 @@ namespace JSC { class NativeErrorPrototype : public JSObject { public: - NativeErrorPrototype(ExecState*, PassRefPtr<StructureID>, const UString& name, const UString& message); + NativeErrorPrototype(ExecState*, PassRefPtr<Structure>, const UString& name, const UString& message); }; } // namespace JSC diff --git a/JavaScriptCore/runtime/NumberConstructor.cpp b/JavaScriptCore/runtime/NumberConstructor.cpp index 5b6ccf8..caa4a70 100644 --- a/JavaScriptCore/runtime/NumberConstructor.cpp +++ b/JavaScriptCore/runtime/NumberConstructor.cpp @@ -29,11 +29,11 @@ namespace JSC { ASSERT_CLASS_FITS_IN_CELL(NumberConstructor); -static JSValue* numberConstructorNaNValue(ExecState*, const Identifier&, const PropertySlot&); -static JSValue* numberConstructorNegInfinity(ExecState*, const Identifier&, const PropertySlot&); -static JSValue* numberConstructorPosInfinity(ExecState*, const Identifier&, const PropertySlot&); -static JSValue* numberConstructorMaxValue(ExecState*, const Identifier&, const PropertySlot&); -static JSValue* numberConstructorMinValue(ExecState*, const Identifier&, const PropertySlot&); +static JSValuePtr numberConstructorNaNValue(ExecState*, const Identifier&, const PropertySlot&); +static JSValuePtr numberConstructorNegInfinity(ExecState*, const Identifier&, const PropertySlot&); +static JSValuePtr numberConstructorPosInfinity(ExecState*, const Identifier&, const PropertySlot&); +static JSValuePtr numberConstructorMaxValue(ExecState*, const Identifier&, const PropertySlot&); +static JSValuePtr numberConstructorMinValue(ExecState*, const Identifier&, const PropertySlot&); } // namespace JSC @@ -53,7 +53,7 @@ const ClassInfo NumberConstructor::info = { "Function", &InternalFunction::info, @end */ -NumberConstructor::NumberConstructor(ExecState* exec, PassRefPtr<StructureID> structure, NumberPrototype* numberPrototype) +NumberConstructor::NumberConstructor(ExecState* exec, PassRefPtr<Structure> structure, NumberPrototype* numberPrototype) : InternalFunction(&exec->globalData(), structure, Identifier(exec, numberPrototype->info.className)) { // Number.Prototype @@ -68,36 +68,36 @@ bool NumberConstructor::getOwnPropertySlot(ExecState* exec, const Identifier& pr return getStaticValueSlot<NumberConstructor, InternalFunction>(exec, ExecState::numberTable(exec), this, propertyName, slot); } -JSValue* numberConstructorNaNValue(ExecState* exec, const Identifier&, const PropertySlot&) +JSValuePtr numberConstructorNaNValue(ExecState* exec, const Identifier&, const PropertySlot&) { return jsNaN(exec); } -JSValue* numberConstructorNegInfinity(ExecState* exec, const Identifier&, const PropertySlot&) +JSValuePtr numberConstructorNegInfinity(ExecState* exec, const Identifier&, const PropertySlot&) { - return jsNumberCell(exec, -Inf); + return jsNumber(exec, -Inf); } -JSValue* numberConstructorPosInfinity(ExecState* exec, const Identifier&, const PropertySlot&) +JSValuePtr numberConstructorPosInfinity(ExecState* exec, const Identifier&, const PropertySlot&) { - return jsNumberCell(exec, Inf); + return jsNumber(exec, Inf); } -JSValue* numberConstructorMaxValue(ExecState* exec, const Identifier&, const PropertySlot&) +JSValuePtr numberConstructorMaxValue(ExecState* exec, const Identifier&, const PropertySlot&) { - return jsNumberCell(exec, 1.7976931348623157E+308); + return jsNumber(exec, 1.7976931348623157E+308); } -JSValue* numberConstructorMinValue(ExecState* exec, const Identifier&, const PropertySlot&) +JSValuePtr numberConstructorMinValue(ExecState* exec, const Identifier&, const PropertySlot&) { - return jsNumberCell(exec, 5E-324); + return jsNumber(exec, 5E-324); } // ECMA 15.7.1 static JSObject* constructWithNumberConstructor(ExecState* exec, JSObject*, const ArgList& args) { NumberObject* object = new (exec) NumberObject(exec->lexicalGlobalObject()->numberObjectStructure()); - double n = args.isEmpty() ? 0 : args.at(exec, 0)->toNumber(exec); + double n = args.isEmpty() ? 0 : args.at(exec, 0).toNumber(exec); object->setInternalValue(jsNumber(exec, n)); return object; } @@ -109,9 +109,9 @@ ConstructType NumberConstructor::getConstructData(ConstructData& constructData) } // ECMA 15.7.2 -static JSValue* callNumberConstructor(ExecState* exec, JSObject*, JSValue*, const ArgList& args) +static JSValuePtr callNumberConstructor(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) { - return jsNumber(exec, args.isEmpty() ? 0 : args.at(exec, 0)->toNumber(exec)); + return jsNumber(exec, args.isEmpty() ? 0 : args.at(exec, 0).toNumber(exec)); } CallType NumberConstructor::getCallData(CallData& callData) diff --git a/JavaScriptCore/runtime/NumberConstructor.h b/JavaScriptCore/runtime/NumberConstructor.h index 8da23c4..070be5f 100644 --- a/JavaScriptCore/runtime/NumberConstructor.h +++ b/JavaScriptCore/runtime/NumberConstructor.h @@ -29,16 +29,16 @@ namespace JSC { class NumberConstructor : public InternalFunction { public: - NumberConstructor(ExecState*, PassRefPtr<StructureID>, NumberPrototype*); + NumberConstructor(ExecState*, PassRefPtr<Structure>, NumberPrototype*); virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&); - JSValue* getValueProperty(ExecState*, int token) const; + JSValuePtr getValueProperty(ExecState*, int token) const; static const ClassInfo info; - static PassRefPtr<StructureID> createStructureID(JSValue* proto) + static PassRefPtr<Structure> createStructure(JSValuePtr proto) { - return StructureID::create(proto, TypeInfo(ObjectType, ImplementsHasInstance)); + return Structure::create(proto, TypeInfo(ObjectType, ImplementsHasInstance)); } enum { NaNValue, NegInfinity, PosInfinity, MaxValue, MinValue }; diff --git a/JavaScriptCore/runtime/NumberObject.cpp b/JavaScriptCore/runtime/NumberObject.cpp index 252671b..dc10d8f 100644 --- a/JavaScriptCore/runtime/NumberObject.cpp +++ b/JavaScriptCore/runtime/NumberObject.cpp @@ -31,28 +31,21 @@ ASSERT_CLASS_FITS_IN_CELL(NumberObject); const ClassInfo NumberObject::info = { "Number", 0, 0, 0 }; -NumberObject::NumberObject(PassRefPtr<StructureID> structure) +NumberObject::NumberObject(PassRefPtr<Structure> structure) : JSWrapperObject(structure) { } -JSValue* NumberObject::getJSNumber() +JSValuePtr NumberObject::getJSNumber() { return internalValue(); } -NumberObject* constructNumber(ExecState* exec, JSNumberCell* number) +NumberObject* constructNumber(ExecState* exec, JSValuePtr number) { NumberObject* object = new (exec) NumberObject(exec->lexicalGlobalObject()->numberObjectStructure()); object->setInternalValue(number); return object; } -NumberObject* constructNumberFromImmediateNumber(ExecState* exec, JSValue* value) -{ - NumberObject* object = new (exec) NumberObject(exec->lexicalGlobalObject()->numberObjectStructure()); - object->setInternalValue(value); - return object; -} - } // namespace JSC diff --git a/JavaScriptCore/runtime/NumberObject.h b/JavaScriptCore/runtime/NumberObject.h index eddecd1..285421d 100644 --- a/JavaScriptCore/runtime/NumberObject.h +++ b/JavaScriptCore/runtime/NumberObject.h @@ -25,22 +25,19 @@ namespace JSC { - class JSNumberCell; - class NumberObject : public JSWrapperObject { public: - explicit NumberObject(PassRefPtr<StructureID>); + explicit NumberObject(PassRefPtr<Structure>); static const ClassInfo info; private: virtual const ClassInfo* classInfo() const { return &info; } - virtual JSValue* getJSNumber(); + virtual JSValuePtr getJSNumber(); }; - NumberObject* constructNumber(ExecState*, JSNumberCell*); - NumberObject* constructNumberFromImmediateNumber(ExecState*, JSValue*); + NumberObject* constructNumber(ExecState*, JSValuePtr); } // namespace JSC diff --git a/JavaScriptCore/runtime/NumberPrototype.cpp b/JavaScriptCore/runtime/NumberPrototype.cpp index d203e3f..3e5ac91 100644 --- a/JavaScriptCore/runtime/NumberPrototype.cpp +++ b/JavaScriptCore/runtime/NumberPrototype.cpp @@ -26,7 +26,7 @@ #include "JSString.h" #include "PrototypeFunction.h" #include "dtoa.h" -#include "operations.h" +#include "Operations.h" #include <wtf/Assertions.h> #include <wtf/MathExtras.h> #include <wtf/Vector.h> @@ -35,16 +35,16 @@ namespace JSC { ASSERT_CLASS_FITS_IN_CELL(NumberPrototype); -static JSValue* numberProtoFuncToString(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* numberProtoFuncToLocaleString(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* numberProtoFuncValueOf(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* numberProtoFuncToFixed(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* numberProtoFuncToExponential(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* numberProtoFuncToPrecision(ExecState*, JSObject*, JSValue*, const ArgList&); +static JSValuePtr numberProtoFuncToString(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr numberProtoFuncToLocaleString(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr numberProtoFuncValueOf(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr numberProtoFuncToFixed(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr numberProtoFuncToExponential(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr numberProtoFuncToPrecision(ExecState*, JSObject*, JSValuePtr, const ArgList&); // ECMA 15.7.4 -NumberPrototype::NumberPrototype(ExecState* exec, PassRefPtr<StructureID> structure, StructureID* prototypeFunctionStructure) +NumberPrototype::NumberPrototype(ExecState* exec, PassRefPtr<Structure> structure, Structure* prototypeFunctionStructure) : NumberObject(structure) { setInternalValue(jsNumber(exec, 0)); @@ -67,7 +67,7 @@ static UString integerPartNoExp(double d) { int decimalPoint; int sign; - char* result = dtoa(d, 0, &decimalPoint, &sign, NULL); + char* result = WTF::dtoa(d, 0, &decimalPoint, &sign, NULL); bool resultIsInfOrNan = (decimalPoint == 9999); size_t length = strlen(result); @@ -89,7 +89,7 @@ static UString integerPartNoExp(double d) str.append(buf.data()); } - freedtoa(result); + WTF::freedtoa(result); return str; } @@ -133,15 +133,15 @@ static double intPow10(int e) return static_cast<double>(result); } -JSValue* numberProtoFuncToString(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) +JSValuePtr numberProtoFuncToString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) { - JSValue* v = thisValue->getJSNumber(); + JSValuePtr v = thisValue.getJSNumber(); if (!v) return throwError(exec, TypeError); - double radixAsDouble = args.at(exec, 0)->toInteger(exec); // nan -> 0 - if (radixAsDouble == 10 || args.at(exec, 0)->isUndefined()) - return jsString(exec, v->toString(exec)); + double radixAsDouble = args.at(exec, 0).toInteger(exec); // nan -> 0 + if (radixAsDouble == 10 || args.at(exec, 0).isUndefined()) + return jsString(exec, v.toString(exec)); if (radixAsDouble < 2 || radixAsDouble > 36) return throwError(exec, RangeError, "toString() radix argument must be between 2 and 36"); @@ -153,7 +153,7 @@ JSValue* numberProtoFuncToString(ExecState* exec, JSObject*, JSValue* thisValue, // unless someone finds a precise rule. char s[2048 + 3]; const char* lastCharInString = s + sizeof(s) - 1; - double x = v->uncheckedGetNumber(); + double x = v.uncheckedGetNumber(); if (isnan(x) || isinf(x)) return jsString(exec, UString::from(x)); @@ -197,39 +197,39 @@ JSValue* numberProtoFuncToString(ExecState* exec, JSObject*, JSValue* thisValue, return jsString(exec, startOfResultString); } -JSValue* numberProtoFuncToLocaleString(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&) +JSValuePtr numberProtoFuncToLocaleString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) { // FIXME: Not implemented yet. - JSValue* v = thisValue->getJSNumber(); + JSValuePtr v = thisValue.getJSNumber(); if (!v) return throwError(exec, TypeError); - return jsString(exec, v->toString(exec)); + return jsString(exec, v.toString(exec)); } -JSValue* numberProtoFuncValueOf(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&) +JSValuePtr numberProtoFuncValueOf(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) { - JSValue* v = thisValue->getJSNumber(); + JSValuePtr v = thisValue.getJSNumber(); if (!v) return throwError(exec, TypeError); return v; } -JSValue* numberProtoFuncToFixed(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) +JSValuePtr numberProtoFuncToFixed(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) { - JSValue* v = thisValue->getJSNumber(); + JSValuePtr v = thisValue.getJSNumber(); if (!v) return throwError(exec, TypeError); - JSValue* fractionDigits = args.at(exec, 0); - double df = fractionDigits->toInteger(exec); + JSValuePtr fractionDigits = args.at(exec, 0); + double df = fractionDigits.toInteger(exec); if (!(df >= 0 && df <= 20)) return throwError(exec, RangeError, "toFixed() digits argument must be between 0 and 20"); int f = static_cast<int>(df); - double x = v->uncheckedGetNumber(); + double x = v.uncheckedGetNumber(); if (isnan(x)) return jsNontrivialString(exec, "NaN"); @@ -302,23 +302,23 @@ static void exponentialPartToString(char* buf, int& i, int decimalPoint) buf[i++] = static_cast<char>('0' + exponential % 10); } -JSValue* numberProtoFuncToExponential(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) +JSValuePtr numberProtoFuncToExponential(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) { - JSValue* v = thisValue->getJSNumber(); + JSValuePtr v = thisValue.getJSNumber(); if (!v) return throwError(exec, TypeError); - double x = v->uncheckedGetNumber(); + double x = v.uncheckedGetNumber(); if (isnan(x) || isinf(x)) return jsString(exec, UString::from(x)); - JSValue* fractionalDigitsValue = args.at(exec, 0); - double df = fractionalDigitsValue->toInteger(exec); + JSValuePtr fractionalDigitsValue = args.at(exec, 0); + double df = fractionalDigitsValue.toInteger(exec); if (!(df >= 0 && df <= 20)) return throwError(exec, RangeError, "toExponential() argument must between 0 and 20"); int fractionalDigits = static_cast<int>(df); - bool includeAllDigits = fractionalDigitsValue->isUndefined(); + bool includeAllDigits = fractionalDigitsValue.isUndefined(); int decimalAdjust = 0; if (x && !includeAllDigits) { @@ -344,7 +344,7 @@ JSValue* numberProtoFuncToExponential(ExecState* exec, JSObject*, JSValue* thisV int decimalPoint; int sign; - char* result = dtoa(x, 0, &decimalPoint, &sign, NULL); + char* result = WTF::dtoa(x, 0, &decimalPoint, &sign, NULL); size_t resultLength = strlen(result); decimalPoint += decimalAdjust; @@ -367,21 +367,21 @@ JSValue* numberProtoFuncToExponential(ExecState* exec, JSObject*, JSValue* thisV } ASSERT(i <= 80); - freedtoa(result); + WTF::freedtoa(result); return jsString(exec, buf); } -JSValue* numberProtoFuncToPrecision(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) +JSValuePtr numberProtoFuncToPrecision(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) { - JSValue* v = thisValue->getJSNumber(); + JSValuePtr v = thisValue.getJSNumber(); if (!v) return throwError(exec, TypeError); - double doublePrecision = args.at(exec, 0)->toIntegerPreserveNaN(exec); - double x = v->uncheckedGetNumber(); - if (args.at(exec, 0)->isUndefined() || isnan(x) || isinf(x)) - return jsString(exec, v->toString(exec)); + double doublePrecision = args.at(exec, 0).toIntegerPreserveNaN(exec); + double x = v.uncheckedGetNumber(); + if (args.at(exec, 0).isUndefined() || isnan(x) || isinf(x)) + return jsString(exec, v.toString(exec)); UString s; if (x < 0) { diff --git a/JavaScriptCore/runtime/NumberPrototype.h b/JavaScriptCore/runtime/NumberPrototype.h index d70f260..0a3a544 100644 --- a/JavaScriptCore/runtime/NumberPrototype.h +++ b/JavaScriptCore/runtime/NumberPrototype.h @@ -27,7 +27,7 @@ namespace JSC { class NumberPrototype : public NumberObject { public: - NumberPrototype(ExecState*, PassRefPtr<StructureID>, StructureID* prototypeFunctionStructure); + NumberPrototype(ExecState*, PassRefPtr<Structure>, Structure* prototypeFunctionStructure); }; } // namespace JSC diff --git a/JavaScriptCore/runtime/ObjectConstructor.cpp b/JavaScriptCore/runtime/ObjectConstructor.cpp index 329816f..2d61127 100644 --- a/JavaScriptCore/runtime/ObjectConstructor.cpp +++ b/JavaScriptCore/runtime/ObjectConstructor.cpp @@ -28,7 +28,7 @@ namespace JSC { ASSERT_CLASS_FITS_IN_CELL(ObjectConstructor); -ObjectConstructor::ObjectConstructor(ExecState* exec, PassRefPtr<StructureID> structure, ObjectPrototype* objectPrototype) +ObjectConstructor::ObjectConstructor(ExecState* exec, PassRefPtr<Structure> structure, ObjectPrototype* objectPrototype) : InternalFunction(&exec->globalData(), structure, Identifier(exec, "Object")) { // ECMA 15.2.3.1 @@ -41,10 +41,10 @@ ObjectConstructor::ObjectConstructor(ExecState* exec, PassRefPtr<StructureID> st // ECMA 15.2.2 static ALWAYS_INLINE JSObject* constructObject(ExecState* exec, const ArgList& args) { - JSValue* arg = args.at(exec, 0); - if (arg->isUndefinedOrNull()) + JSValuePtr arg = args.at(exec, 0); + if (arg.isUndefinedOrNull()) return new (exec) JSObject(exec->lexicalGlobalObject()->emptyObjectStructure()); - return arg->toObject(exec); + return arg.toObject(exec); } static JSObject* constructWithObjectConstructor(ExecState* exec, JSObject*, const ArgList& args) @@ -58,7 +58,7 @@ ConstructType ObjectConstructor::getConstructData(ConstructData& constructData) return ConstructTypeHost; } -static JSValue* callObjectConstructor(ExecState* exec, JSObject*, JSValue*, const ArgList& args) +static JSValuePtr callObjectConstructor(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) { return constructObject(exec, args); } diff --git a/JavaScriptCore/runtime/ObjectConstructor.h b/JavaScriptCore/runtime/ObjectConstructor.h index c100424..f8c058a 100644 --- a/JavaScriptCore/runtime/ObjectConstructor.h +++ b/JavaScriptCore/runtime/ObjectConstructor.h @@ -29,7 +29,7 @@ namespace JSC { class ObjectConstructor : public InternalFunction { public: - ObjectConstructor(ExecState*, PassRefPtr<StructureID>, ObjectPrototype*); + ObjectConstructor(ExecState*, PassRefPtr<Structure>, ObjectPrototype*); private: virtual ConstructType getConstructData(ConstructData&); diff --git a/JavaScriptCore/runtime/ObjectPrototype.cpp b/JavaScriptCore/runtime/ObjectPrototype.cpp index 42a8063..4b776a7 100644 --- a/JavaScriptCore/runtime/ObjectPrototype.cpp +++ b/JavaScriptCore/runtime/ObjectPrototype.cpp @@ -29,17 +29,17 @@ namespace JSC { ASSERT_CLASS_FITS_IN_CELL(ObjectPrototype); -static JSValue* objectProtoFuncValueOf(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* objectProtoFuncHasOwnProperty(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* objectProtoFuncIsPrototypeOf(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* objectProtoFuncDefineGetter(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* objectProtoFuncDefineSetter(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* objectProtoFuncLookupGetter(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* objectProtoFuncLookupSetter(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* objectProtoFuncPropertyIsEnumerable(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* objectProtoFuncToLocaleString(ExecState*, JSObject*, JSValue*, const ArgList&); - -ObjectPrototype::ObjectPrototype(ExecState* exec, PassRefPtr<StructureID> stucture, StructureID* prototypeFunctionStructure) +static JSValuePtr objectProtoFuncValueOf(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr objectProtoFuncHasOwnProperty(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr objectProtoFuncIsPrototypeOf(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr objectProtoFuncDefineGetter(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr objectProtoFuncDefineSetter(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr objectProtoFuncLookupGetter(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr objectProtoFuncLookupSetter(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr objectProtoFuncPropertyIsEnumerable(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr objectProtoFuncToLocaleString(ExecState*, JSObject*, JSValuePtr, const ArgList&); + +ObjectPrototype::ObjectPrototype(ExecState* exec, PassRefPtr<Structure> stucture, Structure* prototypeFunctionStructure) : JSObject(stucture) { putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 0, exec->propertyNames().toString, objectProtoFuncToString), DontEnum); @@ -60,75 +60,75 @@ ObjectPrototype::ObjectPrototype(ExecState* exec, PassRefPtr<StructureID> stuctu // ECMA 15.2.4.2, 15.2.4.4, 15.2.4.5, 15.2.4.7 -JSValue* objectProtoFuncValueOf(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&) +JSValuePtr objectProtoFuncValueOf(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) { - return thisValue->toThisObject(exec); + return thisValue.toThisObject(exec); } -JSValue* objectProtoFuncHasOwnProperty(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) +JSValuePtr objectProtoFuncHasOwnProperty(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) { - return jsBoolean(thisValue->toThisObject(exec)->hasOwnProperty(exec, Identifier(exec, args.at(exec, 0)->toString(exec)))); + return jsBoolean(thisValue.toThisObject(exec)->hasOwnProperty(exec, Identifier(exec, args.at(exec, 0).toString(exec)))); } -JSValue* objectProtoFuncIsPrototypeOf(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) +JSValuePtr objectProtoFuncIsPrototypeOf(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) { - JSObject* thisObj = thisValue->toThisObject(exec); + JSObject* thisObj = thisValue.toThisObject(exec); - if (!args.at(exec, 0)->isObject()) + if (!args.at(exec, 0).isObject()) return jsBoolean(false); - JSValue* v = asObject(args.at(exec, 0))->prototype(); + JSValuePtr v = asObject(args.at(exec, 0))->prototype(); while (true) { - if (!v->isObject()) + if (!v.isObject()) return jsBoolean(false); - if (thisObj == v) + if (v == thisObj) return jsBoolean(true); v = asObject(v)->prototype(); } } -JSValue* objectProtoFuncDefineGetter(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) +JSValuePtr objectProtoFuncDefineGetter(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) { CallData callData; - if (args.at(exec, 1)->getCallData(callData) == CallTypeNone) + if (args.at(exec, 1).getCallData(callData) == CallTypeNone) return throwError(exec, SyntaxError, "invalid getter usage"); - thisValue->toThisObject(exec)->defineGetter(exec, Identifier(exec, args.at(exec, 0)->toString(exec)), asObject(args.at(exec, 1))); + thisValue.toThisObject(exec)->defineGetter(exec, Identifier(exec, args.at(exec, 0).toString(exec)), asObject(args.at(exec, 1))); return jsUndefined(); } -JSValue* objectProtoFuncDefineSetter(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) +JSValuePtr objectProtoFuncDefineSetter(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) { CallData callData; - if (args.at(exec, 1)->getCallData(callData) == CallTypeNone) + if (args.at(exec, 1).getCallData(callData) == CallTypeNone) return throwError(exec, SyntaxError, "invalid setter usage"); - thisValue->toThisObject(exec)->defineSetter(exec, Identifier(exec, args.at(exec, 0)->toString(exec)), asObject(args.at(exec, 1))); + thisValue.toThisObject(exec)->defineSetter(exec, Identifier(exec, args.at(exec, 0).toString(exec)), asObject(args.at(exec, 1))); return jsUndefined(); } -JSValue* objectProtoFuncLookupGetter(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) +JSValuePtr objectProtoFuncLookupGetter(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) { - return thisValue->toThisObject(exec)->lookupGetter(exec, Identifier(exec, args.at(exec, 0)->toString(exec))); + return thisValue.toThisObject(exec)->lookupGetter(exec, Identifier(exec, args.at(exec, 0).toString(exec))); } -JSValue* objectProtoFuncLookupSetter(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) +JSValuePtr objectProtoFuncLookupSetter(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) { - return thisValue->toThisObject(exec)->lookupSetter(exec, Identifier(exec, args.at(exec, 0)->toString(exec))); + return thisValue.toThisObject(exec)->lookupSetter(exec, Identifier(exec, args.at(exec, 0).toString(exec))); } -JSValue* objectProtoFuncPropertyIsEnumerable(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) +JSValuePtr objectProtoFuncPropertyIsEnumerable(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) { - return jsBoolean(thisValue->toThisObject(exec)->propertyIsEnumerable(exec, Identifier(exec, args.at(exec, 0)->toString(exec)))); + return jsBoolean(thisValue.toThisObject(exec)->propertyIsEnumerable(exec, Identifier(exec, args.at(exec, 0).toString(exec)))); } -JSValue* objectProtoFuncToLocaleString(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&) +JSValuePtr objectProtoFuncToLocaleString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) { - return thisValue->toThisJSString(exec); + return thisValue.toThisJSString(exec); } -JSValue* objectProtoFuncToString(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&) +JSValuePtr objectProtoFuncToString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) { - return jsNontrivialString(exec, "[object " + thisValue->toThisObject(exec)->className() + "]"); + return jsNontrivialString(exec, "[object " + thisValue.toThisObject(exec)->className() + "]"); } } // namespace JSC diff --git a/JavaScriptCore/runtime/ObjectPrototype.h b/JavaScriptCore/runtime/ObjectPrototype.h index aefdf95..1c432fe 100644 --- a/JavaScriptCore/runtime/ObjectPrototype.h +++ b/JavaScriptCore/runtime/ObjectPrototype.h @@ -27,10 +27,10 @@ namespace JSC { class ObjectPrototype : public JSObject { public: - ObjectPrototype(ExecState*, PassRefPtr<StructureID>, StructureID* prototypeFunctionStructure); + ObjectPrototype(ExecState*, PassRefPtr<Structure>, Structure* prototypeFunctionStructure); }; - JSValue* objectProtoFuncToString(ExecState*, JSObject*, JSValue*, const ArgList&); + JSValuePtr objectProtoFuncToString(ExecState*, JSObject*, JSValuePtr, const ArgList&); } // namespace JSC diff --git a/JavaScriptCore/kjs/operations.cpp b/JavaScriptCore/runtime/Operations.cpp index f2d8deb..550d3f6 100644 --- a/JavaScriptCore/kjs/operations.cpp +++ b/JavaScriptCore/runtime/Operations.cpp @@ -20,7 +20,7 @@ */ #include "config.h" -#include "operations.h" +#include "Operations.h" #include "Error.h" #include "JSObject.h" @@ -35,37 +35,17 @@ namespace JSC { -// ECMA 11.9.3 -bool equal(ExecState* exec, JSValue* v1, JSValue* v2) -{ - if (JSImmediate::areBothImmediateNumbers(v1, v2)) - return v1 == v2; - - return equalSlowCaseInline(exec, v1, v2); -} - -bool equalSlowCase(ExecState* exec, JSValue* v1, JSValue* v2) +bool JSValuePtr::equalSlowCase(ExecState* exec, JSValuePtr v1, JSValuePtr v2) { return equalSlowCaseInline(exec, v1, v2); } -bool strictEqual(JSValue* v1, JSValue* v2) -{ - if (JSImmediate::areBothImmediate(v1, v2)) - return v1 == v2; - - if (JSImmediate::isEitherImmediate(v1, v2) & (v1 != JSImmediate::from(0)) & (v2 != JSImmediate::from(0))) - return false; - - return strictEqualSlowCaseInline(v1, v2); -} - -bool strictEqualSlowCase(JSValue* v1, JSValue* v2) +bool JSValuePtr::strictEqualSlowCase(JSValuePtr v1, JSValuePtr v2) { return strictEqualSlowCaseInline(v1, v2); } -NEVER_INLINE JSValue* throwOutOfMemoryError(ExecState* exec) +NEVER_INLINE JSValuePtr throwOutOfMemoryError(ExecState* exec) { JSObject* error = Error::create(exec, GeneralError, "Out of memory"); exec->setException(error); diff --git a/JavaScriptCore/runtime/Operations.h b/JavaScriptCore/runtime/Operations.h new file mode 100644 index 0000000..c6a7e7a --- /dev/null +++ b/JavaScriptCore/runtime/Operations.h @@ -0,0 +1,135 @@ +/* + * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) + * Copyright (C) 2002, 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 Operations_h +#define Operations_h + +#include "JSImmediate.h" +#include "JSNumberCell.h" +#include "JSString.h" + +namespace JSC { + + // ECMA 11.9.3 + inline bool JSValuePtr::equal(ExecState* exec, JSValuePtr v1, JSValuePtr v2) + { + if (JSImmediate::areBothImmediateIntegerNumbers(v1, v2)) + return v1 == v2; + + return equalSlowCase(exec, v1, v2); + } + + ALWAYS_INLINE bool JSValuePtr::equalSlowCaseInline(ExecState* exec, JSValuePtr v1, JSValuePtr v2) + { + ASSERT(!JSImmediate::areBothImmediateIntegerNumbers(v1, v2)); + + do { + if (v1.isNumber() && v2.isNumber()) + return v1.uncheckedGetNumber() == v2.uncheckedGetNumber(); + + bool s1 = v1.isString(); + bool s2 = v2.isString(); + if (s1 && s2) + return asString(v1)->value() == asString(v2)->value(); + + if (v1.isUndefinedOrNull()) { + if (v2.isUndefinedOrNull()) + return true; + if (JSImmediate::isImmediate(v2)) + return false; + return v2.asCell()->structure()->typeInfo().masqueradesAsUndefined(); + } + + if (v2.isUndefinedOrNull()) { + if (JSImmediate::isImmediate(v1)) + return false; + return v1.asCell()->structure()->typeInfo().masqueradesAsUndefined(); + } + + if (v1.isObject()) { + if (v2.isObject()) + return v1 == v2; + JSValuePtr p1 = v1.toPrimitive(exec); + if (exec->hadException()) + return false; + v1 = p1; + if (JSImmediate::areBothImmediateIntegerNumbers(v1, v2)) + return v1 == v2; + continue; + } + + if (v2.isObject()) { + JSValuePtr p2 = v2.toPrimitive(exec); + if (exec->hadException()) + return false; + v2 = p2; + if (JSImmediate::areBothImmediateIntegerNumbers(v1, v2)) + return v1 == v2; + continue; + } + + if (s1 || s2) { + double d1 = v1.toNumber(exec); + double d2 = v2.toNumber(exec); + return d1 == d2; + } + + if (v1.isBoolean()) { + if (v2.isNumber()) + return static_cast<double>(v1.getBoolean()) == v2.uncheckedGetNumber(); + } else if (v2.isBoolean()) { + if (v1.isNumber()) + return v1.uncheckedGetNumber() == static_cast<double>(v2.getBoolean()); + } + + return v1 == v2; + } while (true); + } + + // ECMA 11.9.3 + inline bool JSValuePtr::strictEqual(JSValuePtr v1, JSValuePtr v2) + { + if (JSImmediate::areBothImmediateIntegerNumbers(v1, v2)) + return v1 == v2; + + if (v1.isNumber() && v2.isNumber()) + return v1.uncheckedGetNumber() == v2.uncheckedGetNumber(); + + if (JSImmediate::isEitherImmediate(v1, v2)) + return v1 == v2; + + return strictEqualSlowCase(v1, v2); + } + + ALWAYS_INLINE bool JSValuePtr::strictEqualSlowCaseInline(JSValuePtr v1, JSValuePtr v2) + { + ASSERT(!JSImmediate::isEitherImmediate(v1, v2)); + + if (v1.asCell()->isString() && v2.asCell()->isString()) + return asString(v1)->value() == asString(v2)->value(); + + return v1 == v2; + } + + JSValuePtr throwOutOfMemoryError(ExecState*); + +} +#endif diff --git a/JavaScriptCore/runtime/PropertyMapHashTable.h b/JavaScriptCore/runtime/PropertyMapHashTable.h index 98b0727..935df68 100644 --- a/JavaScriptCore/runtime/PropertyMapHashTable.h +++ b/JavaScriptCore/runtime/PropertyMapHashTable.h @@ -21,7 +21,8 @@ #ifndef PropertyMapHashTable_h #define PropertyMapHashTable_h -#include "ustring.h" +#include "UString.h" +#include <wtf/Vector.h> namespace JSC { @@ -31,13 +32,21 @@ namespace JSC { unsigned attributes; unsigned index; - PropertyMapEntry(UString::Rep* k, int a) - : key(k) + PropertyMapEntry(UString::Rep* key, unsigned attributes) + : key(key) , offset(0) - , attributes(a) + , attributes(attributes) , index(0) { } + + PropertyMapEntry(UString::Rep* key, unsigned offset, unsigned attributes, unsigned index) + : key(key) + , offset(offset) + , attributes(attributes) + , index(index) + { + } }; // lastIndexUsed is an ever-increasing index used to identify the order items @@ -50,6 +59,7 @@ namespace JSC { unsigned keyCount; unsigned deletedSentinelCount; unsigned lastIndexUsed; + Vector<unsigned>* deletedOffsets; unsigned entryIndices[1]; PropertyMapEntry* entries() diff --git a/JavaScriptCore/runtime/PropertyNameArray.cpp b/JavaScriptCore/runtime/PropertyNameArray.cpp index 47e9d84..0878e73 100644 --- a/JavaScriptCore/runtime/PropertyNameArray.cpp +++ b/JavaScriptCore/runtime/PropertyNameArray.cpp @@ -27,7 +27,7 @@ static const size_t setThreshold = 20; void PropertyNameArray::add(UString::Rep* identifier) { - ASSERT(identifier == &UString::Rep::null || identifier == &UString::Rep::empty || identifier->identifierTable()); + ASSERT(identifier == &UString::Rep::null() || identifier == &UString::Rep::empty() || identifier->identifierTable()); size_t size = m_data->propertyNameVector().size(); if (size < setThreshold) { diff --git a/JavaScriptCore/runtime/PropertyNameArray.h b/JavaScriptCore/runtime/PropertyNameArray.h index d19c2e5..7dc14fe 100644 --- a/JavaScriptCore/runtime/PropertyNameArray.h +++ b/JavaScriptCore/runtime/PropertyNameArray.h @@ -21,9 +21,9 @@ #ifndef PropertyNameArray_h #define PropertyNameArray_h -#include "ExecState.h" -#include "StructureID.h" -#include "identifier.h" +#include "CallFrame.h" +#include "Identifier.h" +#include "Structure.h" #include <wtf/HashSet.h> #include <wtf/Vector.h> @@ -41,21 +41,21 @@ namespace JSC { PropertyNameVector& propertyNameVector() { return m_propertyNameVector; } - void setCachedStructureID(StructureID* structureID) { m_cachedStructureID = structureID; } - StructureID* cachedStructureID() const { return m_cachedStructureID; } + void setCachedStructure(Structure* structure) { m_cachedStructure = structure; } + Structure* cachedStructure() const { return m_cachedStructure; } - void setCachedPrototypeChain(PassRefPtr<StructureIDChain> cachedPrototypeChain) { m_cachedPrototypeChain = cachedPrototypeChain; } - StructureIDChain* cachedPrototypeChain() { return m_cachedPrototypeChain.get(); } + void setCachedPrototypeChain(PassRefPtr<StructureChain> cachedPrototypeChain) { m_cachedPrototypeChain = cachedPrototypeChain; } + StructureChain* cachedPrototypeChain() { return m_cachedPrototypeChain.get(); } private: PropertyNameArrayData() - : m_cachedStructureID(0) + : m_cachedStructure(0) { } PropertyNameVector m_propertyNameVector; - StructureID* m_cachedStructureID; - RefPtr<StructureIDChain> m_cachedPrototypeChain; + Structure* m_cachedStructure; + RefPtr<StructureChain> m_cachedPrototypeChain; }; class PropertyNameArray { diff --git a/JavaScriptCore/runtime/PropertySlot.cpp b/JavaScriptCore/runtime/PropertySlot.cpp index 37df83a..175f271 100644 --- a/JavaScriptCore/runtime/PropertySlot.cpp +++ b/JavaScriptCore/runtime/PropertySlot.cpp @@ -27,7 +27,7 @@ namespace JSC { -JSValue* PropertySlot::functionGetter(ExecState* exec, const Identifier&, const PropertySlot& slot) +JSValuePtr PropertySlot::functionGetter(ExecState* exec, const Identifier&, const PropertySlot& slot) { // Prevent getter functions from observing execution if an exception is pending. if (exec->hadException()) diff --git a/JavaScriptCore/runtime/PropertySlot.h b/JavaScriptCore/runtime/PropertySlot.h index 29c19d4..1dd1afa 100644 --- a/JavaScriptCore/runtime/PropertySlot.h +++ b/JavaScriptCore/runtime/PropertySlot.h @@ -21,9 +21,10 @@ #ifndef PropertySlot_h #define PropertySlot_h -#include "Register.h" +#include "Identifier.h" #include "JSValue.h" -#include "identifier.h" +#include "JSImmediate.h" +#include "Register.h" #include <wtf/Assertions.h> #include <wtf/NotFound.h> @@ -44,16 +45,16 @@ namespace JSC { clearValue(); } - explicit PropertySlot(const JSValue* base) - : m_slotBase(const_cast<JSValue*>(base)) + explicit PropertySlot(const JSValuePtr base) + : m_slotBase(base) , m_offset(WTF::notFound) { clearValue(); } - typedef JSValue* (*GetValueFunc)(ExecState*, const Identifier&, const PropertySlot&); + typedef JSValuePtr (*GetValueFunc)(ExecState*, const Identifier&, const PropertySlot&); - JSValue* getValue(ExecState* exec, const Identifier& propertyName) const + JSValuePtr getValue(ExecState* exec, const Identifier& propertyName) const { if (m_getValue == JSC_VALUE_SLOT_MARKER) return *m_data.valueSlot; @@ -62,7 +63,7 @@ namespace JSC { return m_getValue(exec, propertyName, *this); } - JSValue* getValue(ExecState* exec, unsigned propertyName) const + JSValuePtr getValue(ExecState* exec, unsigned propertyName) const { if (m_getValue == JSC_VALUE_SLOT_MARKER) return *m_data.valueSlot; @@ -78,17 +79,17 @@ namespace JSC { return m_offset; } - void putValue(JSValue* value) + void putValue(JSValuePtr value) { if (m_getValue == JSC_VALUE_SLOT_MARKER) { *m_data.valueSlot = value; return; } ASSERT(m_getValue == JSC_REGISTER_SLOT_MARKER); - *m_data.registerSlot = value; + *m_data.registerSlot = JSValuePtr(value); } - void setValueSlot(JSValue** valueSlot) + void setValueSlot(JSValuePtr* valueSlot) { ASSERT(valueSlot); m_getValue = JSC_VALUE_SLOT_MARKER; @@ -96,7 +97,7 @@ namespace JSC { m_data.valueSlot = valueSlot; } - void setValueSlot(JSValue* slotBase, JSValue** valueSlot) + void setValueSlot(JSValuePtr slotBase, JSValuePtr* valueSlot) { ASSERT(valueSlot); m_getValue = JSC_VALUE_SLOT_MARKER; @@ -104,7 +105,7 @@ namespace JSC { m_data.valueSlot = valueSlot; } - void setValueSlot(JSValue* slotBase, JSValue** valueSlot, size_t offset) + void setValueSlot(JSValuePtr slotBase, JSValuePtr* valueSlot, size_t offset) { ASSERT(valueSlot); m_getValue = JSC_VALUE_SLOT_MARKER; @@ -113,7 +114,7 @@ namespace JSC { m_offset = offset; } - void setValue(JSValue* value) + void setValue(JSValuePtr value) { ASSERT(value); m_getValue = JSC_VALUE_SLOT_MARKER; @@ -130,7 +131,7 @@ namespace JSC { m_data.registerSlot = registerSlot; } - void setCustom(JSValue* slotBase, GetValueFunc getValue) + void setCustom(JSValuePtr slotBase, GetValueFunc getValue) { ASSERT(slotBase); ASSERT(getValue); @@ -138,7 +139,7 @@ namespace JSC { m_slotBase = slotBase; } - void setCustomIndex(JSValue* slotBase, unsigned index, GetValueFunc getValue) + void setCustomIndex(JSValuePtr slotBase, unsigned index, GetValueFunc getValue) { ASSERT(slotBase); ASSERT(getValue); @@ -160,13 +161,13 @@ namespace JSC { setValue(jsUndefined()); } - JSValue* slotBase() const + JSValuePtr slotBase() const { ASSERT(m_slotBase); return m_slotBase; } - void setBase(JSValue* base) + void setBase(JSValuePtr base) { ASSERT(m_slotBase); ASSERT(base); @@ -190,19 +191,19 @@ namespace JSC { unsigned index() const { return m_data.index; } private: - static JSValue* functionGetter(ExecState*, const Identifier&, const PropertySlot&); + static JSValuePtr functionGetter(ExecState*, const Identifier&, const PropertySlot&); GetValueFunc m_getValue; - JSValue* m_slotBase; + JSValuePtr m_slotBase; union { JSObject* getterFunc; - JSValue** valueSlot; + JSValuePtr* valueSlot; Register* registerSlot; unsigned index; } m_data; - JSValue* m_value; + JSValuePtr m_value; size_t m_offset; }; diff --git a/JavaScriptCore/runtime/Protect.h b/JavaScriptCore/runtime/Protect.h new file mode 100644 index 0000000..c7f6b2d --- /dev/null +++ b/JavaScriptCore/runtime/Protect.h @@ -0,0 +1,215 @@ +/* + * Copyright (C) 2004, 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 Protect_h +#define Protect_h + +#include "JSCell.h" +#include "Collector.h" + +namespace JSC { + + inline void gcProtect(JSCell* val) + { + Heap::heap(val)->protect(val); + } + + inline void gcUnprotect(JSCell* val) + { + Heap::heap(val)->unprotect(val); + } + + inline void gcProtectNullTolerant(JSCell* val) + { + if (val) + gcProtect(val); + } + + inline void gcUnprotectNullTolerant(JSCell* val) + { + if (val) + gcUnprotect(val); + } + + inline void gcProtect(JSValuePtr value) + { + if (value && value.isCell()) + gcProtect(asCell(value)); + } + + inline void gcUnprotect(JSValuePtr value) + { + if (value && value.isCell()) + gcUnprotect(asCell(value)); + } + + // FIXME: Share more code with RefPtr template? The only differences are the ref/deref operation + // and the implicit conversion to raw pointer + template <class T> class ProtectedPtr { + public: + ProtectedPtr() : m_ptr(0) {} + ProtectedPtr(T* ptr); + ProtectedPtr(const ProtectedPtr&); + ~ProtectedPtr(); + + template <class U> ProtectedPtr(const ProtectedPtr<U>&); + + T* get() const { return m_ptr; } + operator T*() const { return m_ptr; } + operator JSValuePtr() const { return JSValuePtr(m_ptr); } + T* operator->() const { return m_ptr; } + + operator bool() const { return m_ptr; } + bool operator!() const { return !m_ptr; } + + ProtectedPtr& operator=(const ProtectedPtr&); + ProtectedPtr& operator=(T*); + + private: + T* m_ptr; + }; + + class ProtectedJSValuePtr { + public: + ProtectedJSValuePtr() {} + ProtectedJSValuePtr(JSValuePtr value); + ProtectedJSValuePtr(const ProtectedJSValuePtr&); + ~ProtectedJSValuePtr(); + + template <class U> ProtectedJSValuePtr(const ProtectedPtr<U>&); + + JSValuePtr get() const { return m_value; } + operator JSValuePtr() const { return m_value; } + JSValuePtr operator->() const { return m_value; } + + operator bool() const { return m_value; } + bool operator!() const { return !m_value; } + + ProtectedJSValuePtr& operator=(const ProtectedJSValuePtr&); + ProtectedJSValuePtr& operator=(JSValuePtr); + + private: + JSValuePtr m_value; + }; + + template <class T> inline ProtectedPtr<T>::ProtectedPtr(T* ptr) + : m_ptr(ptr) + { + gcProtectNullTolerant(m_ptr); + } + + template <class T> inline ProtectedPtr<T>::ProtectedPtr(const ProtectedPtr& o) + : m_ptr(o.get()) + { + gcProtectNullTolerant(m_ptr); + } + + template <class T> inline ProtectedPtr<T>::~ProtectedPtr() + { + gcUnprotectNullTolerant(m_ptr); + } + + template <class T> template <class U> inline ProtectedPtr<T>::ProtectedPtr(const ProtectedPtr<U>& o) + : m_ptr(o.get()) + { + gcProtectNullTolerant(m_ptr); + } + + template <class T> inline ProtectedPtr<T>& ProtectedPtr<T>::operator=(const ProtectedPtr<T>& o) + { + T* optr = o.m_ptr; + gcProtectNullTolerant(optr); + gcUnprotectNullTolerant(m_ptr); + m_ptr = optr; + return *this; + } + + template <class T> inline ProtectedPtr<T>& ProtectedPtr<T>::operator=(T* optr) + { + gcProtectNullTolerant(optr); + gcUnprotectNullTolerant(m_ptr); + m_ptr = optr; + return *this; + } + + inline ProtectedJSValuePtr::ProtectedJSValuePtr(JSValuePtr value) + : m_value(value) + { + gcProtect(m_value); + } + + inline ProtectedJSValuePtr::ProtectedJSValuePtr(const ProtectedJSValuePtr& o) + : m_value(o.get()) + { + gcProtect(m_value); + } + + inline ProtectedJSValuePtr::~ProtectedJSValuePtr() + { + gcUnprotect(m_value); + } + + template <class U> ProtectedJSValuePtr::ProtectedJSValuePtr(const ProtectedPtr<U>& o) + : m_value(o.get()) + { + gcProtect(m_value); + } + + inline ProtectedJSValuePtr& ProtectedJSValuePtr::operator=(const ProtectedJSValuePtr& o) + { + JSValuePtr ovalue = o.m_value; + gcProtect(ovalue); + gcUnprotect(m_value); + m_value = ovalue; + return *this; + } + + inline ProtectedJSValuePtr& ProtectedJSValuePtr::operator=(JSValuePtr ovalue) + { + gcProtect(ovalue); + gcUnprotect(m_value); + m_value = ovalue; + return *this; + } + + template <class T> inline bool operator==(const ProtectedPtr<T>& a, const ProtectedPtr<T>& b) { return a.get() == b.get(); } + template <class T> inline bool operator==(const ProtectedPtr<T>& a, const T* b) { return a.get() == b; } + template <class T> inline bool operator==(const T* a, const ProtectedPtr<T>& b) { return a == b.get(); } + + template <class T> inline bool operator!=(const ProtectedPtr<T>& a, const ProtectedPtr<T>& b) { return a.get() != b.get(); } + template <class T> inline bool operator!=(const ProtectedPtr<T>& a, const T* b) { return a.get() != b; } + template <class T> inline bool operator!=(const T* a, const ProtectedPtr<T>& b) { return a != b.get(); } + + inline bool operator==(const ProtectedJSValuePtr& a, const ProtectedJSValuePtr& b) { return a.get() == b.get(); } + inline bool operator==(const ProtectedJSValuePtr& a, const JSValuePtr b) { return a.get() == b; } + template <class T> inline bool operator==(const ProtectedJSValuePtr& a, const ProtectedPtr<T>& b) { return a.get() == JSValuePtr(b.get()); } + inline bool operator==(const JSValuePtr a, const ProtectedJSValuePtr& b) { return a == b.get(); } + template <class T> inline bool operator==(const ProtectedPtr<T>& a, const ProtectedJSValuePtr& b) { return JSValuePtr(a.get()) == b.get(); } + + inline bool operator!=(const ProtectedJSValuePtr& a, const ProtectedJSValuePtr& b) { return a.get() != b.get(); } + inline bool operator!=(const ProtectedJSValuePtr& a, const JSValuePtr b) { return a.get() != b; } + template <class T> inline bool operator!=(const ProtectedJSValuePtr& a, const ProtectedPtr<T>& b) { return a.get() != JSValuePtr(b.get()); } + inline bool operator!=(const JSValuePtr a, const ProtectedJSValuePtr& b) { return a != b.get(); } + template <class T> inline bool operator!=(const ProtectedPtr<T>& a, const ProtectedJSValuePtr& b) { return JSValuePtr(a.get()) != b.get(); } + +} // namespace JSC + +#endif // Protect_h diff --git a/JavaScriptCore/runtime/PrototypeFunction.cpp b/JavaScriptCore/runtime/PrototypeFunction.cpp index 8afe6a4..8e3d107 100644 --- a/JavaScriptCore/runtime/PrototypeFunction.cpp +++ b/JavaScriptCore/runtime/PrototypeFunction.cpp @@ -40,7 +40,7 @@ PrototypeFunction::PrototypeFunction(ExecState* exec, int length, const Identifi putDirect(exec->propertyNames().length, jsNumber(exec, length), DontDelete | ReadOnly | DontEnum); } -PrototypeFunction::PrototypeFunction(ExecState* exec, PassRefPtr<StructureID> prototypeFunctionStructure, int length, const Identifier& name, NativeFunction function) +PrototypeFunction::PrototypeFunction(ExecState* exec, PassRefPtr<Structure> prototypeFunctionStructure, int length, const Identifier& name, NativeFunction function) : InternalFunction(&exec->globalData(), prototypeFunctionStructure, name) , m_function(function) { diff --git a/JavaScriptCore/runtime/PrototypeFunction.h b/JavaScriptCore/runtime/PrototypeFunction.h index 1592995..99ab327 100644 --- a/JavaScriptCore/runtime/PrototypeFunction.h +++ b/JavaScriptCore/runtime/PrototypeFunction.h @@ -32,7 +32,7 @@ namespace JSC { class PrototypeFunction : public InternalFunction { public: PrototypeFunction(ExecState*, int length, const Identifier&, NativeFunction); - PrototypeFunction(ExecState*, PassRefPtr<StructureID>, int length, const Identifier&, NativeFunction); + PrototypeFunction(ExecState*, PassRefPtr<Structure>, int length, const Identifier&, NativeFunction); private: virtual CallType getCallData(CallData&); diff --git a/JavaScriptCore/kjs/regexp.cpp b/JavaScriptCore/runtime/RegExp.cpp index 7397232..b8251d2 100644 --- a/JavaScriptCore/kjs/regexp.cpp +++ b/JavaScriptCore/runtime/RegExp.cpp @@ -19,20 +19,24 @@ */ #include "config.h" -#include "regexp.h" +#include "RegExp.h" -#include "CTI.h" -#include "lexer.h" +#include "JIT.h" +#include "Lexer.h" +#include "WRECGenerator.h" #include <pcre/pcre.h> #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <wrec/WREC.h> #include <wtf/Assertions.h> #include <wtf/OwnArrayPtr.h> namespace JSC { +#if ENABLE(WREC) +using namespace WREC; +#endif + inline RegExp::RegExp(JSGlobalData* globalData, const UString& pattern) : m_pattern(pattern) , m_flagBits(0) @@ -41,8 +45,8 @@ inline RegExp::RegExp(JSGlobalData* globalData, const UString& pattern) , m_numSubpatterns(0) { #if ENABLE(WREC) - m_wrecFunction = CTI::compileRegExp(globalData->machine, pattern, &m_numSubpatterns, &m_constructionError); - if (m_wrecFunction) + m_wrecFunction = Generator::compileRegExp(globalData, pattern, &m_numSubpatterns, &m_constructionError, m_executablePool); + if (m_wrecFunction || m_constructionError) return; // Fall through to non-WREC case. #else @@ -84,8 +88,8 @@ inline RegExp::RegExp(JSGlobalData* globalData, const UString& pattern, const US } #if ENABLE(WREC) - m_wrecFunction = CTI::compileRegExp(globalData->machine, pattern, &m_numSubpatterns, &m_constructionError, (m_flagBits & IgnoreCase), (m_flagBits & Multiline)); - if (m_wrecFunction) + m_wrecFunction = Generator::compileRegExp(globalData, pattern, &m_numSubpatterns, &m_constructionError, m_executablePool, (m_flagBits & IgnoreCase), (m_flagBits & Multiline)); + if (m_wrecFunction || m_constructionError) return; // Fall through to non-WREC case. #else @@ -103,20 +107,16 @@ PassRefPtr<RegExp> RegExp::create(JSGlobalData* globalData, const UString& patte RegExp::~RegExp() { jsRegExpFree(m_regExp); -#if ENABLE(WREC) - if (m_wrecFunction) - WTF::fastFreeExecutable(m_wrecFunction); -#endif } -int RegExp::match(const UString& s, int i, OwnArrayPtr<int>* ovector) +int RegExp::match(const UString& s, int startOffset, OwnArrayPtr<int>* ovector) { - if (i < 0) - i = 0; + if (startOffset < 0) + startOffset = 0; if (ovector) ovector->clear(); - if (i > s.size() || s.isNull()) + if (startOffset > s.size() || s.isNull()) return -1; #if ENABLE(WREC) @@ -132,7 +132,7 @@ int RegExp::match(const UString& s, int i, OwnArrayPtr<int>* ovector) else ovector->set(offsetVector); - int result = reinterpret_cast<WRECFunction>(m_wrecFunction)(s.data(), i, s.size(), offsetVector); + int result = m_wrecFunction(s.data(), startOffset, s.size(), offsetVector); if (result < 0) { #ifndef NDEBUG @@ -161,7 +161,7 @@ int RegExp::match(const UString& s, int i, OwnArrayPtr<int>* ovector) ovector->set(offsetVector); } - int numMatches = jsRegExpExecute(m_regExp, reinterpret_cast<const UChar*>(s.data()), s.size(), i, offsetVector, offsetVectorSize); + int numMatches = jsRegExpExecute(m_regExp, reinterpret_cast<const UChar*>(s.data()), s.size(), startOffset, offsetVector, offsetVectorSize); if (numMatches < 0) { #ifndef NDEBUG diff --git a/JavaScriptCore/kjs/regexp.h b/JavaScriptCore/runtime/RegExp.h index 1842d94..139c754 100644 --- a/JavaScriptCore/kjs/regexp.h +++ b/JavaScriptCore/runtime/RegExp.h @@ -1,6 +1,6 @@ /* * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) - * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 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 Lesser General Public @@ -18,10 +18,12 @@ * */ -#ifndef KJS_REGEXP_H -#define KJS_REGEXP_H +#ifndef RegExp_h +#define RegExp_h -#include "ustring.h" +#include "UString.h" +#include "WREC.h" +#include "ExecutableAllocator.h" #include <wtf/Forward.h> #include <wtf/RefCounted.h> @@ -33,8 +35,8 @@ namespace JSC { class RegExp : public RefCounted<RegExp> { public: - static PassRefPtr<RegExp> create(JSGlobalData*, const UString& pattern); - static PassRefPtr<RegExp> create(JSGlobalData*, const UString& pattern, const UString& flags); + static PassRefPtr<RegExp> create(JSGlobalData* globalData, const UString& pattern); + static PassRefPtr<RegExp> create(JSGlobalData* globalData, const UString& pattern, const UString& flags); ~RegExp(); bool global() const { return m_flagBits & Global; } @@ -47,12 +49,12 @@ namespace JSC { bool isValid() const { return !m_constructionError; } const char* errorMessage() const { return m_constructionError; } - int match(const UString&, int offset, OwnArrayPtr<int>* ovector = 0); + int match(const UString&, int startOffset, OwnArrayPtr<int>* ovector = 0); unsigned numSubpatterns() const { return m_numSubpatterns; } private: - RegExp(JSGlobalData*, const UString& pattern); - RegExp(JSGlobalData*, const UString& pattern, const UString& flags); + RegExp(JSGlobalData* globalData, const UString& pattern); + RegExp(JSGlobalData* globalData, const UString& pattern, const UString& flags); void compile(); @@ -66,11 +68,11 @@ namespace JSC { unsigned m_numSubpatterns; #if ENABLE(WREC) - // Called as a WRECFunction - void* m_wrecFunction; + WREC::CompiledRegExp m_wrecFunction; + RefPtr<ExecutablePool> m_executablePool; #endif }; } // namespace JSC -#endif // KJS_REGEXP_H +#endif // RegExp_h diff --git a/JavaScriptCore/runtime/RegExpConstructor.cpp b/JavaScriptCore/runtime/RegExpConstructor.cpp index 4c4db39..bff51e0 100644 --- a/JavaScriptCore/runtime/RegExpConstructor.cpp +++ b/JavaScriptCore/runtime/RegExpConstructor.cpp @@ -29,28 +29,28 @@ #include "RegExpMatchesArray.h" #include "RegExpObject.h" #include "RegExpPrototype.h" -#include "regexp.h" +#include "RegExp.h" namespace JSC { -static JSValue* regExpConstructorInput(ExecState*, const Identifier&, const PropertySlot&); -static JSValue* regExpConstructorMultiline(ExecState*, const Identifier&, const PropertySlot&); -static JSValue* regExpConstructorLastMatch(ExecState*, const Identifier&, const PropertySlot&); -static JSValue* regExpConstructorLastParen(ExecState*, const Identifier&, const PropertySlot&); -static JSValue* regExpConstructorLeftContext(ExecState*, const Identifier&, const PropertySlot&); -static JSValue* regExpConstructorRightContext(ExecState*, const Identifier&, const PropertySlot&); -static JSValue* regExpConstructorDollar1(ExecState*, const Identifier&, const PropertySlot&); -static JSValue* regExpConstructorDollar2(ExecState*, const Identifier&, const PropertySlot&); -static JSValue* regExpConstructorDollar3(ExecState*, const Identifier&, const PropertySlot&); -static JSValue* regExpConstructorDollar4(ExecState*, const Identifier&, const PropertySlot&); -static JSValue* regExpConstructorDollar5(ExecState*, const Identifier&, const PropertySlot&); -static JSValue* regExpConstructorDollar6(ExecState*, const Identifier&, const PropertySlot&); -static JSValue* regExpConstructorDollar7(ExecState*, const Identifier&, const PropertySlot&); -static JSValue* regExpConstructorDollar8(ExecState*, const Identifier&, const PropertySlot&); -static JSValue* regExpConstructorDollar9(ExecState*, const Identifier&, const PropertySlot&); - -static void setRegExpConstructorInput(ExecState*, JSObject*, JSValue*); -static void setRegExpConstructorMultiline(ExecState*, JSObject*, JSValue*); +static JSValuePtr regExpConstructorInput(ExecState*, const Identifier&, const PropertySlot&); +static JSValuePtr regExpConstructorMultiline(ExecState*, const Identifier&, const PropertySlot&); +static JSValuePtr regExpConstructorLastMatch(ExecState*, const Identifier&, const PropertySlot&); +static JSValuePtr regExpConstructorLastParen(ExecState*, const Identifier&, const PropertySlot&); +static JSValuePtr regExpConstructorLeftContext(ExecState*, const Identifier&, const PropertySlot&); +static JSValuePtr regExpConstructorRightContext(ExecState*, const Identifier&, const PropertySlot&); +static JSValuePtr regExpConstructorDollar1(ExecState*, const Identifier&, const PropertySlot&); +static JSValuePtr regExpConstructorDollar2(ExecState*, const Identifier&, const PropertySlot&); +static JSValuePtr regExpConstructorDollar3(ExecState*, const Identifier&, const PropertySlot&); +static JSValuePtr regExpConstructorDollar4(ExecState*, const Identifier&, const PropertySlot&); +static JSValuePtr regExpConstructorDollar5(ExecState*, const Identifier&, const PropertySlot&); +static JSValuePtr regExpConstructorDollar6(ExecState*, const Identifier&, const PropertySlot&); +static JSValuePtr regExpConstructorDollar7(ExecState*, const Identifier&, const PropertySlot&); +static JSValuePtr regExpConstructorDollar8(ExecState*, const Identifier&, const PropertySlot&); +static JSValuePtr regExpConstructorDollar9(ExecState*, const Identifier&, const PropertySlot&); + +static void setRegExpConstructorInput(ExecState*, JSObject*, JSValuePtr); +static void setRegExpConstructorMultiline(ExecState*, JSObject*, JSValuePtr); } // namespace JSC @@ -103,7 +103,7 @@ struct RegExpConstructorPrivate { bool multiline : 1; }; -RegExpConstructor::RegExpConstructor(ExecState* exec, PassRefPtr<StructureID> structure, RegExpPrototype* regExpPrototype) +RegExpConstructor::RegExpConstructor(ExecState* exec, PassRefPtr<Structure> structure, RegExpPrototype* regExpPrototype) : InternalFunction(&exec->globalData(), structure, Identifier(exec, "RegExp")) , d(new RegExpConstructorPrivate) { @@ -185,7 +185,7 @@ JSObject* RegExpConstructor::arrayOfMatches(ExecState* exec) const return new (exec) RegExpMatchesArray(exec, d.get()); } -JSValue* RegExpConstructor::getBackref(ExecState* exec, unsigned i) const +JSValuePtr RegExpConstructor::getBackref(ExecState* exec, unsigned i) const { if (d->lastOvector && i <= d->lastNumSubPatterns) { int start = d->lastOvector[2 * i]; @@ -195,7 +195,7 @@ JSValue* RegExpConstructor::getBackref(ExecState* exec, unsigned i) const return jsEmptyString(exec); } -JSValue* RegExpConstructor::getLastParen(ExecState* exec) const +JSValuePtr RegExpConstructor::getLastParen(ExecState* exec) const { unsigned i = d->lastNumSubPatterns; if (i > 0) { @@ -207,14 +207,14 @@ JSValue* RegExpConstructor::getLastParen(ExecState* exec) const return jsEmptyString(exec); } -JSValue* RegExpConstructor::getLeftContext(ExecState* exec) const +JSValuePtr RegExpConstructor::getLeftContext(ExecState* exec) const { if (d->lastOvector) return jsSubstring(exec, d->lastInput, 0, d->lastOvector[0]); return jsEmptyString(exec); } -JSValue* RegExpConstructor::getRightContext(ExecState* exec) const +JSValuePtr RegExpConstructor::getRightContext(ExecState* exec) const { if (d->lastOvector) return jsSubstring(exec, d->lastInput, d->lastOvector[1], d->lastInput.size() - d->lastOvector[1]); @@ -226,110 +226,110 @@ bool RegExpConstructor::getOwnPropertySlot(ExecState* exec, const Identifier& pr return getStaticValueSlot<RegExpConstructor, InternalFunction>(exec, ExecState::regExpConstructorTable(exec), this, propertyName, slot); } -JSValue* regExpConstructorDollar1(ExecState* exec, const Identifier&, const PropertySlot& slot) +JSValuePtr regExpConstructorDollar1(ExecState* exec, const Identifier&, const PropertySlot& slot) { return asRegExpConstructor(slot.slotBase())->getBackref(exec, 1); } -JSValue* regExpConstructorDollar2(ExecState* exec, const Identifier&, const PropertySlot& slot) +JSValuePtr regExpConstructorDollar2(ExecState* exec, const Identifier&, const PropertySlot& slot) { return asRegExpConstructor(slot.slotBase())->getBackref(exec, 2); } -JSValue* regExpConstructorDollar3(ExecState* exec, const Identifier&, const PropertySlot& slot) +JSValuePtr regExpConstructorDollar3(ExecState* exec, const Identifier&, const PropertySlot& slot) { return asRegExpConstructor(slot.slotBase())->getBackref(exec, 3); } -JSValue* regExpConstructorDollar4(ExecState* exec, const Identifier&, const PropertySlot& slot) +JSValuePtr regExpConstructorDollar4(ExecState* exec, const Identifier&, const PropertySlot& slot) { return asRegExpConstructor(slot.slotBase())->getBackref(exec, 4); } -JSValue* regExpConstructorDollar5(ExecState* exec, const Identifier&, const PropertySlot& slot) +JSValuePtr regExpConstructorDollar5(ExecState* exec, const Identifier&, const PropertySlot& slot) { return asRegExpConstructor(slot.slotBase())->getBackref(exec, 5); } -JSValue* regExpConstructorDollar6(ExecState* exec, const Identifier&, const PropertySlot& slot) +JSValuePtr regExpConstructorDollar6(ExecState* exec, const Identifier&, const PropertySlot& slot) { return asRegExpConstructor(slot.slotBase())->getBackref(exec, 6); } -JSValue* regExpConstructorDollar7(ExecState* exec, const Identifier&, const PropertySlot& slot) +JSValuePtr regExpConstructorDollar7(ExecState* exec, const Identifier&, const PropertySlot& slot) { return asRegExpConstructor(slot.slotBase())->getBackref(exec, 7); } -JSValue* regExpConstructorDollar8(ExecState* exec, const Identifier&, const PropertySlot& slot) +JSValuePtr regExpConstructorDollar8(ExecState* exec, const Identifier&, const PropertySlot& slot) { return asRegExpConstructor(slot.slotBase())->getBackref(exec, 8); } -JSValue* regExpConstructorDollar9(ExecState* exec, const Identifier&, const PropertySlot& slot) +JSValuePtr regExpConstructorDollar9(ExecState* exec, const Identifier&, const PropertySlot& slot) { return asRegExpConstructor(slot.slotBase())->getBackref(exec, 9); } -JSValue* regExpConstructorInput(ExecState* exec, const Identifier&, const PropertySlot& slot) +JSValuePtr regExpConstructorInput(ExecState* exec, const Identifier&, const PropertySlot& slot) { return jsString(exec, asRegExpConstructor(slot.slotBase())->input()); } -JSValue* regExpConstructorMultiline(ExecState*, const Identifier&, const PropertySlot& slot) +JSValuePtr regExpConstructorMultiline(ExecState*, const Identifier&, const PropertySlot& slot) { return jsBoolean(asRegExpConstructor(slot.slotBase())->multiline()); } -JSValue* regExpConstructorLastMatch(ExecState* exec, const Identifier&, const PropertySlot& slot) +JSValuePtr regExpConstructorLastMatch(ExecState* exec, const Identifier&, const PropertySlot& slot) { return asRegExpConstructor(slot.slotBase())->getBackref(exec, 0); } -JSValue* regExpConstructorLastParen(ExecState* exec, const Identifier&, const PropertySlot& slot) +JSValuePtr regExpConstructorLastParen(ExecState* exec, const Identifier&, const PropertySlot& slot) { return asRegExpConstructor(slot.slotBase())->getLastParen(exec); } -JSValue* regExpConstructorLeftContext(ExecState* exec, const Identifier&, const PropertySlot& slot) +JSValuePtr regExpConstructorLeftContext(ExecState* exec, const Identifier&, const PropertySlot& slot) { return asRegExpConstructor(slot.slotBase())->getLeftContext(exec); } -JSValue* regExpConstructorRightContext(ExecState* exec, const Identifier&, const PropertySlot& slot) +JSValuePtr regExpConstructorRightContext(ExecState* exec, const Identifier&, const PropertySlot& slot) { return asRegExpConstructor(slot.slotBase())->getRightContext(exec); } -void RegExpConstructor::put(ExecState* exec, const Identifier& propertyName, JSValue* value, PutPropertySlot& slot) +void RegExpConstructor::put(ExecState* exec, const Identifier& propertyName, JSValuePtr value, PutPropertySlot& slot) { lookupPut<RegExpConstructor, InternalFunction>(exec, propertyName, value, ExecState::regExpConstructorTable(exec), this, slot); } -void setRegExpConstructorInput(ExecState* exec, JSObject* baseObject, JSValue* value) +void setRegExpConstructorInput(ExecState* exec, JSObject* baseObject, JSValuePtr value) { - asRegExpConstructor(baseObject)->setInput(value->toString(exec)); + asRegExpConstructor(baseObject)->setInput(value.toString(exec)); } -void setRegExpConstructorMultiline(ExecState* exec, JSObject* baseObject, JSValue* value) +void setRegExpConstructorMultiline(ExecState* exec, JSObject* baseObject, JSValuePtr value) { - asRegExpConstructor(baseObject)->setMultiline(value->toBoolean(exec)); + asRegExpConstructor(baseObject)->setMultiline(value.toBoolean(exec)); } // ECMA 15.10.4 JSObject* constructRegExp(ExecState* exec, const ArgList& args) { - JSValue* arg0 = args.at(exec, 0); - JSValue* arg1 = args.at(exec, 1); + JSValuePtr arg0 = args.at(exec, 0); + JSValuePtr arg1 = args.at(exec, 1); - if (arg0->isObject(&RegExpObject::info)) { - if (!arg1->isUndefined()) + if (arg0.isObject(&RegExpObject::info)) { + if (!arg1.isUndefined()) return throwError(exec, TypeError, "Cannot supply flags when constructing one RegExp from another."); return asObject(arg0); } - UString pattern = arg0->isUndefined() ? UString("") : arg0->toString(exec); - UString flags = arg1->isUndefined() ? UString("") : arg1->toString(exec); + UString pattern = arg0.isUndefined() ? UString("") : arg0.toString(exec); + UString flags = arg1.isUndefined() ? UString("") : arg1.toString(exec); RefPtr<RegExp> regExp = RegExp::create(&exec->globalData(), pattern, flags); if (!regExp->isValid()) @@ -349,7 +349,7 @@ ConstructType RegExpConstructor::getConstructData(ConstructData& constructData) } // ECMA 15.10.3 -static JSValue* callRegExpConstructor(ExecState* exec, JSObject*, JSValue*, const ArgList& args) +static JSValuePtr callRegExpConstructor(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) { return constructRegExp(exec, args); } diff --git a/JavaScriptCore/runtime/RegExpConstructor.h b/JavaScriptCore/runtime/RegExpConstructor.h index c5a94a5..f8c4366 100644 --- a/JavaScriptCore/runtime/RegExpConstructor.h +++ b/JavaScriptCore/runtime/RegExpConstructor.h @@ -32,14 +32,14 @@ namespace JSC { class RegExpConstructor : public InternalFunction { public: - RegExpConstructor(ExecState*, PassRefPtr<StructureID>, RegExpPrototype*); + RegExpConstructor(ExecState*, PassRefPtr<Structure>, RegExpPrototype*); - static PassRefPtr<StructureID> createStructureID(JSValue* prototype) + static PassRefPtr<Structure> createStructure(JSValuePtr prototype) { - return StructureID::create(prototype, TypeInfo(ObjectType, ImplementsHasInstance)); + return Structure::create(prototype, TypeInfo(ObjectType, ImplementsHasInstance)); } - virtual void put(ExecState*, const Identifier& propertyName, JSValue*, PutPropertySlot&); + virtual void put(ExecState*, const Identifier& propertyName, JSValuePtr, PutPropertySlot&); virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); static const ClassInfo info; @@ -53,10 +53,10 @@ namespace JSC { void setMultiline(bool); bool multiline() const; - JSValue* getBackref(ExecState*, unsigned) const; - JSValue* getLastParen(ExecState*) const; - JSValue* getLeftContext(ExecState*) const; - JSValue* getRightContext(ExecState*) const; + JSValuePtr getBackref(ExecState*, unsigned) const; + JSValuePtr getLastParen(ExecState*) const; + JSValuePtr getLeftContext(ExecState*) const; + JSValuePtr getRightContext(ExecState*) const; private: virtual ConstructType getConstructData(ConstructData&); @@ -67,11 +67,11 @@ namespace JSC { OwnPtr<RegExpConstructorPrivate> d; }; - RegExpConstructor* asRegExpConstructor(JSValue*); + RegExpConstructor* asRegExpConstructor(JSValuePtr); JSObject* constructRegExp(ExecState*, const ArgList&); - inline RegExpConstructor* asRegExpConstructor(JSValue* value) + inline RegExpConstructor* asRegExpConstructor(JSValuePtr value) { ASSERT(asObject(value)->inherits(&RegExpConstructor::info)); return static_cast<RegExpConstructor*>(asObject(value)); diff --git a/JavaScriptCore/runtime/RegExpMatchesArray.h b/JavaScriptCore/runtime/RegExpMatchesArray.h index 6a4279e..3583941 100644 --- a/JavaScriptCore/runtime/RegExpMatchesArray.h +++ b/JavaScriptCore/runtime/RegExpMatchesArray.h @@ -44,14 +44,14 @@ namespace JSC { return JSArray::getOwnPropertySlot(exec, propertyName, slot); } - virtual void put(ExecState* exec, const Identifier& propertyName, JSValue* v, PutPropertySlot& slot) + virtual void put(ExecState* exec, const Identifier& propertyName, JSValuePtr v, PutPropertySlot& slot) { if (lazyCreationData()) fillArrayInstance(exec); JSArray::put(exec, propertyName, v, slot); } - virtual void put(ExecState* exec, unsigned propertyName, JSValue* v) + virtual void put(ExecState* exec, unsigned propertyName, JSValuePtr v) { if (lazyCreationData()) fillArrayInstance(exec); diff --git a/JavaScriptCore/runtime/RegExpObject.cpp b/JavaScriptCore/runtime/RegExpObject.cpp index 127a71e..f8e0522 100644 --- a/JavaScriptCore/runtime/RegExpObject.cpp +++ b/JavaScriptCore/runtime/RegExpObject.cpp @@ -29,12 +29,12 @@ namespace JSC { -static JSValue* regExpObjectGlobal(ExecState*, const Identifier&, const PropertySlot&); -static JSValue* regExpObjectIgnoreCase(ExecState*, const Identifier&, const PropertySlot&); -static JSValue* regExpObjectMultiline(ExecState*, const Identifier&, const PropertySlot&); -static JSValue* regExpObjectSource(ExecState*, const Identifier&, const PropertySlot&); -static JSValue* regExpObjectLastIndex(ExecState*, const Identifier&, const PropertySlot&); -static void setRegExpObjectLastIndex(ExecState*, JSObject*, JSValue*); +static JSValuePtr regExpObjectGlobal(ExecState*, const Identifier&, const PropertySlot&); +static JSValuePtr regExpObjectIgnoreCase(ExecState*, const Identifier&, const PropertySlot&); +static JSValuePtr regExpObjectMultiline(ExecState*, const Identifier&, const PropertySlot&); +static JSValuePtr regExpObjectSource(ExecState*, const Identifier&, const PropertySlot&); +static JSValuePtr regExpObjectLastIndex(ExecState*, const Identifier&, const PropertySlot&); +static void setRegExpObjectLastIndex(ExecState*, JSObject*, JSValuePtr); } // namespace JSC @@ -56,7 +56,7 @@ const ClassInfo RegExpObject::info = { "RegExp", 0, 0, ExecState::regExpTable }; @end */ -RegExpObject::RegExpObject(PassRefPtr<StructureID> structure, PassRefPtr<RegExp> regExp) +RegExpObject::RegExpObject(PassRefPtr<Structure> structure, PassRefPtr<RegExp> regExp) : JSObject(structure) , d(new RegExpObjectData(regExp, 0)) { @@ -71,91 +71,54 @@ bool RegExpObject::getOwnPropertySlot(ExecState* exec, const Identifier& propert return getStaticValueSlot<RegExpObject, JSObject>(exec, ExecState::regExpTable(exec), this, propertyName, slot); } -JSValue* regExpObjectGlobal(ExecState*, const Identifier&, const PropertySlot& slot) +JSValuePtr regExpObjectGlobal(ExecState*, const Identifier&, const PropertySlot& slot) { return jsBoolean(asRegExpObject(slot.slotBase())->regExp()->global()); } -JSValue* regExpObjectIgnoreCase(ExecState*, const Identifier&, const PropertySlot& slot) +JSValuePtr regExpObjectIgnoreCase(ExecState*, const Identifier&, const PropertySlot& slot) { return jsBoolean(asRegExpObject(slot.slotBase())->regExp()->ignoreCase()); } -JSValue* regExpObjectMultiline(ExecState*, const Identifier&, const PropertySlot& slot) +JSValuePtr regExpObjectMultiline(ExecState*, const Identifier&, const PropertySlot& slot) { return jsBoolean(asRegExpObject(slot.slotBase())->regExp()->multiline()); } -JSValue* regExpObjectSource(ExecState* exec, const Identifier&, const PropertySlot& slot) +JSValuePtr regExpObjectSource(ExecState* exec, const Identifier&, const PropertySlot& slot) { return jsString(exec, asRegExpObject(slot.slotBase())->regExp()->pattern()); } -JSValue* regExpObjectLastIndex(ExecState* exec, const Identifier&, const PropertySlot& slot) +JSValuePtr regExpObjectLastIndex(ExecState* exec, const Identifier&, const PropertySlot& slot) { return jsNumber(exec, asRegExpObject(slot.slotBase())->lastIndex()); } -void RegExpObject::put(ExecState* exec, const Identifier& propertyName, JSValue* value, PutPropertySlot& slot) +void RegExpObject::put(ExecState* exec, const Identifier& propertyName, JSValuePtr value, PutPropertySlot& slot) { lookupPut<RegExpObject, JSObject>(exec, propertyName, value, ExecState::regExpTable(exec), this, slot); } -void setRegExpObjectLastIndex(ExecState* exec, JSObject* baseObject, JSValue* value) +void setRegExpObjectLastIndex(ExecState* exec, JSObject* baseObject, JSValuePtr value) { - asRegExpObject(baseObject)->setLastIndex(value->toInteger(exec)); + asRegExpObject(baseObject)->setLastIndex(value.toInteger(exec)); } -bool RegExpObject::match(ExecState* exec, const ArgList& args) -{ - RegExpConstructor* regExpObj = exec->lexicalGlobalObject()->regExpConstructor(); - - UString input; - if (!args.isEmpty()) - input = args.at(exec, 0)->toString(exec); - else { - input = regExpObj->input(); - if (input.isNull()) { - throwError(exec, GeneralError, "No input."); - return false; - } - } - - bool global = get(exec, exec->propertyNames().global)->toBoolean(exec); - int lastIndex = 0; - if (global) { - if (d->lastIndex < 0 || d->lastIndex > input.size()) { - d->lastIndex = 0; - return false; - } - lastIndex = static_cast<int>(d->lastIndex); - } - - int foundIndex; - int foundLength; - regExpObj->performMatch(d->regExp.get(), input, lastIndex, foundIndex, foundLength); - - if (global) { - lastIndex = foundIndex < 0 ? 0 : foundIndex + foundLength; - d->lastIndex = lastIndex; - } - - return foundIndex >= 0; -} - -JSValue* RegExpObject::test(ExecState* exec, const ArgList& args) +JSValuePtr RegExpObject::test(ExecState* exec, const ArgList& args) { return jsBoolean(match(exec, args)); } -JSValue* RegExpObject::exec(ExecState* exec, const ArgList& args) +JSValuePtr RegExpObject::exec(ExecState* exec, const ArgList& args) { if (match(exec, args)) return exec->lexicalGlobalObject()->regExpConstructor()->arrayOfMatches(exec); return jsNull(); } -static JSValue* callRegExpObject(ExecState* exec, JSObject* function, JSValue*, const ArgList& args) +static JSValuePtr callRegExpObject(ExecState* exec, JSObject* function, JSValuePtr, const ArgList& args) { return asRegExpObject(function)->exec(exec, args); } @@ -166,4 +129,39 @@ CallType RegExpObject::getCallData(CallData& callData) return CallTypeHost; } +// Shared implementation used by test and exec. +bool RegExpObject::match(ExecState* exec, const ArgList& args) +{ + RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor(); + + UString input = args.isEmpty() ? regExpConstructor->input() : args.at(exec, 0).toString(exec); + if (input.isNull()) { + throwError(exec, GeneralError, "No input to " + toString(exec) + "."); + return false; + } + + if (!regExp()->global()) { + int position; + int length; + regExpConstructor->performMatch(d->regExp.get(), input, 0, position, length); + return position >= 0; + } + + if (d->lastIndex < 0 || d->lastIndex > input.size()) { + d->lastIndex = 0; + return false; + } + + int position; + int length; + regExpConstructor->performMatch(d->regExp.get(), input, static_cast<int>(d->lastIndex), position, length); + if (position < 0) { + d->lastIndex = 0; + return false; + } + + d->lastIndex = position + length; + return true; +} + } // namespace JSC diff --git a/JavaScriptCore/runtime/RegExpObject.h b/JavaScriptCore/runtime/RegExpObject.h index d80b47c..4c99c30 100644 --- a/JavaScriptCore/runtime/RegExpObject.h +++ b/JavaScriptCore/runtime/RegExpObject.h @@ -22,13 +22,13 @@ #define RegExpObject_h #include "JSObject.h" -#include "regexp.h" +#include "RegExp.h" namespace JSC { class RegExpObject : public JSObject { public: - RegExpObject(PassRefPtr<StructureID>, PassRefPtr<RegExp>); + RegExpObject(PassRefPtr<Structure>, PassRefPtr<RegExp>); virtual ~RegExpObject(); void setRegExp(PassRefPtr<RegExp> r) { d->regExp = r; } @@ -37,18 +37,18 @@ namespace JSC { void setLastIndex(double lastIndex) { d->lastIndex = lastIndex; } double lastIndex() const { return d->lastIndex; } - JSValue* test(ExecState*, const ArgList&); - JSValue* exec(ExecState*, const ArgList&); + JSValuePtr test(ExecState*, const ArgList&); + JSValuePtr exec(ExecState*, const ArgList&); virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); - virtual void put(ExecState*, const Identifier& propertyName, JSValue*, PutPropertySlot&); + virtual void put(ExecState*, const Identifier& propertyName, JSValuePtr, PutPropertySlot&); virtual const ClassInfo* classInfo() const { return &info; } static const ClassInfo info; - static PassRefPtr<StructureID> createStructureID(JSValue* prototype) + static PassRefPtr<Structure> createStructure(JSValuePtr prototype) { - return StructureID::create(prototype, TypeInfo(ObjectType)); + return Structure::create(prototype, TypeInfo(ObjectType)); } private: @@ -70,9 +70,9 @@ namespace JSC { OwnPtr<RegExpObjectData> d; }; - RegExpObject* asRegExpObject(JSValue*); + RegExpObject* asRegExpObject(JSValuePtr); - inline RegExpObject* asRegExpObject(JSValue* value) + inline RegExpObject* asRegExpObject(JSValuePtr value) { ASSERT(asObject(value)->inherits(&RegExpObject::info)); return static_cast<RegExpObject*>(asObject(value)); diff --git a/JavaScriptCore/runtime/RegExpPrototype.cpp b/JavaScriptCore/runtime/RegExpPrototype.cpp index ceee32a..73787bc 100644 --- a/JavaScriptCore/runtime/RegExpPrototype.cpp +++ b/JavaScriptCore/runtime/RegExpPrototype.cpp @@ -29,22 +29,22 @@ #include "ObjectPrototype.h" #include "PrototypeFunction.h" #include "RegExpObject.h" -#include "regexp.h" +#include "RegExp.h" namespace JSC { ASSERT_CLASS_FITS_IN_CELL(RegExpPrototype); -static JSValue* regExpProtoFuncTest(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* regExpProtoFuncExec(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* regExpProtoFuncCompile(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* regExpProtoFuncToString(ExecState*, JSObject*, JSValue*, const ArgList&); +static JSValuePtr regExpProtoFuncTest(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr regExpProtoFuncExec(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr regExpProtoFuncCompile(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr regExpProtoFuncToString(ExecState*, JSObject*, JSValuePtr, const ArgList&); // ECMA 15.10.5 const ClassInfo RegExpPrototype::info = { "RegExpPrototype", 0, 0, 0 }; -RegExpPrototype::RegExpPrototype(ExecState* exec, PassRefPtr<StructureID> structure, StructureID* prototypeFunctionStructure) +RegExpPrototype::RegExpPrototype(ExecState* exec, PassRefPtr<Structure> structure, Structure* prototypeFunctionStructure) : JSObject(structure) { putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 0, exec->propertyNames().compile, regExpProtoFuncCompile), DontEnum); @@ -55,36 +55,36 @@ RegExpPrototype::RegExpPrototype(ExecState* exec, PassRefPtr<StructureID> struct // ------------------------------ Functions --------------------------- -JSValue* regExpProtoFuncTest(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) +JSValuePtr regExpProtoFuncTest(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) { - if (!thisValue->isObject(&RegExpObject::info)) + if (!thisValue.isObject(&RegExpObject::info)) return throwError(exec, TypeError); return asRegExpObject(thisValue)->test(exec, args); } -JSValue* regExpProtoFuncExec(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) +JSValuePtr regExpProtoFuncExec(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) { - if (!thisValue->isObject(&RegExpObject::info)) + if (!thisValue.isObject(&RegExpObject::info)) return throwError(exec, TypeError); return asRegExpObject(thisValue)->exec(exec, args); } -JSValue* regExpProtoFuncCompile(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) +JSValuePtr regExpProtoFuncCompile(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) { - if (!thisValue->isObject(&RegExpObject::info)) + if (!thisValue.isObject(&RegExpObject::info)) return throwError(exec, TypeError); RefPtr<RegExp> regExp; - JSValue* arg0 = args.at(exec, 0); - JSValue* arg1 = args.at(exec, 1); + JSValuePtr arg0 = args.at(exec, 0); + JSValuePtr arg1 = args.at(exec, 1); - if (arg0->isObject(&RegExpObject::info)) { - if (!arg1->isUndefined()) + if (arg0.isObject(&RegExpObject::info)) { + if (!arg1.isUndefined()) return throwError(exec, TypeError, "Cannot supply flags when constructing one RegExp from another."); regExp = asRegExpObject(arg0)->regExp(); } else { - UString pattern = args.isEmpty() ? UString("") : arg0->toString(exec); - UString flags = arg1->isUndefined() ? UString("") : arg1->toString(exec); + UString pattern = args.isEmpty() ? UString("") : arg0.toString(exec); + UString flags = arg1.isUndefined() ? UString("") : arg1.toString(exec); regExp = RegExp::create(&exec->globalData(), pattern, flags); } @@ -96,21 +96,21 @@ JSValue* regExpProtoFuncCompile(ExecState* exec, JSObject*, JSValue* thisValue, return jsUndefined(); } -JSValue* regExpProtoFuncToString(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&) +JSValuePtr regExpProtoFuncToString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) { - if (!thisValue->isObject(&RegExpObject::info)) { - if (thisValue->isObject(&RegExpPrototype::info)) + if (!thisValue.isObject(&RegExpObject::info)) { + if (thisValue.isObject(&RegExpPrototype::info)) return jsNontrivialString(exec, "//"); return throwError(exec, TypeError); } - UString result = "/" + asRegExpObject(thisValue)->get(exec, exec->propertyNames().source)->toString(exec); + UString result = "/" + asRegExpObject(thisValue)->get(exec, exec->propertyNames().source).toString(exec); result.append('/'); - if (asRegExpObject(thisValue)->get(exec, exec->propertyNames().global)->toBoolean(exec)) + if (asRegExpObject(thisValue)->get(exec, exec->propertyNames().global).toBoolean(exec)) result.append('g'); - if (asRegExpObject(thisValue)->get(exec, exec->propertyNames().ignoreCase)->toBoolean(exec)) + if (asRegExpObject(thisValue)->get(exec, exec->propertyNames().ignoreCase).toBoolean(exec)) result.append('i'); - if (asRegExpObject(thisValue)->get(exec, exec->propertyNames().multiline)->toBoolean(exec)) + if (asRegExpObject(thisValue)->get(exec, exec->propertyNames().multiline).toBoolean(exec)) result.append('m'); return jsNontrivialString(exec, result); } diff --git a/JavaScriptCore/runtime/RegExpPrototype.h b/JavaScriptCore/runtime/RegExpPrototype.h index 44a0f32..f5db720 100644 --- a/JavaScriptCore/runtime/RegExpPrototype.h +++ b/JavaScriptCore/runtime/RegExpPrototype.h @@ -27,7 +27,7 @@ namespace JSC { class RegExpPrototype : public JSObject { public: - RegExpPrototype(ExecState*, PassRefPtr<StructureID>, StructureID* prototypeFunctionStructure); + RegExpPrototype(ExecState*, PassRefPtr<Structure>, Structure* prototypeFunctionStructure); virtual const ClassInfo* classInfo() const { return &info; } static const ClassInfo info; diff --git a/JavaScriptCore/runtime/ScopeChain.cpp b/JavaScriptCore/runtime/ScopeChain.cpp index e90b565..5c2edab 100644 --- a/JavaScriptCore/runtime/ScopeChain.cpp +++ b/JavaScriptCore/runtime/ScopeChain.cpp @@ -21,6 +21,7 @@ #include "config.h" #include "ScopeChain.h" +#include "JSActivation.h" #include "JSGlobalObject.h" #include "JSObject.h" #include "PropertyNameArray.h" @@ -50,4 +51,18 @@ void ScopeChainNode::print() const #endif +int ScopeChain::localDepth() const +{ + int scopeDepth = 0; + ScopeChainIterator iter = this->begin(); + ScopeChainIterator end = this->end(); + while (!(*iter)->isObject(&JSActivation::info)) { + ++iter; + if (iter == end) + break; + ++scopeDepth; + } + return scopeDepth; +} + } // namespace JSC diff --git a/JavaScriptCore/runtime/ScopeChain.h b/JavaScriptCore/runtime/ScopeChain.h index 834217c..32b5e92 100644 --- a/JavaScriptCore/runtime/ScopeChain.h +++ b/JavaScriptCore/runtime/ScopeChain.h @@ -48,8 +48,8 @@ namespace JSC { JSObject* globalThis; int refCount; - void deref() { if (--refCount == 0) release(); } - void ref() { ++refCount; } + void deref() { ASSERT(refCount); if (--refCount == 0) { release();} } + void ref() { ASSERT(refCount); ++refCount; } void release(); // Before calling "push" on a bare ScopeChainNode, a client should @@ -143,7 +143,7 @@ namespace JSC { class NoScopeChain {}; class ScopeChain { - friend class CTI; + friend class JIT; public: ScopeChain(NoScopeChain) : m_node(0) @@ -191,6 +191,13 @@ namespace JSC { void mark() const; + // Caution: this should only be used if the codeblock this is being used + // with needs a full scope chain, otherwise this returns the depth of + // the preceeding call frame + // + // Returns the depth of the current call frame's scope chain + int localDepth() const; + #ifndef NDEBUG void print() const { m_node->print(); } #endif diff --git a/JavaScriptCore/runtime/SmallStrings.cpp b/JavaScriptCore/runtime/SmallStrings.cpp index 06811b9..6c73df2 100644 --- a/JavaScriptCore/runtime/SmallStrings.cpp +++ b/JavaScriptCore/runtime/SmallStrings.cpp @@ -29,48 +29,60 @@ #include "JSGlobalObject.h" #include "JSString.h" +#include <wtf/Noncopyable.h> + namespace JSC { +static const unsigned numCharactersToStore = 0x100; -class SmallStringsStorage { +class SmallStringsStorage : Noncopyable { public: SmallStringsStorage(); - ~SmallStringsStorage(); - UString::Rep* rep(unsigned char character) { return &reps[character]; } + UString::Rep* rep(unsigned char character) { return &m_reps[character]; } private: - UChar characters[0x100]; - UString::Rep* reps; + UChar m_characters[numCharactersToStore]; + UString::BaseString m_base; + UString::Rep m_reps[numCharactersToStore]; }; SmallStringsStorage::SmallStringsStorage() - : reps(static_cast<UString::Rep*>(fastZeroedMalloc(sizeof(UString::Rep) * 0x100))) { - for (unsigned i = 0; i < 0x100; ++i) { - characters[i] = i; - reps[i].offset = i; - reps[i].len = 1; - reps[i].rc = 1; - reps[i].baseString = &reps[0]; - } - reps[0].rc = 0x101; - reps[0].buf = characters; + for (unsigned i = 0; i < numCharactersToStore; ++i) + m_characters[i] = i; + + m_base.rc = numCharactersToStore + 1; + m_base.buf = m_characters; + m_base.len = numCharactersToStore; + m_base.offset = 0; + m_base._hash = 0; + m_base.m_baseString = 0; + m_base.preCapacity = 0; + m_base.usedPreCapacity = 0; + m_base.reportedCost = 0; // make sure UString doesn't try to reuse the buffer by pretending we have one more character in it - reps[0].usedCapacity = 0x101; - reps[0].capacity = 0x101; -} + m_base.usedCapacity = numCharactersToStore + 1; + m_base.capacity = numCharactersToStore + 1; + m_base.checkConsistency(); -SmallStringsStorage::~SmallStringsStorage() -{ - fastFree(reps); + memset(&m_reps, 0, sizeof(m_reps)); + for (unsigned i = 0; i < numCharactersToStore; ++i) { + m_reps[i].offset = i; + m_reps[i].len = 1; + m_reps[i].rc = 1; + m_reps[i].setBaseString(&m_base); + m_reps[i].checkConsistency(); + } } SmallStrings::SmallStrings() : m_emptyString(0) , m_storage(0) { - for (unsigned i = 0; i < 0x100; ++i) + COMPILE_ASSERT(numCharactersToStore == sizeof(m_singleCharacterStrings) / sizeof(m_singleCharacterStrings[0]), IsNumCharactersConstInSyncWithClassUsage); + + for (unsigned i = 0; i < numCharactersToStore; ++i) m_singleCharacterStrings[i] = 0; } @@ -82,12 +94,24 @@ void SmallStrings::mark() { if (m_emptyString && !m_emptyString->marked()) m_emptyString->mark(); - for (unsigned i = 0; i < 0x100; ++i) { + for (unsigned i = 0; i < numCharactersToStore; ++i) { if (m_singleCharacterStrings[i] && !m_singleCharacterStrings[i]->marked()) m_singleCharacterStrings[i]->mark(); } } - + +unsigned SmallStrings::count() const +{ + unsigned count = 0; + if (m_emptyString) + ++count; + for (unsigned i = 0; i < numCharactersToStore; ++i) { + if (m_singleCharacterStrings[i]) + ++count; + } + return count; +} + void SmallStrings::createEmptyString(JSGlobalData* globalData) { ASSERT(!m_emptyString); @@ -109,4 +133,4 @@ UString::Rep* SmallStrings::singleCharacterStringRep(unsigned char character) return m_storage->rep(character); } -} +} // namespace JSC diff --git a/JavaScriptCore/runtime/SmallStrings.h b/JavaScriptCore/runtime/SmallStrings.h index 7c71208..e7f1170 100644 --- a/JavaScriptCore/runtime/SmallStrings.h +++ b/JavaScriptCore/runtime/SmallStrings.h @@ -26,7 +26,7 @@ #ifndef SmallStrings_h #define SmallStrings_h -#include "ustring.h" +#include "UString.h" #include <wtf/OwnPtr.h> namespace JSC { @@ -55,9 +55,11 @@ namespace JSC { } UString::Rep* singleCharacterStringRep(unsigned char character); - + void mark(); - + + unsigned count() const; + private: void createEmptyString(JSGlobalData*); void createSingleCharacterString(JSGlobalData*, unsigned char); @@ -66,7 +68,7 @@ namespace JSC { JSString* m_singleCharacterStrings[0x100]; OwnPtr<SmallStringsStorage> m_storage; }; - -} -#endif +} // namespace JSC + +#endif // SmallStrings_h diff --git a/JavaScriptCore/runtime/StringConstructor.cpp b/JavaScriptCore/runtime/StringConstructor.cpp index 850310e..dc1d60f 100644 --- a/JavaScriptCore/runtime/StringConstructor.cpp +++ b/JavaScriptCore/runtime/StringConstructor.cpp @@ -27,26 +27,26 @@ namespace JSC { -static NEVER_INLINE JSValue* stringFromCharCodeSlowCase(ExecState* exec, const ArgList& args) +static NEVER_INLINE JSValuePtr stringFromCharCodeSlowCase(ExecState* exec, const ArgList& args) { UChar* buf = static_cast<UChar*>(fastMalloc(args.size() * sizeof(UChar))); UChar* p = buf; ArgList::const_iterator end = args.end(); for (ArgList::const_iterator it = args.begin(); it != end; ++it) - *p++ = static_cast<UChar>((*it).jsValue(exec)->toUInt32(exec)); + *p++ = static_cast<UChar>((*it).jsValue(exec).toUInt32(exec)); return jsString(exec, UString(buf, p - buf, false)); } -static JSValue* stringFromCharCode(ExecState* exec, JSObject*, JSValue*, const ArgList& args) +static JSValuePtr stringFromCharCode(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) { if (LIKELY(args.size() == 1)) - return jsSingleCharacterString(exec, args.at(exec, 0)->toUInt32(exec)); + return jsSingleCharacterString(exec, args.at(exec, 0).toUInt32(exec)); return stringFromCharCodeSlowCase(exec, args); } ASSERT_CLASS_FITS_IN_CELL(StringConstructor); -StringConstructor::StringConstructor(ExecState* exec, PassRefPtr<StructureID> structure, StructureID* prototypeFunctionStructure, StringPrototype* stringPrototype) +StringConstructor::StringConstructor(ExecState* exec, PassRefPtr<Structure> structure, Structure* prototypeFunctionStructure, StringPrototype* stringPrototype) : InternalFunction(&exec->globalData(), structure, Identifier(exec, stringPrototype->classInfo()->className)) { // ECMA 15.5.3.1 String.prototype @@ -64,7 +64,7 @@ static JSObject* constructWithStringConstructor(ExecState* exec, JSObject*, cons { if (args.isEmpty()) return new (exec) StringObject(exec, exec->lexicalGlobalObject()->stringObjectStructure()); - return new (exec) StringObject(exec, exec->lexicalGlobalObject()->stringObjectStructure(), args.at(exec, 0)->toString(exec)); + return new (exec) StringObject(exec, exec->lexicalGlobalObject()->stringObjectStructure(), args.at(exec, 0).toString(exec)); } ConstructType StringConstructor::getConstructData(ConstructData& constructData) @@ -74,11 +74,11 @@ ConstructType StringConstructor::getConstructData(ConstructData& constructData) } // ECMA 15.5.1 -static JSValue* callStringConstructor(ExecState* exec, JSObject*, JSValue*, const ArgList& args) +static JSValuePtr callStringConstructor(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) { if (args.isEmpty()) return jsEmptyString(exec); - return jsString(exec, args.at(exec, 0)->toString(exec)); + return jsString(exec, args.at(exec, 0).toString(exec)); } CallType StringConstructor::getCallData(CallData& callData) diff --git a/JavaScriptCore/runtime/StringConstructor.h b/JavaScriptCore/runtime/StringConstructor.h index 3376134..7d52c69 100644 --- a/JavaScriptCore/runtime/StringConstructor.h +++ b/JavaScriptCore/runtime/StringConstructor.h @@ -29,7 +29,7 @@ namespace JSC { class StringConstructor : public InternalFunction { public: - StringConstructor(ExecState*, PassRefPtr<StructureID>, StructureID* prototypeFunctionStructure, StringPrototype*); + StringConstructor(ExecState*, PassRefPtr<Structure>, Structure* prototypeFunctionStructure, StringPrototype*); virtual ConstructType getConstructData(ConstructData&); virtual CallType getCallData(CallData&); diff --git a/JavaScriptCore/runtime/StringObject.cpp b/JavaScriptCore/runtime/StringObject.cpp index 5959395..093f5de 100644 --- a/JavaScriptCore/runtime/StringObject.cpp +++ b/JavaScriptCore/runtime/StringObject.cpp @@ -29,19 +29,19 @@ ASSERT_CLASS_FITS_IN_CELL(StringObject); const ClassInfo StringObject::info = { "String", 0, 0, 0 }; -StringObject::StringObject(ExecState* exec, PassRefPtr<StructureID> structure) +StringObject::StringObject(ExecState* exec, PassRefPtr<Structure> structure) : JSWrapperObject(structure) { setInternalValue(jsEmptyString(exec)); } -StringObject::StringObject(PassRefPtr<StructureID> structure, JSString* string) +StringObject::StringObject(PassRefPtr<Structure> structure, JSString* string) : JSWrapperObject(structure) { setInternalValue(string); } -StringObject::StringObject(ExecState* exec, PassRefPtr<StructureID> structure, const UString& string) +StringObject::StringObject(ExecState* exec, PassRefPtr<Structure> structure, const UString& string) : JSWrapperObject(structure) { setInternalValue(jsString(exec, string)); @@ -61,7 +61,7 @@ bool StringObject::getOwnPropertySlot(ExecState* exec, unsigned propertyName, Pr return JSObject::getOwnPropertySlot(exec, Identifier::from(exec, propertyName), slot); } -void StringObject::put(ExecState* exec, const Identifier& propertyName, JSValue* value, PutPropertySlot& slot) +void StringObject::put(ExecState* exec, const Identifier& propertyName, JSValuePtr value, PutPropertySlot& slot) { if (propertyName == exec->propertyNames().length) return; diff --git a/JavaScriptCore/runtime/StringObject.h b/JavaScriptCore/runtime/StringObject.h index 9297fd7..540c576 100644 --- a/JavaScriptCore/runtime/StringObject.h +++ b/JavaScriptCore/runtime/StringObject.h @@ -28,15 +28,15 @@ namespace JSC { class StringObject : public JSWrapperObject { public: - StringObject(ExecState*, PassRefPtr<StructureID>); - StringObject(ExecState*, PassRefPtr<StructureID>, const UString&); + StringObject(ExecState*, PassRefPtr<Structure>); + StringObject(ExecState*, PassRefPtr<Structure>, const UString&); static StringObject* create(ExecState*, JSString*); virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&); - virtual void put(ExecState* exec, const Identifier& propertyName, JSValue*, PutPropertySlot&); + virtual void put(ExecState* exec, const Identifier& propertyName, JSValuePtr, PutPropertySlot&); virtual bool deleteProperty(ExecState*, const Identifier& propertyName); virtual void getPropertyNames(ExecState*, PropertyNameArray&); @@ -45,13 +45,13 @@ namespace JSC { JSString* internalValue() const { return asString(JSWrapperObject::internalValue());} - static PassRefPtr<StructureID> createStructureID(JSValue* prototype) + static PassRefPtr<Structure> createStructure(JSValuePtr prototype) { - return StructureID::create(prototype, TypeInfo(ObjectType)); + return Structure::create(prototype, TypeInfo(ObjectType)); } protected: - StringObject(PassRefPtr<StructureID>, JSString*); + StringObject(PassRefPtr<Structure>, JSString*); private: virtual UString toString(ExecState*) const; @@ -59,9 +59,9 @@ namespace JSC { virtual JSString* toThisJSString(ExecState*); }; - StringObject* asStringObject(JSValue*); + StringObject* asStringObject(JSValuePtr); - inline StringObject* asStringObject(JSValue* value) + inline StringObject* asStringObject(JSValuePtr value) { ASSERT(asObject(value)->inherits(&StringObject::info)); return static_cast<StringObject*>(asObject(value)); diff --git a/JavaScriptCore/runtime/StringObjectThatMasqueradesAsUndefined.h b/JavaScriptCore/runtime/StringObjectThatMasqueradesAsUndefined.h index d703228..72c0f47 100644 --- a/JavaScriptCore/runtime/StringObjectThatMasqueradesAsUndefined.h +++ b/JavaScriptCore/runtime/StringObjectThatMasqueradesAsUndefined.h @@ -23,7 +23,7 @@ #include "JSGlobalObject.h" #include "StringObject.h" -#include "ustring.h" +#include "UString.h" namespace JSC { @@ -33,18 +33,18 @@ namespace JSC { static StringObjectThatMasqueradesAsUndefined* create(ExecState* exec, const UString& string) { return new (exec) StringObjectThatMasqueradesAsUndefined(exec, - createStructureID(exec->lexicalGlobalObject()->stringPrototype()), string); + createStructure(exec->lexicalGlobalObject()->stringPrototype()), string); } private: - StringObjectThatMasqueradesAsUndefined(ExecState* exec, PassRefPtr<StructureID> structure, const UString& string) + StringObjectThatMasqueradesAsUndefined(ExecState* exec, PassRefPtr<Structure> structure, const UString& string) : StringObject(exec, structure, string) { } - static PassRefPtr<StructureID> createStructureID(JSValue* proto) + static PassRefPtr<Structure> createStructure(JSValuePtr proto) { - return StructureID::create(proto, TypeInfo(ObjectType, MasqueradesAsUndefined)); + return Structure::create(proto, TypeInfo(ObjectType, MasqueradesAsUndefined)); } virtual bool toBoolean(ExecState*) const { return false; } diff --git a/JavaScriptCore/runtime/StringPrototype.cpp b/JavaScriptCore/runtime/StringPrototype.cpp index 0b11c24..9c58f85 100644 --- a/JavaScriptCore/runtime/StringPrototype.cpp +++ b/JavaScriptCore/runtime/StringPrototype.cpp @@ -37,36 +37,36 @@ namespace JSC { ASSERT_CLASS_FITS_IN_CELL(StringPrototype); -static JSValue* stringProtoFuncToString(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* stringProtoFuncCharAt(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* stringProtoFuncCharCodeAt(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* stringProtoFuncConcat(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* stringProtoFuncIndexOf(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* stringProtoFuncLastIndexOf(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* stringProtoFuncMatch(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* stringProtoFuncReplace(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* stringProtoFuncSearch(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* stringProtoFuncSlice(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* stringProtoFuncSplit(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* stringProtoFuncSubstr(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* stringProtoFuncSubstring(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* stringProtoFuncToLowerCase(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* stringProtoFuncToUpperCase(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* stringProtoFuncLocaleCompare(ExecState*, JSObject*, JSValue*, const ArgList&); - -static JSValue* stringProtoFuncBig(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* stringProtoFuncSmall(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* stringProtoFuncBlink(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* stringProtoFuncBold(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* stringProtoFuncFixed(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* stringProtoFuncItalics(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* stringProtoFuncStrike(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* stringProtoFuncSub(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* stringProtoFuncSup(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* stringProtoFuncFontcolor(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* stringProtoFuncFontsize(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* stringProtoFuncAnchor(ExecState*, JSObject*, JSValue*, const ArgList&); -static JSValue* stringProtoFuncLink(ExecState*, JSObject*, JSValue*, const ArgList&); +static JSValuePtr stringProtoFuncToString(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr stringProtoFuncCharAt(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr stringProtoFuncCharCodeAt(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr stringProtoFuncConcat(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr stringProtoFuncIndexOf(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr stringProtoFuncLastIndexOf(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr stringProtoFuncMatch(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr stringProtoFuncReplace(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr stringProtoFuncSearch(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr stringProtoFuncSlice(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr stringProtoFuncSplit(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr stringProtoFuncSubstr(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr stringProtoFuncSubstring(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr stringProtoFuncToLowerCase(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr stringProtoFuncToUpperCase(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr stringProtoFuncLocaleCompare(ExecState*, JSObject*, JSValuePtr, const ArgList&); + +static JSValuePtr stringProtoFuncBig(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr stringProtoFuncSmall(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr stringProtoFuncBlink(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr stringProtoFuncBold(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr stringProtoFuncFixed(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr stringProtoFuncItalics(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr stringProtoFuncStrike(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr stringProtoFuncSub(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr stringProtoFuncSup(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr stringProtoFuncFontcolor(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr stringProtoFuncFontsize(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr stringProtoFuncAnchor(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValuePtr stringProtoFuncLink(ExecState*, JSObject*, JSValuePtr, const ArgList&); } @@ -117,7 +117,7 @@ const ClassInfo StringPrototype::info = { "String", &StringObject::info, 0, Exec */ // ECMA 15.5.4 -StringPrototype::StringPrototype(ExecState* exec, PassRefPtr<StructureID> structure) +StringPrototype::StringPrototype(ExecState* exec, PassRefPtr<Structure> structure) : StringObject(exec, structure) { // The constructor will be added later, after StringConstructor has been built @@ -140,13 +140,12 @@ static inline UString substituteBackreferences(const UString& replacement, const if (i + 1 == replacement.size()) break; - unsigned short ref = replacement[i + 1]; + UChar ref = replacement[i + 1]; if (ref == '$') { // "$$" -> "$" ++i; substitutedReplacement.append(replacement.data() + offset, i - offset); offset = i + 1; - substitutedReplacement.append('$'); continue; } @@ -162,7 +161,7 @@ static inline UString substituteBackreferences(const UString& replacement, const } else if (ref == '\'') { backrefStart = ovector[1]; backrefLength = source.size() - backrefStart; - } else if (ref >= '0' && ref <= '9') { + } else if (reg && ref >= '0' && ref <= '9') { // 1- and 2-digit back references are allowed unsigned backrefIndex = ref - '0'; if (backrefIndex > reg->numSubpatterns()) @@ -177,6 +176,8 @@ static inline UString substituteBackreferences(const UString& replacement, const advance = 1; } } + if (!backrefIndex) + continue; backrefStart = ovector[2 * backrefIndex]; backrefLength = ovector[2 * backrefIndex + 1] - backrefStart; } else @@ -203,25 +204,25 @@ static inline int localeCompare(const UString& a, const UString& b) return Collator::userDefault()->collate(reinterpret_cast<const ::UChar*>(a.data()), a.size(), reinterpret_cast<const ::UChar*>(b.data()), b.size()); } -JSValue* stringProtoFuncReplace(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) +JSValuePtr stringProtoFuncReplace(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) { - JSString* sourceVal = thisValue->toThisJSString(exec); + JSString* sourceVal = thisValue.toThisJSString(exec); const UString& source = sourceVal->value(); - JSValue* pattern = args.at(exec, 0); + JSValuePtr pattern = args.at(exec, 0); - JSValue* replacement = args.at(exec, 1); + JSValuePtr replacement = args.at(exec, 1); UString replacementString; CallData callData; - CallType callType = replacement->getCallData(callData); + CallType callType = replacement.getCallData(callData); if (callType == CallTypeNone) - replacementString = replacement->toString(exec); + replacementString = replacement.toString(exec); - if (pattern->isObject(&RegExpObject::info)) { + if (pattern.isObject(&RegExpObject::info)) { RegExp* reg = asRegExpObject(pattern)->regExp(); bool global = reg->global(); - RegExpConstructor* regExpObj = exec->lexicalGlobalObject()->regExpConstructor(); + RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor(); int lastIndex = 0; int startPosition = 0; @@ -234,7 +235,7 @@ JSValue* stringProtoFuncReplace(ExecState* exec, JSObject*, JSValue* thisValue, int matchIndex; int matchLen; int* ovector; - regExpObj->performMatch(reg, source, startPosition, matchIndex, matchLen, &ovector); + regExpConstructor->performMatch(reg, source, startPosition, matchIndex, matchLen, &ovector); if (matchIndex < 0) break; @@ -257,7 +258,7 @@ JSValue* stringProtoFuncReplace(ExecState* exec, JSObject*, JSValue* thisValue, args.append(jsNumber(exec, completeMatchStart)); args.append(sourceVal); - replacements.append(call(exec, replacement, callType, callData, exec->globalThisValue(), args)->toString(exec)); + replacements.append(call(exec, replacement, callType, callData, exec->globalThisValue(), args).toString(exec)); if (exec->hadException()) break; } else @@ -286,7 +287,7 @@ JSValue* stringProtoFuncReplace(ExecState* exec, JSObject*, JSValue* thisValue, } // First arg is a string - UString patternString = pattern->toString(exec); + UString patternString = pattern.toString(exec); int matchPos = source.find(patternString); int matchLen = patternString.size(); // Do the replacement @@ -299,95 +300,107 @@ JSValue* stringProtoFuncReplace(ExecState* exec, JSObject*, JSValue* thisValue, args.append(jsNumber(exec, matchPos)); args.append(sourceVal); - replacementString = call(exec, replacement, callType, callData, exec->globalThisValue(), args)->toString(exec); + replacementString = call(exec, replacement, callType, callData, exec->globalThisValue(), args).toString(exec); } - return jsString(exec, source.substr(0, matchPos) + replacementString + source.substr(matchPos + matchLen)); + int ovector[2] = { matchPos, matchPos + matchLen }; + return jsString(exec, source.substr(0, matchPos) + + substituteBackreferences(replacementString, source, ovector, 0) + + source.substr(matchPos + matchLen)); } -JSValue* stringProtoFuncToString(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&) +JSValuePtr stringProtoFuncToString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) { // Also used for valueOf. - if (thisValue->isString()) + if (thisValue.isString()) return thisValue; - if (thisValue->isObject(&StringObject::info)) + if (thisValue.isObject(&StringObject::info)) return asStringObject(thisValue)->internalValue(); return throwError(exec, TypeError); } -JSValue* stringProtoFuncCharAt(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) +JSValuePtr stringProtoFuncCharAt(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) { - UString s = thisValue->toThisString(exec); + UString s = thisValue.toThisString(exec); unsigned len = s.size(); - JSValue* a0 = args.at(exec, 0); - if (JSImmediate::isNumber(a0)) { - uint32_t i; - if (JSImmediate::getUInt32(a0, i) && i < len) + JSValuePtr a0 = args.at(exec, 0); + if (a0.isUInt32Fast()) { + uint32_t i = a0.getUInt32Fast(); + if (i < len) return jsSingleCharacterSubstring(exec, s, i); return jsEmptyString(exec); } - double dpos = a0->toInteger(exec); + double dpos = a0.toInteger(exec); if (dpos >= 0 && dpos < len) return jsSingleCharacterSubstring(exec, s, static_cast<unsigned>(dpos)); return jsEmptyString(exec); } -JSValue* stringProtoFuncCharCodeAt(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) +JSValuePtr stringProtoFuncCharCodeAt(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) { - UString s = thisValue->toThisString(exec); + UString s = thisValue.toThisString(exec); unsigned len = s.size(); - JSValue* a0 = args.at(exec, 0); - if (JSImmediate::isNumber(a0)) { - uint32_t i; - if (JSImmediate::getUInt32(a0, i) && i < len) + JSValuePtr a0 = args.at(exec, 0); + if (a0.isUInt32Fast()) { + uint32_t i = a0.getUInt32Fast(); + if (i < len) return jsNumber(exec, s.data()[i]); return jsNaN(exec); } - double dpos = a0->toInteger(exec); + double dpos = a0.toInteger(exec); if (dpos >= 0 && dpos < len) return jsNumber(exec, s[static_cast<int>(dpos)]); return jsNaN(exec); } -JSValue* stringProtoFuncConcat(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) +JSValuePtr stringProtoFuncConcat(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) { - UString s = thisValue->toThisString(exec); + UString s = thisValue.toThisString(exec); ArgList::const_iterator end = args.end(); for (ArgList::const_iterator it = args.begin(); it != end; ++it) - s += (*it).jsValue(exec)->toString(exec); + s += (*it).jsValue(exec).toString(exec); return jsString(exec, s); } -JSValue* stringProtoFuncIndexOf(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) +JSValuePtr stringProtoFuncIndexOf(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) { - UString s = thisValue->toThisString(exec); + UString s = thisValue.toThisString(exec); int len = s.size(); - JSValue* a0 = args.at(exec, 0); - JSValue* a1 = args.at(exec, 1); - UString u2 = a0->toString(exec); - double dpos = a1->toInteger(exec); - if (dpos < 0) - dpos = 0; - else if (dpos > len) - dpos = len; - return jsNumber(exec, s.find(u2, static_cast<int>(dpos))); + JSValuePtr a0 = args.at(exec, 0); + JSValuePtr a1 = args.at(exec, 1); + UString u2 = a0.toString(exec); + int pos; + if (a1.isUndefined()) + pos = 0; + else if (a1.isUInt32Fast()) + pos = min<uint32_t>(a1.getUInt32Fast(), len); + else { + double dpos = a1.toInteger(exec); + if (dpos < 0) + dpos = 0; + else if (dpos > len) + dpos = len; + pos = static_cast<int>(dpos); + } + + return jsNumber(exec, s.find(u2, pos)); } -JSValue* stringProtoFuncLastIndexOf(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) +JSValuePtr stringProtoFuncLastIndexOf(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) { - UString s = thisValue->toThisString(exec); + UString s = thisValue.toThisString(exec); int len = s.size(); - JSValue* a0 = args.at(exec, 0); - JSValue* a1 = args.at(exec, 1); + JSValuePtr a0 = args.at(exec, 0); + JSValuePtr a1 = args.at(exec, 1); - UString u2 = a0->toString(exec); - double dpos = a1->toIntegerPreserveNaN(exec); + UString u2 = a0.toString(exec); + double dpos = a1.toIntegerPreserveNaN(exec); if (dpos < 0) dpos = 0; else if (!(dpos <= len)) // true for NaN @@ -395,16 +408,16 @@ JSValue* stringProtoFuncLastIndexOf(ExecState* exec, JSObject*, JSValue* thisVal return jsNumber(exec, s.rfind(u2, static_cast<int>(dpos))); } -JSValue* stringProtoFuncMatch(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) +JSValuePtr stringProtoFuncMatch(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) { - UString s = thisValue->toThisString(exec); + UString s = thisValue.toThisString(exec); - JSValue* a0 = args.at(exec, 0); + JSValuePtr a0 = args.at(exec, 0); UString u = s; RefPtr<RegExp> reg; RegExpObject* imp = 0; - if (a0->isObject(&RegExpObject::info)) + if (a0.isObject(&RegExpObject::info)) reg = asRegExpObject(a0)->regExp(); else { /* @@ -412,17 +425,17 @@ JSValue* stringProtoFuncMatch(ExecState* exec, JSObject*, JSValue* thisValue, co * If regexp is not an object whose [[Class]] property is "RegExp", it is * replaced with the result of the expression new RegExp(regexp). */ - reg = RegExp::create(&exec->globalData(), a0->toString(exec)); + reg = RegExp::create(&exec->globalData(), a0.toString(exec)); } - RegExpConstructor* regExpObj = exec->lexicalGlobalObject()->regExpConstructor(); + RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor(); int pos; int matchLength; - regExpObj->performMatch(reg.get(), u, 0, pos, matchLength); + regExpConstructor->performMatch(reg.get(), u, 0, pos, matchLength); if (!(reg->global())) { // case without 'g' flag is handled like RegExp.prototype.exec if (pos < 0) return jsNull(); - return regExpObj->arrayOfMatches(exec); + return regExpConstructor->arrayOfMatches(exec); } // return array of matches @@ -432,7 +445,7 @@ JSValue* stringProtoFuncMatch(ExecState* exec, JSObject*, JSValue* thisValue, co list.append(jsSubstring(exec, u, pos, matchLength)); lastIndex = pos; pos += matchLength == 0 ? 1 : matchLength; - regExpObj->performMatch(reg.get(), u, pos, pos, matchLength); + regExpConstructor->performMatch(reg.get(), u, pos, pos, matchLength); } if (imp) imp->setLastIndex(lastIndex); @@ -446,15 +459,15 @@ JSValue* stringProtoFuncMatch(ExecState* exec, JSObject*, JSValue* thisValue, co return constructArray(exec, list); } -JSValue* stringProtoFuncSearch(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) +JSValuePtr stringProtoFuncSearch(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) { - UString s = thisValue->toThisString(exec); + UString s = thisValue.toThisString(exec); - JSValue* a0 = args.at(exec, 0); + JSValuePtr a0 = args.at(exec, 0); UString u = s; RefPtr<RegExp> reg; - if (a0->isObject(&RegExpObject::info)) + if (a0.isObject(&RegExpObject::info)) reg = asRegExpObject(a0)->regExp(); else { /* @@ -462,26 +475,26 @@ JSValue* stringProtoFuncSearch(ExecState* exec, JSObject*, JSValue* thisValue, c * If regexp is not an object whose [[Class]] property is "RegExp", it is * replaced with the result of the expression new RegExp(regexp). */ - reg = RegExp::create(&exec->globalData(), a0->toString(exec)); + reg = RegExp::create(&exec->globalData(), a0.toString(exec)); } - RegExpConstructor* regExpObj = exec->lexicalGlobalObject()->regExpConstructor(); + RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor(); int pos; int matchLength; - regExpObj->performMatch(reg.get(), u, 0, pos, matchLength); + regExpConstructor->performMatch(reg.get(), u, 0, pos, matchLength); return jsNumber(exec, pos); } -JSValue* stringProtoFuncSlice(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) +JSValuePtr stringProtoFuncSlice(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) { - UString s = thisValue->toThisString(exec); + UString s = thisValue.toThisString(exec); int len = s.size(); - JSValue* a0 = args.at(exec, 0); - JSValue* a1 = args.at(exec, 1); + JSValuePtr a0 = args.at(exec, 0); + JSValuePtr a1 = args.at(exec, 1); // The arg processing is very much like ArrayProtoFunc::Slice - double start = a0->toInteger(exec); - double end = a1->isUndefined() ? len : a1->toInteger(exec); + double start = a0.toInteger(exec); + double end = a1.isUndefined() ? len : a1.toInteger(exec); double from = start < 0 ? len + start : start; double to = end < 0 ? len + end : end; if (to > from && to > 0 && from < len) { @@ -495,18 +508,18 @@ JSValue* stringProtoFuncSlice(ExecState* exec, JSObject*, JSValue* thisValue, co return jsEmptyString(exec); } -JSValue* stringProtoFuncSplit(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) +JSValuePtr stringProtoFuncSplit(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) { - UString s = thisValue->toThisString(exec); + UString s = thisValue.toThisString(exec); - JSValue* a0 = args.at(exec, 0); - JSValue* a1 = args.at(exec, 1); + JSValuePtr a0 = args.at(exec, 0); + JSValuePtr a1 = args.at(exec, 1); JSArray* result = constructEmptyArray(exec); unsigned i = 0; int p0 = 0; - unsigned limit = a1->isUndefined() ? 0xFFFFFFFFU : a1->toUInt32(exec); - if (a0->isObject(&RegExpObject::info)) { + unsigned limit = a1.isUndefined() ? 0xFFFFFFFFU : a1.toUInt32(exec); + if (a0.isObject(&RegExpObject::info)) { RegExp* reg = asRegExpObject(a0)->regExp(); if (s.isEmpty() && reg->match(s, 0) >= 0) { // empty string matched by regexp -> empty array @@ -533,7 +546,7 @@ JSValue* stringProtoFuncSplit(ExecState* exec, JSObject*, JSValue* thisValue, co } } } else { - UString u2 = a0->toString(exec); + UString u2 = a0.toString(exec); if (u2.isEmpty()) { if (s.isEmpty()) { // empty separator matches empty string -> empty array @@ -557,16 +570,16 @@ JSValue* stringProtoFuncSplit(ExecState* exec, JSObject*, JSValue* thisValue, co return result; } -JSValue* stringProtoFuncSubstr(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) +JSValuePtr stringProtoFuncSubstr(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) { - UString s = thisValue->toThisString(exec); + UString s = thisValue.toThisString(exec); int len = s.size(); - JSValue* a0 = args.at(exec, 0); - JSValue* a1 = args.at(exec, 1); + JSValuePtr a0 = args.at(exec, 0); + JSValuePtr a1 = args.at(exec, 1); - double start = a0->toInteger(exec); - double length = a1->isUndefined() ? len : a1->toInteger(exec); + double start = a0.toInteger(exec); + double length = a1.isUndefined() ? len : a1.toInteger(exec); if (start >= len || length <= 0) return jsEmptyString(exec); if (start < 0) { @@ -579,16 +592,16 @@ JSValue* stringProtoFuncSubstr(ExecState* exec, JSObject*, JSValue* thisValue, c return jsSubstring(exec, s, static_cast<unsigned>(start), static_cast<unsigned>(length)); } -JSValue* stringProtoFuncSubstring(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) +JSValuePtr stringProtoFuncSubstring(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) { - UString s = thisValue->toThisString(exec); + UString s = thisValue.toThisString(exec); int len = s.size(); - JSValue* a0 = args.at(exec, 0); - JSValue* a1 = args.at(exec, 1); + JSValuePtr a0 = args.at(exec, 0); + JSValuePtr a1 = args.at(exec, 1); - double start = a0->toNumber(exec); - double end = a1->toNumber(exec); + double start = a0.toNumber(exec); + double end = a1.toNumber(exec); if (isnan(start)) start = 0; if (isnan(end)) @@ -601,7 +614,7 @@ JSValue* stringProtoFuncSubstring(ExecState* exec, JSObject*, JSValue* thisValue start = len; if (end > len) end = len; - if (a1->isUndefined()) + if (a1.isUndefined()) end = len; if (start > end) { double temp = end; @@ -611,9 +624,9 @@ JSValue* stringProtoFuncSubstring(ExecState* exec, JSObject*, JSValue* thisValue return jsSubstring(exec, s, static_cast<unsigned>(start), static_cast<unsigned>(end) - static_cast<unsigned>(start)); } -JSValue* stringProtoFuncToLowerCase(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&) +JSValuePtr stringProtoFuncToLowerCase(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) { - JSString* sVal = thisValue->toThisJSString(exec); + JSString* sVal = thisValue.toThisJSString(exec); const UString& s = sVal->value(); int sSize = s.size(); @@ -645,9 +658,9 @@ JSValue* stringProtoFuncToLowerCase(ExecState* exec, JSObject*, JSValue* thisVal return jsString(exec, UString(buffer.releaseBuffer(), length, false)); } -JSValue* stringProtoFuncToUpperCase(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&) +JSValuePtr stringProtoFuncToUpperCase(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) { - JSString* sVal = thisValue->toThisJSString(exec); + JSString* sVal = thisValue.toThisJSString(exec); const UString& s = sVal->value(); int sSize = s.size(); @@ -679,96 +692,155 @@ JSValue* stringProtoFuncToUpperCase(ExecState* exec, JSObject*, JSValue* thisVal return jsString(exec, UString(buffer.releaseBuffer(), length, false)); } -JSValue* stringProtoFuncLocaleCompare(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) +JSValuePtr stringProtoFuncLocaleCompare(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) { if (args.size() < 1) return jsNumber(exec, 0); - UString s = thisValue->toThisString(exec); - JSValue* a0 = args.at(exec, 0); - return jsNumber(exec, localeCompare(s, a0->toString(exec))); + UString s = thisValue.toThisString(exec); + JSValuePtr a0 = args.at(exec, 0); + return jsNumber(exec, localeCompare(s, a0.toString(exec))); } -JSValue* stringProtoFuncBig(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&) +JSValuePtr stringProtoFuncBig(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) { - UString s = thisValue->toThisString(exec); - return jsString(exec, "<big>" + s + "</big>"); + UString s = thisValue.toThisString(exec); + return jsNontrivialString(exec, "<big>" + s + "</big>"); } -JSValue* stringProtoFuncSmall(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&) +JSValuePtr stringProtoFuncSmall(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) { - UString s = thisValue->toThisString(exec); - return jsString(exec, "<small>" + s + "</small>"); + UString s = thisValue.toThisString(exec); + return jsNontrivialString(exec, "<small>" + s + "</small>"); } -JSValue* stringProtoFuncBlink(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&) +JSValuePtr stringProtoFuncBlink(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) { - UString s = thisValue->toThisString(exec); - return jsString(exec, "<blink>" + s + "</blink>"); + UString s = thisValue.toThisString(exec); + return jsNontrivialString(exec, "<blink>" + s + "</blink>"); } -JSValue* stringProtoFuncBold(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&) +JSValuePtr stringProtoFuncBold(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) { - UString s = thisValue->toThisString(exec); - return jsString(exec, "<b>" + s + "</b>"); + UString s = thisValue.toThisString(exec); + return jsNontrivialString(exec, "<b>" + s + "</b>"); } -JSValue* stringProtoFuncFixed(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&) +JSValuePtr stringProtoFuncFixed(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) { - UString s = thisValue->toThisString(exec); + UString s = thisValue.toThisString(exec); return jsString(exec, "<tt>" + s + "</tt>"); } -JSValue* stringProtoFuncItalics(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&) +JSValuePtr stringProtoFuncItalics(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) { - UString s = thisValue->toThisString(exec); - return jsString(exec, "<i>" + s + "</i>"); + UString s = thisValue.toThisString(exec); + return jsNontrivialString(exec, "<i>" + s + "</i>"); } -JSValue* stringProtoFuncStrike(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&) +JSValuePtr stringProtoFuncStrike(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) { - UString s = thisValue->toThisString(exec); - return jsString(exec, "<strike>" + s + "</strike>"); + UString s = thisValue.toThisString(exec); + return jsNontrivialString(exec, "<strike>" + s + "</strike>"); } -JSValue* stringProtoFuncSub(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&) +JSValuePtr stringProtoFuncSub(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) { - UString s = thisValue->toThisString(exec); - return jsString(exec, "<sub>" + s + "</sub>"); + UString s = thisValue.toThisString(exec); + return jsNontrivialString(exec, "<sub>" + s + "</sub>"); } -JSValue* stringProtoFuncSup(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&) +JSValuePtr stringProtoFuncSup(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) { - UString s = thisValue->toThisString(exec); - return jsString(exec, "<sup>" + s + "</sup>"); + UString s = thisValue.toThisString(exec); + return jsNontrivialString(exec, "<sup>" + s + "</sup>"); } -JSValue* stringProtoFuncFontcolor(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) +JSValuePtr stringProtoFuncFontcolor(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) { - UString s = thisValue->toThisString(exec); - JSValue* a0 = args.at(exec, 0); - return jsString(exec, "<font color=\"" + a0->toString(exec) + "\">" + s + "</font>"); + UString s = thisValue.toThisString(exec); + JSValuePtr a0 = args.at(exec, 0); + return jsNontrivialString(exec, "<font color=\"" + a0.toString(exec) + "\">" + s + "</font>"); } -JSValue* stringProtoFuncFontsize(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) +JSValuePtr stringProtoFuncFontsize(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) { - UString s = thisValue->toThisString(exec); - JSValue* a0 = args.at(exec, 0); - return jsString(exec, "<font size=\"" + a0->toString(exec) + "\">" + s + "</font>"); -} + UString s = thisValue.toThisString(exec); + JSValuePtr a0 = args.at(exec, 0); -JSValue* stringProtoFuncAnchor(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) -{ - UString s = thisValue->toThisString(exec); - JSValue* a0 = args.at(exec, 0); - return jsString(exec, "<a name=\"" + a0->toString(exec) + "\">" + s + "</a>"); -} + uint32_t smallInteger; + if (a0.getUInt32(smallInteger) && smallInteger <= 9) { + unsigned stringSize = s.size(); + unsigned bufferSize = 22 + stringSize; + UChar* buffer = static_cast<UChar*>(tryFastMalloc(bufferSize * sizeof(UChar))); + if (!buffer) + return jsUndefined(); + buffer[0] = '<'; + buffer[1] = 'f'; + buffer[2] = 'o'; + buffer[3] = 'n'; + buffer[4] = 't'; + buffer[5] = ' '; + buffer[6] = 's'; + buffer[7] = 'i'; + buffer[8] = 'z'; + buffer[9] = 'e'; + buffer[10] = '='; + buffer[11] = '"'; + buffer[12] = '0' + smallInteger; + buffer[13] = '"'; + buffer[14] = '>'; + memcpy(&buffer[15], s.data(), stringSize * sizeof(UChar)); + buffer[15 + stringSize] = '<'; + buffer[16 + stringSize] = '/'; + buffer[17 + stringSize] = 'f'; + buffer[18 + stringSize] = 'o'; + buffer[19 + stringSize] = 'n'; + buffer[20 + stringSize] = 't'; + buffer[21 + stringSize] = '>'; + return jsNontrivialString(exec, UString(buffer, bufferSize, false)); + } -JSValue* stringProtoFuncLink(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) -{ - UString s = thisValue->toThisString(exec); - JSValue* a0 = args.at(exec, 0); - return jsString(exec, "<a href=\"" + a0->toString(exec) + "\">" + s + "</a>"); + return jsNontrivialString(exec, "<font size=\"" + a0.toString(exec) + "\">" + s + "</font>"); +} + +JSValuePtr stringProtoFuncAnchor(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) +{ + UString s = thisValue.toThisString(exec); + JSValuePtr a0 = args.at(exec, 0); + return jsNontrivialString(exec, "<a name=\"" + a0.toString(exec) + "\">" + s + "</a>"); +} + +JSValuePtr stringProtoFuncLink(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) +{ + UString s = thisValue.toThisString(exec); + JSValuePtr a0 = args.at(exec, 0); + UString linkText = a0.toString(exec); + + unsigned linkTextSize = linkText.size(); + unsigned stringSize = s.size(); + unsigned bufferSize = 15 + linkTextSize + stringSize; + UChar* buffer = static_cast<UChar*>(tryFastMalloc(bufferSize * sizeof(UChar))); + if (!buffer) + return jsUndefined(); + buffer[0] = '<'; + buffer[1] = 'a'; + buffer[2] = ' '; + buffer[3] = 'h'; + buffer[4] = 'r'; + buffer[5] = 'e'; + buffer[6] = 'f'; + buffer[7] = '='; + buffer[8] = '"'; + memcpy(&buffer[9], linkText.data(), linkTextSize * sizeof(UChar)); + buffer[9 + linkTextSize] = '"'; + buffer[10 + linkTextSize] = '>'; + memcpy(&buffer[11 + linkTextSize], s.data(), stringSize * sizeof(UChar)); + buffer[11 + linkTextSize + stringSize] = '<'; + buffer[12 + linkTextSize + stringSize] = '/'; + buffer[13 + linkTextSize + stringSize] = 'a'; + buffer[14 + linkTextSize + stringSize] = '>'; + return jsNontrivialString(exec, UString(buffer, bufferSize, false)); } } // namespace JSC diff --git a/JavaScriptCore/runtime/StringPrototype.h b/JavaScriptCore/runtime/StringPrototype.h index b127885..6f5344e 100644 --- a/JavaScriptCore/runtime/StringPrototype.h +++ b/JavaScriptCore/runtime/StringPrototype.h @@ -29,7 +29,7 @@ namespace JSC { class StringPrototype : public StringObject { public: - StringPrototype(ExecState*, PassRefPtr<StructureID>); + StringPrototype(ExecState*, PassRefPtr<Structure>); virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); diff --git a/JavaScriptCore/runtime/StructureID.cpp b/JavaScriptCore/runtime/Structure.cpp index 8333595..86ee76c 100644 --- a/JavaScriptCore/runtime/StructureID.cpp +++ b/JavaScriptCore/runtime/Structure.cpp @@ -24,13 +24,13 @@ */ #include "config.h" -#include "StructureID.h" +#include "Structure.h" +#include "Identifier.h" #include "JSObject.h" #include "PropertyNameArray.h" -#include "StructureIDChain.h" -#include "identifier.h" -#include "lookup.h" +#include "StructureChain.h" +#include "Lookup.h" #include <wtf/RefCountedLeakCounter.h> #include <wtf/RefPtr.h> @@ -47,7 +47,7 @@ #endif using namespace std; -using WTF::doubleHash; +using namespace WTF; namespace JSC { @@ -59,76 +59,84 @@ static const int smallMapThreshold = 1024; // becomes small compared to the inefficiency of insertion sort. static const unsigned tinyMapThreshold = 20; +static const unsigned newTableSize = 16; + #ifndef NDEBUG -static WTF::RefCountedLeakCounter structureIDCounter("StructureID"); +static WTF::RefCountedLeakCounter structureCounter("Structure"); #if ENABLE(JSC_MULTIPLE_THREADS) static Mutex ignoreSetMutex; #endif static bool shouldIgnoreLeaks; -static HashSet<StructureID*> ignoreSet; +static HashSet<Structure*> ignoreSet; #endif #if DUMP_STRUCTURE_ID_STATISTICS -static HashSet<StructureID*> liveStructureIDSet; +static HashSet<Structure*> liveStructureSet; #endif -void StructureID::dumpStatistics() +void Structure::dumpStatistics() { #if DUMP_STRUCTURE_ID_STATISTICS unsigned numberLeaf = 0; unsigned numberUsingSingleSlot = 0; unsigned numberSingletons = 0; + unsigned numberWithPropertyMaps = 0; unsigned totalPropertyMapsSize = 0; - HashSet<StructureID*>::const_iterator end = liveStructureIDSet.end(); - for (HashSet<StructureID*>::const_iterator it = liveStructureIDSet.begin(); it != end; ++it) { - StructureID* structureID = *it; - if (structureID->m_usingSingleTransitionSlot) { - if (!structureID->m_transitions.singleTransition) + HashSet<Structure*>::const_iterator end = liveStructureSet.end(); + for (HashSet<Structure*>::const_iterator it = liveStructureSet.begin(); it != end; ++it) { + Structure* structure = *it; + if (structure->m_usingSingleTransitionSlot) { + if (!structure->m_transitions.singleTransition) ++numberLeaf; else ++numberUsingSingleSlot; - if (!structureID->m_previous && !structureID->m_transitions.singleTransition) + if (!structure->m_previous && !structure->m_transitions.singleTransition) ++numberSingletons; } - if (structureID->m_propertyTable) - totalPropertyMapsSize += PropertyMapHashTable::allocationSize(structureID->m_propertyTable->size); + if (structure->m_propertyTable) { + ++numberWithPropertyMaps; + totalPropertyMapsSize += PropertyMapHashTable::allocationSize(structure->m_propertyTable->size); + if (structure->m_propertyTable->deletedOffsets) + totalPropertyMapsSize += (structure->m_propertyTable->deletedOffsets->capacity() * sizeof(unsigned)); + } } - printf("Number of live StructureIDs: %d\n", liveStructureIDSet.size()); - printf("Number of StructureIDs using the single item optimization for transition map: %d\n", numberUsingSingleSlot); - printf("Number of StructureIDs that are leaf nodes: %d\n", numberLeaf); - printf("Number of StructureIDs that singletons: %d\n", numberSingletons); + printf("Number of live Structures: %d\n", liveStructureSet.size()); + printf("Number of Structures using the single item optimization for transition map: %d\n", numberUsingSingleSlot); + printf("Number of Structures that are leaf nodes: %d\n", numberLeaf); + printf("Number of Structures that singletons: %d\n", numberSingletons); + printf("Number of Structures with PropertyMaps: %d\n", numberWithPropertyMaps); - printf("Size of a single StructureIDs: %d\n", static_cast<unsigned>(sizeof(StructureID))); + printf("Size of a single Structures: %d\n", static_cast<unsigned>(sizeof(Structure))); printf("Size of sum of all property maps: %d\n", totalPropertyMapsSize); - printf("Size of average of all property maps: %f\n", static_cast<double>(totalPropertyMapsSize) / static_cast<double>(liveStructureIDSet.size())); + printf("Size of average of all property maps: %f\n", static_cast<double>(totalPropertyMapsSize) / static_cast<double>(liveStructureSet.size())); #else - printf("Dumping StructureID statistics is not enabled.\n"); + printf("Dumping Structure statistics is not enabled.\n"); #endif } -StructureID::StructureID(JSValue* prototype, const TypeInfo& typeInfo) +Structure::Structure(JSValuePtr prototype, const TypeInfo& typeInfo) : m_typeInfo(typeInfo) , m_prototype(prototype) , m_cachedPrototypeChain(0) , m_previous(0) , m_nameInPrevious(0) - , m_transitionCount(0) , m_propertyTable(0) , m_propertyStorageCapacity(JSObject::inlineStorageCapacity) - , m_cachedTransistionOffset(WTF::notFound) + , m_offset(noOffset) , m_isDictionary(false) + , m_isPinnedPropertyTable(false) , m_hasGetterSetterProperties(false) , m_usingSingleTransitionSlot(true) , m_attributesInPrevious(0) { ASSERT(m_prototype); - ASSERT(m_prototype->isObject() || m_prototype->isNull()); + ASSERT(m_prototype.isObject() || m_prototype.isNull()); m_transitions.singleTransition = 0; @@ -139,27 +147,27 @@ StructureID::StructureID(JSValue* prototype, const TypeInfo& typeInfo) if (shouldIgnoreLeaks) ignoreSet.add(this); else - structureIDCounter.increment(); + structureCounter.increment(); #endif #if DUMP_STRUCTURE_ID_STATISTICS - liveStructureIDSet.add(this); + liveStructureSet.add(this); #endif } -StructureID::~StructureID() +Structure::~Structure() { if (m_previous) { if (m_previous->m_usingSingleTransitionSlot) { m_previous->m_transitions.singleTransition = 0; } else { - ASSERT(m_previous->m_transitions.table->contains(make_pair(m_nameInPrevious, m_attributesInPrevious))); - m_previous->m_transitions.table->remove(make_pair(m_nameInPrevious, m_attributesInPrevious)); + ASSERT(m_previous->m_transitions.table->contains(make_pair(m_nameInPrevious.get(), m_attributesInPrevious))); + m_previous->m_transitions.table->remove(make_pair(m_nameInPrevious.get(), m_attributesInPrevious)); } } if (m_cachedPropertyNameArrayData) - m_cachedPropertyNameArrayData->setCachedStructureID(0); + m_cachedPropertyNameArrayData->setCachedStructure(0); if (!m_usingSingleTransitionSlot) delete m_transitions.table; @@ -170,6 +178,8 @@ StructureID::~StructureID() if (UString::Rep* key = m_propertyTable->entries()[i].key) key->deref(); } + + delete m_propertyTable->deletedOffsets; fastFree(m_propertyTable); } @@ -177,39 +187,113 @@ StructureID::~StructureID() #if ENABLE(JSC_MULTIPLE_THREADS) MutexLocker protect(ignoreSetMutex); #endif - HashSet<StructureID*>::iterator it = ignoreSet.find(this); + HashSet<Structure*>::iterator it = ignoreSet.find(this); if (it != ignoreSet.end()) ignoreSet.remove(it); else - structureIDCounter.decrement(); + structureCounter.decrement(); #endif #if DUMP_STRUCTURE_ID_STATISTICS - liveStructureIDSet.remove(this); + liveStructureSet.remove(this); #endif } -void StructureID::startIgnoringLeaks() +void Structure::startIgnoringLeaks() { #ifndef NDEBUG shouldIgnoreLeaks = true; #endif } -void StructureID::stopIgnoringLeaks() +void Structure::stopIgnoringLeaks() { #ifndef NDEBUG shouldIgnoreLeaks = false; #endif } -void StructureID::getEnumerablePropertyNames(ExecState* exec, PropertyNameArray& propertyNames, JSObject* baseObject) +static bool isPowerOf2(unsigned v) +{ + // Taken from http://www.cs.utk.edu/~vose/c-stuff/bithacks.html + + return !(v & (v - 1)) && v; +} + +static unsigned nextPowerOf2(unsigned v) +{ + // Taken from http://www.cs.utk.edu/~vose/c-stuff/bithacks.html + // Devised by Sean Anderson, Sepember 14, 2001 + + v--; + v |= v >> 1; + v |= v >> 2; + v |= v >> 4; + v |= v >> 8; + v |= v >> 16; + v++; + + return v; +} + +static unsigned sizeForKeyCount(size_t keyCount) +{ + if (keyCount == notFound) + return newTableSize; + + if (keyCount < 8) + return newTableSize; + + if (isPowerOf2(keyCount)) + return keyCount * 4; + + return nextPowerOf2(keyCount) * 2; +} + +void Structure::materializePropertyMap() +{ + ASSERT(!m_propertyTable); + + Vector<Structure*, 8> structures; + structures.append(this); + + Structure* structure = this; + + // Search for the last Structure with a property table. + while ((structure = structure->previousID())) { + if (structure->m_isPinnedPropertyTable) { + ASSERT(structure->m_propertyTable); + ASSERT(!structure->m_previous); + + m_propertyTable = structure->copyPropertyTable(); + break; + } + + structures.append(structure); + } + + if (!m_propertyTable) + createPropertyMapHashTable(sizeForKeyCount(m_offset + 1)); + else { + if (sizeForKeyCount(m_offset + 1) > m_propertyTable->size) + rehashPropertyMapHashTable(sizeForKeyCount(m_offset + 1)); // This could be made more efficient by combining with the copy above. + } + + for (ptrdiff_t i = structures.size() - 2; i >= 0; --i) { + structure = structures[i]; + structure->m_nameInPrevious->ref(); + PropertyMapEntry entry(structure->m_nameInPrevious.get(), structure->m_offset, structure->m_attributesInPrevious, ++m_propertyTable->lastIndexUsed); + insertIntoPropertyMapHashTable(entry); + } +} + +void Structure::getEnumerablePropertyNames(ExecState* exec, PropertyNameArray& propertyNames, JSObject* baseObject) { bool shouldCache = propertyNames.cacheable() && !(propertyNames.size() || m_isDictionary); if (shouldCache) { if (m_cachedPropertyNameArrayData) { - if (structureIDChainsAreEqual(m_cachedPropertyNameArrayData->cachedPrototypeChain(), cachedPrototypeChain())) { + if (structureChainsAreEqual(m_cachedPropertyNameArrayData->cachedPrototypeChain(), cachedPrototypeChain())) { propertyNames.setData(m_cachedPropertyNameArrayData); return; } @@ -226,7 +310,11 @@ void StructureID::getEnumerablePropertyNames(ExecState* exec, PropertyNameArray& continue; table->initializeIfNeeded(exec); ASSERT(table->table); +#if ENABLE(PERFECT_HASH_SIZE) int hashSizeMask = table->hashSizeMask; +#else + int hashSizeMask = table->compactSize - 1; +#endif const HashEntry* entry = table->table; for (int i = 0; i <= hashSizeMask; ++i, ++entry) { if (entry->key() && !(entry->attributes() & DontEnum)) @@ -234,31 +322,31 @@ void StructureID::getEnumerablePropertyNames(ExecState* exec, PropertyNameArray& } } - if (m_prototype->isObject()) + if (m_prototype.isObject()) asObject(m_prototype)->getPropertyNames(exec, propertyNames); if (shouldCache) { if (m_cachedPropertyNameArrayData) - m_cachedPropertyNameArrayData->setCachedStructureID(0); + m_cachedPropertyNameArrayData->setCachedStructure(0); m_cachedPropertyNameArrayData = propertyNames.data(); - StructureIDChain* chain = cachedPrototypeChain(); + StructureChain* chain = cachedPrototypeChain(); if (!chain) chain = createCachedPrototypeChain(); m_cachedPropertyNameArrayData->setCachedPrototypeChain(chain); - m_cachedPropertyNameArrayData->setCachedStructureID(this); + m_cachedPropertyNameArrayData->setCachedStructure(this); } } -void StructureID::clearEnumerationCache() +void Structure::clearEnumerationCache() { if (m_cachedPropertyNameArrayData) - m_cachedPropertyNameArrayData->setCachedStructureID(0); + m_cachedPropertyNameArrayData->setCachedStructure(0); m_cachedPropertyNameArrayData.clear(); } -void StructureID::growPropertyStorageCapacity() +void Structure::growPropertyStorageCapacity() { if (m_propertyStorageCapacity == JSObject::inlineStorageCapacity) m_propertyStorageCapacity = JSObject::nonInlineBaseStorageCapacity; @@ -266,131 +354,168 @@ void StructureID::growPropertyStorageCapacity() m_propertyStorageCapacity *= 2; } -PassRefPtr<StructureID> StructureID::addPropertyTransition(StructureID* structureID, const Identifier& propertyName, unsigned attributes, size_t& offset) +PassRefPtr<Structure> Structure::addPropertyTransitionToExistingStructure(Structure* structure, const Identifier& propertyName, unsigned attributes, size_t& offset) { - ASSERT(!structureID->m_isDictionary); - ASSERT(structureID->typeInfo().type() == ObjectType); - - if (structureID->m_usingSingleTransitionSlot) { - StructureID* existingTransition = structureID->m_transitions.singleTransition; - if (existingTransition && existingTransition->m_nameInPrevious == propertyName.ustring().rep() && existingTransition->m_attributesInPrevious == attributes) { - offset = structureID->m_transitions.singleTransition->cachedTransistionOffset(); - ASSERT(offset != WTF::notFound); + ASSERT(!structure->m_isDictionary); + ASSERT(structure->typeInfo().type() == ObjectType); + + if (structure->m_usingSingleTransitionSlot) { + Structure* existingTransition = structure->m_transitions.singleTransition; + if (existingTransition && existingTransition->m_nameInPrevious.get() == propertyName.ustring().rep() && existingTransition->m_attributesInPrevious == attributes) { + ASSERT(structure->m_transitions.singleTransition->m_offset != noOffset); + offset = structure->m_transitions.singleTransition->m_offset; return existingTransition; } } else { - if (StructureID* existingTransition = structureID->m_transitions.table->get(make_pair(propertyName.ustring().rep(), attributes))) { - offset = existingTransition->cachedTransistionOffset(); - ASSERT(offset != WTF::notFound); + if (Structure* existingTransition = structure->m_transitions.table->get(make_pair(propertyName.ustring().rep(), attributes))) { + ASSERT(existingTransition->m_offset != noOffset); + offset = existingTransition->m_offset; return existingTransition; - } + } } - if (structureID->m_transitionCount > s_maxTransitionLength) { - RefPtr<StructureID> transition = toDictionaryTransition(structureID); + return 0; +} + +PassRefPtr<Structure> Structure::addPropertyTransition(Structure* structure, const Identifier& propertyName, unsigned attributes, size_t& offset) +{ + ASSERT(!structure->m_isDictionary); + ASSERT(structure->typeInfo().type() == ObjectType); + ASSERT(!Structure::addPropertyTransitionToExistingStructure(structure, propertyName, attributes, offset)); + + if (structure->transitionCount() > s_maxTransitionLength) { + RefPtr<Structure> transition = toDictionaryTransition(structure); offset = transition->put(propertyName, attributes); if (transition->propertyStorageSize() > transition->propertyStorageCapacity()) transition->growPropertyStorageCapacity(); return transition.release(); } - RefPtr<StructureID> transition = create(structureID->m_prototype, structureID->typeInfo()); - transition->m_cachedPrototypeChain = structureID->m_cachedPrototypeChain; - transition->m_previous = structureID; + RefPtr<Structure> transition = create(structure->m_prototype, structure->typeInfo()); + transition->m_cachedPrototypeChain = structure->m_cachedPrototypeChain; + transition->m_previous = structure; transition->m_nameInPrevious = propertyName.ustring().rep(); transition->m_attributesInPrevious = attributes; - transition->m_transitionCount = structureID->m_transitionCount + 1; - transition->m_propertyTable = structureID->copyPropertyTable(); - transition->m_deletedOffsets = structureID->m_deletedOffsets; - transition->m_propertyStorageCapacity = structureID->m_propertyStorageCapacity; - transition->m_hasGetterSetterProperties = structureID->m_hasGetterSetterProperties; + transition->m_propertyStorageCapacity = structure->m_propertyStorageCapacity; + transition->m_hasGetterSetterProperties = structure->m_hasGetterSetterProperties; + + if (structure->m_propertyTable) { + if (structure->m_isPinnedPropertyTable) + transition->m_propertyTable = structure->copyPropertyTable(); + else { + transition->m_propertyTable = structure->m_propertyTable; + structure->m_propertyTable = 0; + } + } else { + if (structure->m_previous) + transition->materializePropertyMap(); + else + transition->createPropertyMapHashTable(); + } offset = transition->put(propertyName, attributes); if (transition->propertyStorageSize() > transition->propertyStorageCapacity()) transition->growPropertyStorageCapacity(); - transition->setCachedTransistionOffset(offset); + transition->m_offset = offset; - if (structureID->m_usingSingleTransitionSlot) { - if (!structureID->m_transitions.singleTransition) { - structureID->m_transitions.singleTransition = transition.get(); + if (structure->m_usingSingleTransitionSlot) { + if (!structure->m_transitions.singleTransition) { + structure->m_transitions.singleTransition = transition.get(); return transition.release(); } - StructureID* existingTransition = structureID->m_transitions.singleTransition; - structureID->m_usingSingleTransitionSlot = false; - StructureIDTransitionTable* transitionTable = new StructureIDTransitionTable; - structureID->m_transitions.table = transitionTable; - transitionTable->add(make_pair(existingTransition->m_nameInPrevious, existingTransition->m_attributesInPrevious), existingTransition); + Structure* existingTransition = structure->m_transitions.singleTransition; + structure->m_usingSingleTransitionSlot = false; + StructureTransitionTable* transitionTable = new StructureTransitionTable; + structure->m_transitions.table = transitionTable; + transitionTable->add(make_pair(existingTransition->m_nameInPrevious.get(), existingTransition->m_attributesInPrevious), existingTransition); } - structureID->m_transitions.table->add(make_pair(propertyName.ustring().rep(), attributes), transition.get()); + structure->m_transitions.table->add(make_pair(propertyName.ustring().rep(), attributes), transition.get()); return transition.release(); } -PassRefPtr<StructureID> StructureID::removePropertyTransition(StructureID* structureID, const Identifier& propertyName, size_t& offset) +PassRefPtr<Structure> Structure::removePropertyTransition(Structure* structure, const Identifier& propertyName, size_t& offset) { - ASSERT(!structureID->m_isDictionary); + ASSERT(!structure->m_isDictionary); - RefPtr<StructureID> transition = create(structureID->m_prototype, structureID->typeInfo()); - transition->m_isDictionary = true; - transition->m_propertyTable = structureID->copyPropertyTable(); - transition->m_deletedOffsets = structureID->m_deletedOffsets; - transition->m_propertyStorageCapacity = structureID->m_propertyStorageCapacity; - transition->m_hasGetterSetterProperties = structureID->m_hasGetterSetterProperties; + RefPtr<Structure> transition = toDictionaryTransition(structure); offset = transition->remove(propertyName); return transition.release(); } -PassRefPtr<StructureID> StructureID::toDictionaryTransition(StructureID* structureID) +PassRefPtr<Structure> Structure::changePrototypeTransition(Structure* structure, JSValuePtr prototype) { - ASSERT(!structureID->m_isDictionary); + RefPtr<Structure> transition = create(prototype, structure->typeInfo()); + + transition->m_propertyStorageCapacity = structure->m_propertyStorageCapacity; + transition->m_hasGetterSetterProperties = structure->m_hasGetterSetterProperties; + + // Don't set m_offset, as one can not transition to this. + + structure->materializePropertyMapIfNecessary(); + transition->m_propertyTable = structure->copyPropertyTable(); + transition->m_isPinnedPropertyTable = true; - RefPtr<StructureID> transition = create(structureID->m_prototype, structureID->typeInfo()); - transition->m_isDictionary = true; - transition->m_propertyTable = structureID->copyPropertyTable(); - transition->m_deletedOffsets = structureID->m_deletedOffsets; - transition->m_propertyStorageCapacity = structureID->m_propertyStorageCapacity; - transition->m_hasGetterSetterProperties = structureID->m_hasGetterSetterProperties; return transition.release(); } -PassRefPtr<StructureID> StructureID::fromDictionaryTransition(StructureID* structureID) +PassRefPtr<Structure> Structure::getterSetterTransition(Structure* structure) { - ASSERT(structureID->m_isDictionary); + RefPtr<Structure> transition = create(structure->storedPrototype(), structure->typeInfo()); + transition->m_propertyStorageCapacity = structure->m_propertyStorageCapacity; + transition->m_hasGetterSetterProperties = transition->m_hasGetterSetterProperties; - // Since dictionary StructureIDs are not shared, and no opcodes specialize - // for them, we don't need to allocate a new StructureID when transitioning - // to non-dictionary status. - structureID->m_isDictionary = false; - return structureID; + // Don't set m_offset, as one can not transition to this. + + structure->materializePropertyMapIfNecessary(); + transition->m_propertyTable = structure->copyPropertyTable(); + transition->m_isPinnedPropertyTable = true; + + return transition.release(); } -PassRefPtr<StructureID> StructureID::changePrototypeTransition(StructureID* structureID, JSValue* prototype) +PassRefPtr<Structure> Structure::toDictionaryTransition(Structure* structure) { - RefPtr<StructureID> transition = create(prototype, structureID->typeInfo()); - transition->m_transitionCount = structureID->m_transitionCount + 1; - transition->m_propertyTable = structureID->copyPropertyTable(); - transition->m_deletedOffsets = structureID->m_deletedOffsets; - transition->m_propertyStorageCapacity = structureID->m_propertyStorageCapacity; - transition->m_hasGetterSetterProperties = structureID->m_hasGetterSetterProperties; + ASSERT(!structure->m_isDictionary); + + RefPtr<Structure> transition = create(structure->m_prototype, structure->typeInfo()); + transition->m_isDictionary = true; + transition->m_propertyStorageCapacity = structure->m_propertyStorageCapacity; + transition->m_hasGetterSetterProperties = structure->m_hasGetterSetterProperties; + + structure->materializePropertyMapIfNecessary(); + transition->m_propertyTable = structure->copyPropertyTable(); + transition->m_isPinnedPropertyTable = true; + return transition.release(); } -PassRefPtr<StructureID> StructureID::getterSetterTransition(StructureID* structureID) +PassRefPtr<Structure> Structure::fromDictionaryTransition(Structure* structure) { - RefPtr<StructureID> transition = create(structureID->storedPrototype(), structureID->typeInfo()); - transition->m_transitionCount = structureID->m_transitionCount + 1; - transition->m_propertyTable = structureID->copyPropertyTable(); - transition->m_deletedOffsets = structureID->m_deletedOffsets; - transition->m_propertyStorageCapacity = structureID->m_propertyStorageCapacity; - transition->m_hasGetterSetterProperties = transition->m_hasGetterSetterProperties; - return transition.release(); + ASSERT(structure->m_isDictionary); + + // Since dictionary Structures are not shared, and no opcodes specialize + // for them, we don't need to allocate a new Structure when transitioning + // to non-dictionary status. + + // FIMXE: We can make this more efficient by canonicalizing the Structure (draining the + // deleted offsets vector) before transitioning from dictionary. + if (!structure->m_propertyTable || !structure->m_propertyTable->deletedOffsets || structure->m_propertyTable->deletedOffsets->isEmpty()) + structure->m_isDictionary = false; + + return structure; } -size_t StructureID::addPropertyWithoutTransition(const Identifier& propertyName, unsigned attributes) +size_t Structure::addPropertyWithoutTransition(const Identifier& propertyName, unsigned attributes) { + ASSERT(!m_transitions.singleTransition); + + materializePropertyMapIfNecessary(); + + m_isPinnedPropertyTable = true; size_t offset = put(propertyName, attributes); if (propertyStorageSize() > propertyStorageCapacity()) growPropertyStorageCapacity(); @@ -398,23 +523,29 @@ size_t StructureID::addPropertyWithoutTransition(const Identifier& propertyName, return offset; } -size_t StructureID::removePropertyWithoutTransition(const Identifier& propertyName) +size_t Structure::removePropertyWithoutTransition(const Identifier& propertyName) { + ASSERT(!m_transitions.singleTransition); + ASSERT(m_isDictionary); + + materializePropertyMapIfNecessary(); + + m_isPinnedPropertyTable = true; size_t offset = remove(propertyName); clearEnumerationCache(); return offset; } -StructureIDChain* StructureID::createCachedPrototypeChain() +StructureChain* Structure::createCachedPrototypeChain() { ASSERT(typeInfo().type() == ObjectType); ASSERT(!m_cachedPrototypeChain); - JSValue* prototype = storedPrototype(); - if (JSImmediate::isImmediate(prototype)) + JSValuePtr prototype = storedPrototype(); + if (!prototype.isCell()) return 0; - RefPtr<StructureIDChain> chain = StructureIDChain::create(asObject(prototype)->structureID()); + RefPtr<StructureChain> chain = StructureChain::create(asObject(prototype)->structure()); setCachedPrototypeChain(chain.release()); return cachedPrototypeChain(); } @@ -447,13 +578,13 @@ static const unsigned deletedSentinelIndex = 1; #if !DO_PROPERTYMAP_CONSTENCY_CHECK -inline void StructureID::checkConsistency() +inline void Structure::checkConsistency() { -} +} #endif -PropertyMapHashTable* StructureID::copyPropertyTable() +PropertyMapHashTable* Structure::copyPropertyTable() { if (!m_propertyTable) return 0; @@ -468,15 +599,20 @@ PropertyMapHashTable* StructureID::copyPropertyTable() key->ref(); } + // Copy the deletedOffsets vector. + if (m_propertyTable->deletedOffsets) + newTable->deletedOffsets = new Vector<unsigned>(*m_propertyTable->deletedOffsets); + return newTable; } -size_t StructureID::get(const Identifier& propertyName, unsigned& attributes) const +size_t Structure::get(const Identifier& propertyName, unsigned& attributes) { ASSERT(!propertyName.isNull()); + materializePropertyMapIfNecessary(); if (!m_propertyTable) - return WTF::notFound; + return notFound; UString::Rep* rep = propertyName._ustring.rep(); @@ -488,7 +624,7 @@ size_t StructureID::get(const Identifier& propertyName, unsigned& attributes) co unsigned entryIndex = m_propertyTable->entryIndices[i & m_propertyTable->sizeMask]; if (entryIndex == emptyEntryIndex) - return WTF::notFound; + return notFound; if (rep == m_propertyTable->entries()[entryIndex - 1].key) { attributes = m_propertyTable->entries()[entryIndex - 1].attributes; @@ -510,7 +646,7 @@ size_t StructureID::get(const Identifier& propertyName, unsigned& attributes) co entryIndex = m_propertyTable->entryIndices[i & m_propertyTable->sizeMask]; if (entryIndex == emptyEntryIndex) - return WTF::notFound; + return notFound; if (rep == m_propertyTable->entries()[entryIndex - 1].key) { attributes = m_propertyTable->entries()[entryIndex - 1].attributes; @@ -519,10 +655,10 @@ size_t StructureID::get(const Identifier& propertyName, unsigned& attributes) co } } -size_t StructureID::put(const Identifier& propertyName, unsigned attributes) +size_t Structure::put(const Identifier& propertyName, unsigned attributes) { ASSERT(!propertyName.isNull()); - ASSERT(get(propertyName) == WTF::notFound); + ASSERT(get(propertyName) == notFound); checkConsistency(); @@ -592,9 +728,9 @@ size_t StructureID::put(const Identifier& propertyName, unsigned attributes) m_propertyTable->entries()[entryIndex - 1].index = ++m_propertyTable->lastIndexUsed; unsigned newOffset; - if (!m_deletedOffsets.isEmpty()) { - newOffset = m_deletedOffsets.last(); - m_deletedOffsets.removeLast(); + if (m_propertyTable->deletedOffsets && !m_propertyTable->deletedOffsets->isEmpty()) { + newOffset = m_propertyTable->deletedOffsets->last(); + m_propertyTable->deletedOffsets->removeLast(); } else newOffset = m_propertyTable->keyCount; m_propertyTable->entries()[entryIndex - 1].offset = newOffset; @@ -608,7 +744,7 @@ size_t StructureID::put(const Identifier& propertyName, unsigned attributes) return newOffset; } -size_t StructureID::remove(const Identifier& propertyName) +size_t Structure::remove(const Identifier& propertyName) { ASSERT(!propertyName.isNull()); @@ -617,7 +753,7 @@ size_t StructureID::remove(const Identifier& propertyName) UString::Rep* rep = propertyName._ustring.rep(); if (!m_propertyTable) - return WTF::notFound; + return notFound; #if DUMP_PROPERTYMAP_STATS ++numProbes; @@ -632,7 +768,7 @@ size_t StructureID::remove(const Identifier& propertyName) while (1) { entryIndex = m_propertyTable->entryIndices[i & m_propertyTable->sizeMask]; if (entryIndex == emptyEntryIndex) - return WTF::notFound; + return notFound; key = m_propertyTable->entries()[entryIndex - 1].key; if (rep == key) @@ -662,7 +798,10 @@ size_t StructureID::remove(const Identifier& propertyName) m_propertyTable->entries()[entryIndex - 1].key = 0; m_propertyTable->entries()[entryIndex - 1].attributes = 0; m_propertyTable->entries()[entryIndex - 1].offset = 0; - m_deletedOffsets.append(offset); + + if (!m_propertyTable->deletedOffsets) + m_propertyTable->deletedOffsets = new Vector<unsigned>; + m_propertyTable->deletedOffsets->append(offset); ASSERT(m_propertyTable->keyCount >= 1); --m_propertyTable->keyCount; @@ -675,7 +814,7 @@ size_t StructureID::remove(const Identifier& propertyName) return offset; } -void StructureID::insertIntoPropertyMapHashTable(const PropertyMapEntry& entry) +void Structure::insertIntoPropertyMapHashTable(const PropertyMapEntry& entry) { ASSERT(m_propertyTable); @@ -712,17 +851,16 @@ void StructureID::insertIntoPropertyMapHashTable(const PropertyMapEntry& entry) ++m_propertyTable->keyCount; } -void StructureID::expandPropertyMapHashTable() +void Structure::createPropertyMapHashTable() { - ASSERT(m_propertyTable); - rehashPropertyMapHashTable(m_propertyTable->size * 2); + ASSERT(sizeForKeyCount(7) == newTableSize); + createPropertyMapHashTable(newTableSize); } -void StructureID::createPropertyMapHashTable() +void Structure::createPropertyMapHashTable(unsigned newTableSize) { - const unsigned newTableSize = 16; - ASSERT(!m_propertyTable); + ASSERT(isPowerOf2(newTableSize)); checkConsistency(); @@ -733,16 +871,23 @@ void StructureID::createPropertyMapHashTable() checkConsistency(); } -void StructureID::rehashPropertyMapHashTable() +void Structure::expandPropertyMapHashTable() +{ + ASSERT(m_propertyTable); + rehashPropertyMapHashTable(m_propertyTable->size * 2); +} + +void Structure::rehashPropertyMapHashTable() { ASSERT(m_propertyTable); ASSERT(m_propertyTable->size); rehashPropertyMapHashTable(m_propertyTable->size); } -void StructureID::rehashPropertyMapHashTable(unsigned newTableSize) +void Structure::rehashPropertyMapHashTable(unsigned newTableSize) { ASSERT(m_propertyTable); + ASSERT(isPowerOf2(newTableSize)); checkConsistency(); @@ -761,6 +906,7 @@ void StructureID::rehashPropertyMapHashTable(unsigned newTableSize) } } m_propertyTable->lastIndexUsed = lastIndexUsed; + m_propertyTable->deletedOffsets = oldTable->deletedOffsets; fastFree(oldTable); @@ -778,8 +924,9 @@ static int comparePropertyMapEntryIndices(const void* a, const void* b) return 0; } -void StructureID::getEnumerablePropertyNamesInternal(PropertyNameArray& propertyNames) const +void Structure::getEnumerablePropertyNamesInternal(PropertyNameArray& propertyNames) { + materializePropertyMapIfNecessary(); if (!m_propertyTable) return; @@ -836,12 +983,12 @@ void StructureID::getEnumerablePropertyNamesInternal(PropertyNameArray& property #if DO_PROPERTYMAP_CONSTENCY_CHECK -void StructureID::checkConsistency() +void Structure::checkConsistency() { if (!m_propertyTable) return; - ASSERT(m_propertyTable->size >= 16); + ASSERT(m_propertyTable->size >= newTableSize); ASSERT(m_propertyTable->sizeMask); ASSERT(m_propertyTable->size == m_propertyTable->sizeMask + 1); ASSERT(!(m_propertyTable->size & m_propertyTable->sizeMask)); diff --git a/JavaScriptCore/runtime/StructureID.h b/JavaScriptCore/runtime/Structure.h index 4f45dac..569738b 100644 --- a/JavaScriptCore/runtime/StructureID.h +++ b/JavaScriptCore/runtime/Structure.h @@ -23,20 +23,17 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef StructureID_h -#define StructureID_h +#ifndef Structure_h +#define Structure_h +#include "Identifier.h" #include "JSType.h" #include "JSValue.h" #include "PropertyMapHashTable.h" -#include "StructureIDChain.h" -#include "StructureIDTransitionTable.h" +#include "StructureChain.h" +#include "StructureTransitionTable.h" #include "TypeInfo.h" -#include "identifier.h" -#include "ustring.h" -#include <wtf/HashFunctions.h> -#include <wtf/HashTraits.h> -#include <wtf/OwnArrayPtr.h> +#include "UString.h" #include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> @@ -51,12 +48,12 @@ namespace JSC { class PropertyNameArray; class PropertyNameArrayData; - class StructureID : public RefCounted<StructureID> { + class Structure : public RefCounted<Structure> { public: - friend class CTI; - static PassRefPtr<StructureID> create(JSValue* prototype, const TypeInfo& typeInfo) + friend class JIT; + static PassRefPtr<Structure> create(JSValuePtr prototype, const TypeInfo& typeInfo) { - return adoptRef(new StructureID(prototype, typeInfo)); + return adoptRef(new Structure(prototype, typeInfo)); } static void startIgnoringLeaks(); @@ -64,113 +61,128 @@ namespace JSC { static void dumpStatistics(); - static PassRefPtr<StructureID> changePrototypeTransition(StructureID*, JSValue* prototype); - static PassRefPtr<StructureID> addPropertyTransition(StructureID*, const Identifier& propertyName, unsigned attributes, size_t& offset); - static PassRefPtr<StructureID> removePropertyTransition(StructureID*, const Identifier& propertyName, size_t& offset); - static PassRefPtr<StructureID> getterSetterTransition(StructureID*); - static PassRefPtr<StructureID> toDictionaryTransition(StructureID*); - static PassRefPtr<StructureID> fromDictionaryTransition(StructureID*); + static PassRefPtr<Structure> addPropertyTransition(Structure*, const Identifier& propertyName, unsigned attributes, size_t& offset); + static PassRefPtr<Structure> addPropertyTransitionToExistingStructure(Structure*, const Identifier& propertyName, unsigned attributes, size_t& offset); + static PassRefPtr<Structure> removePropertyTransition(Structure*, const Identifier& propertyName, size_t& offset); + static PassRefPtr<Structure> changePrototypeTransition(Structure*, JSValuePtr prototype); + static PassRefPtr<Structure> getterSetterTransition(Structure*); + static PassRefPtr<Structure> toDictionaryTransition(Structure*); + static PassRefPtr<Structure> fromDictionaryTransition(Structure*); - ~StructureID(); + ~Structure(); void mark() { - if (!m_prototype->marked()) - m_prototype->mark(); + if (!m_prototype.marked()) + m_prototype.mark(); } // These should be used with caution. size_t addPropertyWithoutTransition(const Identifier& propertyName, unsigned attributes); size_t removePropertyWithoutTransition(const Identifier& propertyName); - void setPrototypeWithoutTransition(JSValue* prototype) { m_prototype = prototype; } + void setPrototypeWithoutTransition(JSValuePtr prototype) { m_prototype = prototype; } bool isDictionary() const { return m_isDictionary; } const TypeInfo& typeInfo() const { return m_typeInfo; } - // For use when first creating a new structure. - TypeInfo& mutableTypeInfo() { return m_typeInfo; } + JSValuePtr storedPrototype() const { return m_prototype; } + JSValuePtr prototypeForLookup(ExecState*); - JSValue* storedPrototype() const { return m_prototype; } - JSValue* prototypeForLookup(ExecState*); + Structure* previousID() const { return m_previous.get(); } - StructureID* previousID() const { return m_previous.get(); } - - StructureIDChain* createCachedPrototypeChain(); - void setCachedPrototypeChain(PassRefPtr<StructureIDChain> cachedPrototypeChain) { m_cachedPrototypeChain = cachedPrototypeChain; } - StructureIDChain* cachedPrototypeChain() const { return m_cachedPrototypeChain.get(); } - - void setCachedTransistionOffset(size_t offset) { m_cachedTransistionOffset = offset; } - size_t cachedTransistionOffset() const { return m_cachedTransistionOffset; } + StructureChain* createCachedPrototypeChain(); + void setCachedPrototypeChain(PassRefPtr<StructureChain> cachedPrototypeChain) { m_cachedPrototypeChain = cachedPrototypeChain; } + StructureChain* cachedPrototypeChain() const { return m_cachedPrototypeChain.get(); } void growPropertyStorageCapacity(); size_t propertyStorageCapacity() const { return m_propertyStorageCapacity; } - size_t propertyStorageSize() const { return m_propertyTable ? m_propertyTable->keyCount + m_deletedOffsets.size() : 0; } + size_t propertyStorageSize() const { return m_propertyTable ? m_propertyTable->keyCount + (m_propertyTable->deletedOffsets ? m_propertyTable->deletedOffsets->size() : 0) : m_offset + 1; } - size_t get(const Identifier& propertyName) const; - size_t get(const Identifier& propertyName, unsigned& attributes) const; + size_t get(const Identifier& propertyName); + size_t get(const Identifier& propertyName, unsigned& attributes); void getEnumerablePropertyNames(ExecState*, PropertyNameArray&, JSObject*); bool hasGetterSetterProperties() const { return m_hasGetterSetterProperties; } void setHasGetterSetterProperties(bool hasGetterSetterProperties) { m_hasGetterSetterProperties = hasGetterSetterProperties; } - bool isEmpty() const { return !m_propertyTable; } + bool isEmpty() const { return m_propertyTable ? !m_propertyTable->keyCount : m_offset == noOffset; } private: - StructureID(JSValue* prototype, const TypeInfo&); + Structure(JSValuePtr prototype, const TypeInfo&); size_t put(const Identifier& propertyName, unsigned attributes); size_t remove(const Identifier& propertyName); - void getEnumerablePropertyNamesInternal(PropertyNameArray&) const; + void getEnumerablePropertyNamesInternal(PropertyNameArray&); void expandPropertyMapHashTable(); void rehashPropertyMapHashTable(); void rehashPropertyMapHashTable(unsigned newTableSize); void createPropertyMapHashTable(); + void createPropertyMapHashTable(unsigned newTableSize); void insertIntoPropertyMapHashTable(const PropertyMapEntry&); void checkConsistency(); PropertyMapHashTable* copyPropertyTable(); + void materializePropertyMap(); + void materializePropertyMapIfNecessary() + { + if (m_propertyTable || !m_previous) + return; + materializePropertyMap(); + } void clearEnumerationCache(); + void* addressOfCount() + { + return &m_refCount; + } + + signed char transitionCount() const + { + // Since the number of transitions is always the same as m_offset, we keep the size of Structure down by not storing both. + return m_offset == noOffset ? 0 : m_offset + 1; + } + static const unsigned emptyEntryIndex = 0; - static const size_t s_maxTransitionLength = 64; + static const signed char s_maxTransitionLength = 64; + + static const signed char noOffset = -1; TypeInfo m_typeInfo; - JSValue* m_prototype; - RefPtr<StructureIDChain> m_cachedPrototypeChain; + JSValuePtr m_prototype; + RefPtr<StructureChain> m_cachedPrototypeChain; - RefPtr<StructureID> m_previous; - UString::Rep* m_nameInPrevious; + RefPtr<Structure> m_previous; + RefPtr<UString::Rep> m_nameInPrevious; - size_t m_transitionCount; union { - StructureID* singleTransition; - StructureIDTransitionTable* table; + Structure* singleTransition; + StructureTransitionTable* table; } m_transitions; RefPtr<PropertyNameArrayData> m_cachedPropertyNameArrayData; PropertyMapHashTable* m_propertyTable; - Vector<unsigned> m_deletedOffsets; size_t m_propertyStorageCapacity; - - size_t m_cachedTransistionOffset; + signed char m_offset; bool m_isDictionary : 1; + bool m_isPinnedPropertyTable : 1; bool m_hasGetterSetterProperties : 1; bool m_usingSingleTransitionSlot : 1; unsigned m_attributesInPrevious : 5; }; - inline size_t StructureID::get(const Identifier& propertyName) const + inline size_t Structure::get(const Identifier& propertyName) { ASSERT(!propertyName.isNull()); + materializePropertyMapIfNecessary(); if (!m_propertyTable) return WTF::notFound; @@ -213,4 +225,4 @@ namespace JSC { } // namespace JSC -#endif // StructureID_h +#endif // Structure_h diff --git a/JavaScriptCore/runtime/StructureIDChain.cpp b/JavaScriptCore/runtime/StructureChain.cpp index 83d9254..4d00263 100644 --- a/JavaScriptCore/runtime/StructureIDChain.cpp +++ b/JavaScriptCore/runtime/StructureChain.cpp @@ -24,42 +24,42 @@ */ #include "config.h" -#include "StructureIDChain.h" +#include "StructureChain.h" #include "JSObject.h" -#include "StructureID.h" +#include "Structure.h" #include <wtf/RefPtr.h> namespace JSC { -StructureIDChain::StructureIDChain(StructureID* structureID) +StructureChain::StructureChain(Structure* structure) { size_t size = 1; - StructureID* tmp = structureID; - while (!tmp->storedPrototype()->isNull()) { + Structure* tmp = structure; + while (!tmp->storedPrototype().isNull()) { ++size; - tmp = asCell(tmp->storedPrototype())->structureID(); + tmp = asCell(tmp->storedPrototype())->structure(); } - m_vector.set(new RefPtr<StructureID>[size + 1]); + m_vector.set(new RefPtr<Structure>[size + 1]); size_t i; for (i = 0; i < size - 1; ++i) { - m_vector[i] = structureID; - structureID = asObject(structureID->storedPrototype())->structureID(); + m_vector[i] = structure; + structure = asObject(structure->storedPrototype())->structure(); } - m_vector[i] = structureID; + m_vector[i] = structure; m_vector[i + 1] = 0; } -bool structureIDChainsAreEqual(StructureIDChain* chainA, StructureIDChain* chainB) +bool structureChainsAreEqual(StructureChain* chainA, StructureChain* chainB) { if (!chainA || !chainB) return false; - RefPtr<StructureID>* a = chainA->head(); - RefPtr<StructureID>* b = chainB->head(); + RefPtr<Structure>* a = chainA->head(); + RefPtr<Structure>* b = chainB->head(); while (1) { if (*a != *b) return false; diff --git a/JavaScriptCore/runtime/StructureIDChain.h b/JavaScriptCore/runtime/StructureChain.h index 2d554a7..a3a1be2 100644 --- a/JavaScriptCore/runtime/StructureIDChain.h +++ b/JavaScriptCore/runtime/StructureChain.h @@ -23,8 +23,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef StructureIDChain_h -#define StructureIDChain_h +#ifndef StructureChain_h +#define StructureChain_h #include <wtf/OwnArrayPtr.h> #include <wtf/PassRefPtr.h> @@ -33,22 +33,22 @@ namespace JSC { - class StructureID; + class Structure; - class StructureIDChain : public RefCounted<StructureIDChain> { + class StructureChain : public RefCounted<StructureChain> { public: - static PassRefPtr<StructureIDChain> create(StructureID* structureID) { return adoptRef(new StructureIDChain(structureID)); } + static PassRefPtr<StructureChain> create(Structure* structure) { return adoptRef(new StructureChain(structure)); } - RefPtr<StructureID>* head() { return m_vector.get(); } + RefPtr<Structure>* head() { return m_vector.get(); } private: - StructureIDChain(StructureID* structureID); + StructureChain(Structure* structure); - OwnArrayPtr<RefPtr<StructureID> > m_vector; + OwnArrayPtr<RefPtr<Structure> > m_vector; }; - bool structureIDChainsAreEqual(StructureIDChain*, StructureIDChain*); + bool structureChainsAreEqual(StructureChain*, StructureChain*); } // namespace JSC -#endif // StructureIDChain_h +#endif // StructureChain_h diff --git a/JavaScriptCore/runtime/StructureIDTransitionTable.h b/JavaScriptCore/runtime/StructureTransitionTable.h index dd65971..1543049 100644 --- a/JavaScriptCore/runtime/StructureIDTransitionTable.h +++ b/JavaScriptCore/runtime/StructureTransitionTable.h @@ -23,10 +23,10 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef StructureIDTransitionTable_h -#define StructureIDTransitionTable_h +#ifndef StructureTransitionTable_h +#define StructureTransitionTable_h -#include "ustring.h" +#include "UString.h" #include <wtf/HashFunctions.h> #include <wtf/HashMap.h> #include <wtf/HashTraits.h> @@ -34,9 +34,9 @@ namespace JSC { - class StructureID; + class Structure; - struct StructureIDTransitionTableHash { + struct StructureTransitionTableHash { typedef std::pair<RefPtr<UString::Rep>, unsigned> Key; static unsigned hash(const Key& p) { @@ -51,7 +51,7 @@ namespace JSC { static const bool safeToCompareToEmptyOrDeleted = true; }; - struct StructureIDTransitionTableHashTraits { + struct StructureTransitionTableHashTraits { typedef WTF::HashTraits<RefPtr<UString::Rep> > FirstTraits; typedef WTF::GenericHashTraits<unsigned> SecondTraits; typedef std::pair<FirstTraits::TraitType, SecondTraits::TraitType> TraitType; @@ -65,8 +65,8 @@ namespace JSC { static bool isDeletedValue(const TraitType& value) { return FirstTraits::isDeletedValue(value.first); } }; - typedef HashMap<StructureIDTransitionTableHash::Key, StructureID*, StructureIDTransitionTableHash, StructureIDTransitionTableHashTraits> StructureIDTransitionTable; + typedef HashMap<StructureTransitionTableHash::Key, Structure*, StructureTransitionTableHash, StructureTransitionTableHashTraits> StructureTransitionTable; } // namespace JSC -#endif // StructureIDTransitionTable_h +#endif // StructureTransitionTable_h diff --git a/JavaScriptCore/runtime/SymbolTable.h b/JavaScriptCore/runtime/SymbolTable.h index d730d58..c00f95a 100644 --- a/JavaScriptCore/runtime/SymbolTable.h +++ b/JavaScriptCore/runtime/SymbolTable.h @@ -30,7 +30,7 @@ #define SymbolTable_h #include "JSObject.h" -#include "ustring.h" +#include "UString.h" #include <wtf/AlwaysInline.h> namespace JSC { diff --git a/JavaScriptCore/kjs/TypeInfo.h b/JavaScriptCore/runtime/TypeInfo.h index 4f0b16c..52da347 100644 --- a/JavaScriptCore/kjs/TypeInfo.h +++ b/JavaScriptCore/runtime/TypeInfo.h @@ -39,7 +39,7 @@ namespace JSC { static const unsigned HasStandardGetOwnPropertySlot = 1 << 4; class TypeInfo { - friend class CTI; + friend class JIT; public: TypeInfo(JSType type, unsigned flags = 0) : m_type(type), m_flags(flags) { } diff --git a/JavaScriptCore/kjs/ustring.cpp b/JavaScriptCore/runtime/UString.cpp index 3a85b1d..8cb12cf 100644 --- a/JavaScriptCore/kjs/ustring.cpp +++ b/JavaScriptCore/runtime/UString.cpp @@ -2,6 +2,7 @@ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca) + * 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 @@ -21,13 +22,13 @@ */ #include "config.h" -#include "ustring.h" +#include "UString.h" #include "JSGlobalObjectFunctions.h" -#include "collector.h" +#include "Collector.h" #include "dtoa.h" -#include "identifier.h" -#include "operations.h" +#include "Identifier.h" +#include "Operations.h" #include <ctype.h> #include <float.h> #include <limits.h> @@ -186,8 +187,37 @@ bool operator==(const CString& c1, const CString& c2) // These static strings are immutable, except for rc, whose initial value is chosen to // reduce the possibility of it becoming zero due to ref/deref not being thread-safe. static UChar sharedEmptyChar; -UString::Rep UString::Rep::null = { 0, 0, INT_MAX / 2, 0, 1, &UString::Rep::null, 0, 0, 0, 0, 0, 0 }; -UString::Rep UString::Rep::empty = { 0, 0, INT_MAX / 2, 0, 1, &UString::Rep::empty, 0, &sharedEmptyChar, 0, 0, 0, 0 }; +UString::BaseString* UString::Rep::nullBaseString; +UString::BaseString* UString::Rep::emptyBaseString; +UString* UString::nullUString; + +static void initializeStaticBaseString(int len, UChar* buf, UString::BaseString& base) +{ + base.offset = 0; + base.len = len; + base.rc = INT_MAX / 2; + base._hash = 0; + base.m_identifierTableAndFlags.setFlag(UString::Rep::StaticFlag); + base.m_baseString = 0; + base.buf = buf; + base.preCapacity = 0; + base.usedPreCapacity = 0; + base.capacity = 0; + base.usedCapacity = 0; + base.reportedCost = 0; + base.checkConsistency(); +} + +void initializeUString() +{ + UString::Rep::nullBaseString = new UString::BaseString; + initializeStaticBaseString(0, 0, *UString::Rep::nullBaseString); + + UString::Rep::emptyBaseString = new UString::BaseString; + initializeStaticBaseString(0, &sharedEmptyChar, *UString::Rep::emptyBaseString); + + UString::nullUString = new UString; +} static char* statBuffer = 0; // Only used for debugging via UString::ascii(). @@ -200,13 +230,12 @@ PassRefPtr<UString::Rep> UString::Rep::createCopying(const UChar* d, int l) PassRefPtr<UString::Rep> UString::Rep::create(UChar* d, int l) { - Rep* r = new Rep; + BaseString* r = new BaseString; r->offset = 0; r->len = l; r->rc = 1; r->_hash = 0; - r->m_identifierTable = 0; - r->baseString = r; + r->m_baseString = 0; r->reportedCost = 0; r->buf = d; r->usedCapacity = l; @@ -220,31 +249,24 @@ PassRefPtr<UString::Rep> UString::Rep::create(UChar* d, int l) return adoptRef(r); } -PassRefPtr<UString::Rep> UString::Rep::create(PassRefPtr<Rep> base, int offset, int length) +PassRefPtr<UString::Rep> UString::Rep::create(PassRefPtr<Rep> rep, int offset, int length) { - ASSERT(base); - base->checkConsistency(); + ASSERT(rep); + rep->checkConsistency(); - int baseOffset = base->offset; + int repOffset = rep->offset; - base = base->baseString; + PassRefPtr<BaseString> base = rep->baseString(); - ASSERT(-(offset + baseOffset) <= base->usedPreCapacity); - ASSERT(offset + baseOffset + length <= base->usedCapacity); + ASSERT(-(offset + repOffset) <= base->usedPreCapacity); + ASSERT(offset + repOffset + length <= base->usedCapacity); Rep* r = new Rep; - r->offset = baseOffset + offset; + r->offset = repOffset + offset; r->len = length; r->rc = 1; r->_hash = 0; - r->m_identifierTable = 0; - r->baseString = base.releaseRef(); - r->reportedCost = 0; - r->buf = 0; - r->usedCapacity = 0; - r->capacity = 0; - r->usedPreCapacity = 0; - r->preCapacity = 0; + r->setBaseString(base); r->checkConsistency(); @@ -255,13 +277,13 @@ PassRefPtr<UString::Rep> UString::Rep::create(PassRefPtr<Rep> base, int offset, PassRefPtr<UString::Rep> UString::Rep::createFromUTF8(const char* string) { if (!string) - return &UString::Rep::null; + return &UString::Rep::null(); size_t length = strlen(string); Vector<UChar, 1024> buffer(length); UChar* p = buffer.data(); if (conversionOK != convertUTF8ToUTF16(&string, string + length, &p, p + length)) - return &UString::Rep::null; + return &UString::Rep::null(); return UString::Rep::createCopying(buffer.data(), p - buffer.data()); } @@ -275,10 +297,11 @@ void UString::Rep::destroy() if (!isStatic()) { if (identifierTable()) Identifier::remove(this); - if (baseString == this) - fastFree(buf); + UString::BaseString* base = baseString(); + if (base == this) + fastFree(base->buf); else - baseString->deref(); + base->deref(); delete this; } @@ -380,17 +403,10 @@ unsigned UString::Rep::computeHash(const char* s, int l) #ifndef NDEBUG void UString::Rep::checkConsistency() const { - // Only base strings have non-zero shared data. - if (this != baseString) { - ASSERT(!buf); - ASSERT(!usedCapacity); - ASSERT(!capacity); - ASSERT(!usedPreCapacity); - ASSERT(!preCapacity); - } + const UString::BaseString* base = baseString(); // There is no recursion for base strings. - ASSERT(baseString == baseString->baseString); + ASSERT(base == base->baseString()); if (isStatic()) { // There are only two static strings: null and empty. @@ -401,10 +417,10 @@ void UString::Rep::checkConsistency() const } // The string fits in buffer. - ASSERT(baseString->usedPreCapacity <= baseString->preCapacity); - ASSERT(baseString->usedCapacity <= baseString->capacity); - ASSERT(-offset <= baseString->usedPreCapacity); - ASSERT(offset + len <= baseString->usedCapacity); + ASSERT(base->usedPreCapacity <= base->preCapacity); + ASSERT(base->usedCapacity <= base->capacity); + ASSERT(-offset <= base->usedPreCapacity); + ASSERT(offset + len <= base->usedCapacity); } #endif @@ -424,35 +440,24 @@ static inline size_t expandedSize(size_t size, size_t otherSize) return expandedSize + otherSize; } -inline int UString::usedCapacity() const -{ - return m_rep->baseString->usedCapacity; -} - -inline int UString::usedPreCapacity() const -{ - return m_rep->baseString->usedPreCapacity; -} - - static inline bool expandCapacity(UString::Rep* rep, int requiredLength) { rep->checkConsistency(); - UString::Rep* r = rep->baseString; + UString::BaseString* base = rep->baseString(); - if (requiredLength > r->capacity) { - size_t newCapacity = expandedSize(requiredLength, r->preCapacity); - UChar* oldBuf = r->buf; - r->buf = reallocChars(r->buf, newCapacity); - if (!r->buf) { - r->buf = oldBuf; + if (requiredLength > base->capacity) { + size_t newCapacity = expandedSize(requiredLength, base->preCapacity); + UChar* oldBuf = base->buf; + base->buf = reallocChars(base->buf, newCapacity); + if (!base->buf) { + base->buf = oldBuf; return false; } - r->capacity = newCapacity - r->preCapacity; + base->capacity = newCapacity - base->preCapacity; } - if (requiredLength > r->usedCapacity) - r->usedCapacity = requiredLength; + if (requiredLength > base->usedCapacity) + base->usedCapacity = requiredLength; rep->checkConsistency(); return true; @@ -468,41 +473,41 @@ void UString::expandPreCapacity(int requiredPreCap) { m_rep->checkConsistency(); - Rep* r = m_rep->baseString; + BaseString* base = m_rep->baseString(); - if (requiredPreCap > r->preCapacity) { - size_t newCapacity = expandedSize(requiredPreCap, r->capacity); - int delta = newCapacity - r->capacity - r->preCapacity; + if (requiredPreCap > base->preCapacity) { + size_t newCapacity = expandedSize(requiredPreCap, base->capacity); + int delta = newCapacity - base->capacity - base->preCapacity; UChar* newBuf = allocChars(newCapacity); if (!newBuf) { makeNull(); return; } - copyChars(newBuf + delta, r->buf, r->capacity + r->preCapacity); - fastFree(r->buf); - r->buf = newBuf; + copyChars(newBuf + delta, base->buf, base->capacity + base->preCapacity); + fastFree(base->buf); + base->buf = newBuf; - r->preCapacity = newCapacity - r->capacity; + base->preCapacity = newCapacity - base->capacity; } - if (requiredPreCap > r->usedPreCapacity) - r->usedPreCapacity = requiredPreCap; + if (requiredPreCap > base->usedPreCapacity) + base->usedPreCapacity = requiredPreCap; m_rep->checkConsistency(); } -PassRefPtr<UString::Rep> createRep(const char* c) +static PassRefPtr<UString::Rep> createRep(const char* c) { if (!c) - return &UString::Rep::null; + return &UString::Rep::null(); if (!c[0]) - return &UString::Rep::empty; + return &UString::Rep::empty(); size_t length = strlen(c); UChar* d = allocChars(length); if (!d) - return &UString::Rep::null; + return &UString::Rep::null(); else { for (size_t i = 0; i < length; i++) d[i] = static_cast<unsigned char>(c[i]); // use unsigned char to zero-extend instead of sign-extend @@ -519,7 +524,7 @@ UString::UString(const char* c) UString::UString(const UChar* c, int length) { if (length == 0) - m_rep = &Rep::empty; + m_rep = &Rep::empty(); else m_rep = Rep::createCopying(c, length); } @@ -527,7 +532,7 @@ UString::UString(const UChar* c, int length) UString::UString(UChar* c, int length, bool copy) { if (length == 0) - m_rep = &Rep::empty; + m_rep = &Rep::empty(); else if (copy) m_rep = Rep::createCopying(c, length); else @@ -537,7 +542,7 @@ UString::UString(UChar* c, int length, bool copy) UString::UString(const Vector<UChar>& buffer) { if (!buffer.size()) - m_rep = &Rep::empty; + m_rep = &Rep::empty(); else m_rep = Rep::createCopying(buffer.data(), buffer.size()); } @@ -551,6 +556,7 @@ static ALWAYS_INLINE PassRefPtr<UString::Rep> concatenate(PassRefPtr<UString::Re int thisSize = rep->size(); int thisOffset = rep->offset; int length = thisSize + tSize; + UString::BaseString* base = rep->baseString(); // possible cases: if (tSize == 0) { @@ -558,19 +564,19 @@ static ALWAYS_INLINE PassRefPtr<UString::Rep> concatenate(PassRefPtr<UString::Re } else if (thisSize == 0) { // this is empty rep = UString::Rep::createCopying(tData, tSize); - } else if (rep->baseIsSelf() && rep->rc == 1) { + } else if (rep == base && rep->rc == 1) { // this is direct and has refcount of 1 (so we can just alter it directly) if (!expandCapacity(rep.get(), thisOffset + length)) - rep = &UString::Rep::null; + rep = &UString::Rep::null(); if (rep->data()) { copyChars(rep->data() + thisSize, tData, tSize); rep->len = length; rep->_hash = 0; } - } else if (thisOffset + thisSize == rep->baseString->usedCapacity && thisSize >= minShareSize) { + } else if (thisOffset + thisSize == base->usedCapacity && thisSize >= minShareSize) { // this reaches the end of the buffer - extend it if it's long enough to append to if (!expandCapacity(rep.get(), thisOffset + length)) - rep = &UString::Rep::null; + rep = &UString::Rep::null(); if (rep->data()) { copyChars(rep->data() + thisSize, tData, tSize); rep = UString::Rep::create(rep, 0, length); @@ -580,12 +586,12 @@ static ALWAYS_INLINE PassRefPtr<UString::Rep> concatenate(PassRefPtr<UString::Re size_t newCapacity = expandedSize(length, 0); UChar* d = allocChars(newCapacity); if (!d) - rep = &UString::Rep::null; + rep = &UString::Rep::null(); else { copyChars(d, rep->data(), thisSize); copyChars(d + thisSize, tData, tSize); rep = UString::Rep::create(d, length); - rep->capacity = newCapacity; + rep->baseString()->capacity = newCapacity; } } @@ -604,6 +610,7 @@ static ALWAYS_INLINE PassRefPtr<UString::Rep> concatenate(PassRefPtr<UString::Re int thisOffset = rep->offset; int tSize = static_cast<int>(strlen(t)); int length = thisSize + tSize; + UString::BaseString* base = rep->baseString(); // possible cases: if (thisSize == 0) { @@ -611,7 +618,7 @@ static ALWAYS_INLINE PassRefPtr<UString::Rep> concatenate(PassRefPtr<UString::Re rep = createRep(t); } else if (tSize == 0) { // t is empty, we'll just return *this below. - } else if (rep->baseIsSelf() && rep->rc == 1) { + } else if (rep == base && rep->rc == 1) { // this is direct and has refcount of 1 (so we can just alter it directly) expandCapacity(rep.get(), thisOffset + length); UChar* d = rep->data(); @@ -621,7 +628,7 @@ static ALWAYS_INLINE PassRefPtr<UString::Rep> concatenate(PassRefPtr<UString::Re rep->len = length; rep->_hash = 0; } - } else if (thisOffset + thisSize == rep->baseString->usedCapacity && thisSize >= minShareSize) { + } else if (thisOffset + thisSize == base->usedCapacity && thisSize >= minShareSize) { // this string reaches the end of the buffer - extend it expandCapacity(rep.get(), thisOffset + length); UChar* d = rep->data(); @@ -635,13 +642,13 @@ static ALWAYS_INLINE PassRefPtr<UString::Rep> concatenate(PassRefPtr<UString::Re size_t newCapacity = expandedSize(length, 0); UChar* d = allocChars(newCapacity); if (!d) - rep = &UString::Rep::null; + rep = &UString::Rep::null(); else { copyChars(d, rep->data(), thisSize); for (int i = 0; i < tSize; ++i) d[thisSize + i] = static_cast<unsigned char>(t[i]); // use unsigned char to zero-extend instead of sign-extend rep = UString::Rep::create(d, length); - rep->capacity = newCapacity; + rep->baseString()->capacity = newCapacity; } } @@ -670,15 +677,17 @@ PassRefPtr<UString::Rep> concatenate(UString::Rep* a, UString::Rep* b) if (bSize == 0) return a; - if (bSize == 1 && aOffset + aSize == a->baseString->usedCapacity && aOffset + length <= a->baseString->capacity) { + UString::BaseString* aBase = a->baseString(); + if (bSize == 1 && aOffset + aSize == aBase->usedCapacity && aOffset + length <= aBase->capacity) { // b is a single character (common fast case) - a->baseString->usedCapacity = aOffset + length; + aBase->usedCapacity = aOffset + length; a->data()[aSize] = b->data()[0]; return UString::Rep::create(a, 0, length); } - if (aOffset + aSize == a->baseString->usedCapacity && aSize >= minShareSize && 4 * aSize >= bSize && - (-bOffset != b->baseString->usedPreCapacity || aSize >= bSize)) { + UString::BaseString* bBase = b->baseString(); + if (aOffset + aSize == aBase->usedCapacity && aSize >= minShareSize && 4 * aSize >= bSize + && (-bOffset != bBase->usedPreCapacity || aSize >= bSize)) { // - a reaches the end of its buffer so it qualifies for shared append // - also, it's at least a quarter the length of b - appending to a much shorter // string does more harm than good @@ -697,7 +706,7 @@ PassRefPtr<UString::Rep> concatenate(UString::Rep* a, UString::Rep* b) return result; } - if (-bOffset == b->baseString->usedPreCapacity && bSize >= minShareSize && 4 * bSize >= aSize) { + if (-bOffset == bBase->usedPreCapacity && bSize >= minShareSize && 4 * bSize >= aSize) { // - b reaches the beginning of its buffer so it qualifies for shared prepend // - also, it's at least a quarter the length of a - prepending to a much shorter // string does more harm than good @@ -723,7 +732,7 @@ PassRefPtr<UString::Rep> concatenate(UString::Rep* a, UString::Rep* b) copyChars(d, a->data(), aSize); copyChars(d + aSize, b->data(), bSize); PassRefPtr<UString::Rep> result = UString::Rep::create(d, length); - result->capacity = newCapacity; + result->baseString()->capacity = newCapacity; a->checkConsistency(); b->checkConsistency(); @@ -775,7 +784,7 @@ PassRefPtr<UString::Rep> concatenate(UString::Rep* rep, double d) int decimalPoint; int sign; - char* result = dtoa(d, 0, &decimalPoint, &sign, NULL); + char* result = WTF::dtoa(d, 0, &decimalPoint, &sign, NULL); int length = static_cast<int>(strlen(result)); int i = 0; @@ -826,17 +835,11 @@ PassRefPtr<UString::Rep> concatenate(UString::Rep* rep, double d) buf[i++] = '\0'; } - freedtoa(result); + WTF::freedtoa(result); return concatenate(rep, buf); } -const UString& UString::null() -{ - static UString* n = new UString; // Should be called from main thread at least once to be safely initialized. - return *n; -} - UString UString::from(int i) { UChar buf[1 + sizeof(i) * 3]; @@ -923,7 +926,7 @@ UString UString::from(double d) int decimalPoint; int sign; - char* result = dtoa(d, 0, &decimalPoint, &sign, NULL); + char* result = WTF::dtoa(d, 0, &decimalPoint, &sign, NULL); int length = static_cast<int>(strlen(result)); int i = 0; @@ -974,7 +977,7 @@ UString UString::from(double d) buf[i++] = '\0'; } - freedtoa(result); + WTF::freedtoa(result); return UString(buf); } @@ -1030,6 +1033,7 @@ UString& UString::append(const UString &t) int thisOffset = m_rep->offset; int tSize = t.size(); int length = thisSize + tSize; + BaseString* base = m_rep->baseString(); // possible cases: if (thisSize == 0) { @@ -1037,7 +1041,7 @@ UString& UString::append(const UString &t) *this = t; } else if (tSize == 0) { // t is empty - } else if (m_rep->baseIsSelf() && m_rep->rc == 1) { + } else if (m_rep == base && m_rep->rc == 1) { // this is direct and has refcount of 1 (so we can just alter it directly) expandCapacity(thisOffset + length); if (data()) { @@ -1045,7 +1049,7 @@ UString& UString::append(const UString &t) m_rep->len = length; m_rep->_hash = 0; } - } else if (thisOffset + thisSize == usedCapacity() && thisSize >= minShareSize) { + } else if (thisOffset + thisSize == base->usedCapacity && thisSize >= minShareSize) { // this reaches the end of the buffer - extend it if it's long enough to append to expandCapacity(thisOffset + length); if (data()) { @@ -1062,7 +1066,7 @@ UString& UString::append(const UString &t) copyChars(d, data(), thisSize); copyChars(d + thisSize, t.data(), tSize); m_rep = Rep::create(d, length); - m_rep->capacity = newCapacity; + m_rep->baseString()->capacity = newCapacity; } } @@ -1090,6 +1094,7 @@ UString& UString::append(UChar c) int thisOffset = m_rep->offset; int length = size(); + BaseString* base = m_rep->baseString(); // possible cases: if (length == 0) { @@ -1101,9 +1106,9 @@ UString& UString::append(UChar c) else { d[0] = c; m_rep = Rep::create(d, 1); - m_rep->capacity = newCapacity; + m_rep->baseString()->capacity = newCapacity; } - } else if (m_rep->baseIsSelf() && m_rep->rc == 1) { + } else if (m_rep == base && m_rep->rc == 1) { // this is direct and has refcount of 1 (so we can just alter it directly) expandCapacity(thisOffset + length + 1); UChar* d = m_rep->data(); @@ -1112,7 +1117,7 @@ UString& UString::append(UChar c) m_rep->len = length + 1; m_rep->_hash = 0; } - } else if (thisOffset + length == usedCapacity() && length >= minShareSize) { + } else if (thisOffset + length == base->usedCapacity && length >= minShareSize) { // this reaches the end of the string - extend it and share expandCapacity(thisOffset + length + 1); UChar* d = m_rep->data(); @@ -1130,7 +1135,7 @@ UString& UString::append(UChar c) copyChars(d, data(), length); d[length] = c; m_rep = Rep::create(d, length + 1); - m_rep->capacity = newCapacity; + m_rep->baseString()->capacity = newCapacity; } } @@ -1185,19 +1190,20 @@ char* UString::ascii() const UString& UString::operator=(const char* c) { if (!c) { - m_rep = &Rep::null; + m_rep = &Rep::null(); return *this; } if (!c[0]) { - m_rep = &Rep::empty; + m_rep = &Rep::empty(); return *this; } int l = static_cast<int>(strlen(c)); UChar* d; - if (m_rep->rc == 1 && l <= m_rep->capacity && m_rep->baseIsSelf() && m_rep->offset == 0 && m_rep->preCapacity == 0) { - d = m_rep->buf; + BaseString* base = m_rep->baseString(); + if (m_rep->rc == 1 && l <= base->capacity && m_rep == base && m_rep->offset == 0 && base->preCapacity == 0) { + d = base->buf; m_rep->_hash = 0; m_rep->len = l; } else { @@ -1281,7 +1287,7 @@ double UString::toDouble(bool tolerateTrailingJunk, bool tolerateEmptyString) co } else { // regular number ? char* end; - d = strtod(c, &end); + d = WTF::strtod(c, &end); if ((d != 0.0 || end != c) && d != Inf && d != -Inf) { c = end; } else { @@ -1413,12 +1419,24 @@ uint32_t UString::toStrictUInt32(bool* ok) const int UString::find(const UString& f, int pos) const { - int sz = size(); int fsz = f.size(); - if (sz < fsz) - return -1; + if (pos < 0) pos = 0; + + if (fsz == 1) { + UChar ch = f[0]; + const UChar* end = data() + size(); + for (const UChar* c = data() + pos; c < end; c++) { + if (*c == ch) + return static_cast<int>(c - data()); + } + return -1; + } + + int sz = size(); + if (sz < fsz) + return -1; if (fsz == 0) return pos; const UChar* end = data() + sz - fsz; @@ -1626,13 +1644,13 @@ CString UString::UTF8String(bool strict) const // For use in error handling code paths -- having this not be inlined helps avoid PIC branches to fetch the global on Mac OS X. NEVER_INLINE void UString::makeNull() { - m_rep = &Rep::null; + m_rep = &Rep::null(); } // For use in error handling code paths -- having this not be inlined helps avoid PIC branches to fetch the global on Mac OS X. NEVER_INLINE UString::Rep* UString::nullRep() { - return &Rep::null; + return &Rep::null(); } } // namespace JSC diff --git a/JavaScriptCore/kjs/ustring.h b/JavaScriptCore/runtime/UString.h index f47b134..59a7665 100644 --- a/JavaScriptCore/kjs/ustring.h +++ b/JavaScriptCore/runtime/UString.h @@ -1,6 +1,7 @@ /* * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) - * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 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 @@ -19,15 +20,15 @@ * */ -#ifndef _KJS_USTRING_H_ -#define _KJS_USTRING_H_ +#ifndef UString_h +#define UString_h -#include "collector.h" +#include "Collector.h" #include <stdint.h> #include <string.h> #include <wtf/Assertions.h> -#include <wtf/FastMalloc.h> #include <wtf/PassRefPtr.h> +#include <wtf/PtrAndFlags.h> #include <wtf/RefPtr.h> #include <wtf/Vector.h> #include <wtf/unicode/Unicode.h> @@ -71,11 +72,12 @@ namespace JSC { typedef Vector<char, 32> CStringBuffer; class UString { - friend class CTI; + friend class JIT; public: - struct Rep { - friend class CTI; + struct BaseString; + struct Rep : Noncopyable { + friend class JIT; static PassRefPtr<Rep> create(UChar*, int); static PassRefPtr<Rep> createCopying(const UChar*, int); @@ -87,8 +89,8 @@ namespace JSC { void destroy(); - bool baseIsSelf() const { return baseString == this; } - UChar* data() const { return baseString->buf + baseString->preCapacity + offset; } + bool baseIsSelf() const { return m_identifierTableAndFlags.isFlagSet(BaseStringFlag); } + UChar* data() const; int size() const { return len; } unsigned hash() const { if (_hash == 0) _hash = computeHash(data(), len); return _hash; } @@ -98,35 +100,55 @@ namespace JSC { static unsigned computeHash(const char*, int length); static unsigned computeHash(const char* s) { return computeHash(s, strlen(s)); } - IdentifierTable* identifierTable() const { return reinterpret_cast<IdentifierTable*>(m_identifierTable & ~static_cast<uintptr_t>(1)); } - void setIdentifierTable(IdentifierTable* table) { ASSERT(!isStatic()); m_identifierTable = reinterpret_cast<intptr_t>(table); } + IdentifierTable* identifierTable() const { return m_identifierTableAndFlags.get(); } + void setIdentifierTable(IdentifierTable* table) { ASSERT(!isStatic()); m_identifierTableAndFlags.set(table); } - bool isStatic() const { return m_identifierTable & 1; } - void setStatic(bool v) { ASSERT(!identifierTable()); m_identifierTable = v; } + bool isStatic() const { return m_identifierTableAndFlags.isFlagSet(StaticFlag); } + void setStatic(bool); + void setBaseString(PassRefPtr<BaseString>); + BaseString* baseString(); + const BaseString* baseString() const; Rep* ref() { ++rc; return this; } ALWAYS_INLINE void deref() { if (--rc == 0) destroy(); } void checkConsistency() const; + enum UStringFlags { + StaticFlag, + BaseStringFlag + }; // unshared data int offset; int len; int rc; // For null and empty static strings, this field does not reflect a correct count, because ref/deref are not thread-safe. A special case in destroy() guarantees that these do not get deleted. mutable unsigned _hash; - intptr_t m_identifierTable; // A pointer to identifier table. The lowest bit is used to indicate whether the string is static (null or empty). - UString::Rep* baseString; - size_t reportedCost; + PtrAndFlags<IdentifierTable, UStringFlags> m_identifierTableAndFlags; + void* m_baseString; // If "this" is a BaseString instance, it is 0. BaseString* otherwise. + + static BaseString& null() { return *nullBaseString; } + static BaseString& empty() { return *emptyBaseString; } + + private: + friend void initializeUString(); + static BaseString* nullBaseString; + static BaseString* emptyBaseString; + }; - // potentially shared data. 0 if backed up by a base string. + struct BaseString : public Rep { + BaseString() + { + m_identifierTableAndFlags.setFlag(BaseStringFlag); + } + + // potentially shared data. UChar* buf; - int usedCapacity; - int capacity; - int usedPreCapacity; int preCapacity; + int usedPreCapacity; + int capacity; + int usedCapacity; - static Rep null; - static Rep empty; + size_t reportedCost; }; public: @@ -204,7 +226,7 @@ namespace JSC { const UChar* data() const { return m_rep->data(); } - bool isNull() const { return (m_rep == &Rep::null); } + bool isNull() const { return (m_rep == &Rep::null()); } bool isEmpty() const { return (!m_rep->len); } bool is8Bit() const; @@ -230,7 +252,7 @@ namespace JSC { UString substr(int pos = 0, int len = -1) const; - static const UString& null(); + static const UString& null() { return *nullUString; } Rep* rep() const { return m_rep.get(); } static Rep* nullRep(); @@ -244,14 +266,14 @@ namespace JSC { size_t cost() const; private: - int usedCapacity() const; - int usedPreCapacity() const; void expandCapacity(int requiredLength); void expandPreCapacity(int requiredPreCap); void makeNull(); RefPtr<Rep> m_rep; + static UString* nullUString; + friend void initializeUString(); friend bool operator==(const UString&, const UString&); friend PassRefPtr<Rep> concatenate(Rep*, Rep*); // returns 0 if out of memory }; @@ -298,6 +320,37 @@ namespace JSC { bool equal(const UString::Rep*, const UString::Rep*); + inline UChar* UString::Rep::data() const + { + const BaseString* base = baseString(); + return base->buf + base->preCapacity + offset; + } + + inline void UString::Rep::setStatic(bool v) + { + ASSERT(!identifierTable()); + if (v) + m_identifierTableAndFlags.setFlag(StaticFlag); + else + m_identifierTableAndFlags.clearFlag(StaticFlag); + } + + inline void UString::Rep::setBaseString(PassRefPtr<BaseString> base) + { + ASSERT(base != this); + m_baseString = base.releaseRef(); + } + + inline UString::BaseString* UString::Rep::baseString() + { + return reinterpret_cast<BaseString*>(baseIsSelf() ? this : m_baseString); + } + + inline const UString::BaseString* UString::Rep::baseString() const + { + return const_cast<const BaseString*>(const_cast<Rep*>(this)->baseString()); + } + #ifdef NDEBUG inline void UString::Rep::checkConsistency() const { @@ -305,7 +358,7 @@ namespace JSC { #endif inline UString::UString() - : m_rep(&Rep::null) + : m_rep(&Rep::null()) { } @@ -328,8 +381,9 @@ namespace JSC { inline size_t UString::cost() const { - size_t capacity = (m_rep->baseString->capacity + m_rep->baseString->preCapacity) * sizeof(UChar); - size_t reportedCost = m_rep->baseString->reportedCost; + BaseString* base = m_rep->baseString(); + size_t capacity = (base->capacity + base->preCapacity) * sizeof(UChar); + size_t reportedCost = base->reportedCost; ASSERT(capacity >= reportedCost); size_t capacityDelta = capacity - reportedCost; @@ -337,7 +391,7 @@ namespace JSC { if (capacityDelta < static_cast<size_t>(minShareSize)) return 0; - m_rep->baseString->reportedCost = capacity; + base->reportedCost = capacity; return capacityDelta; } @@ -347,6 +401,7 @@ namespace JSC { static unsigned hash(JSC::UString::Rep* key) { return key->computedHash(); } }; + void initializeUString(); } // namespace JSC namespace WTF { diff --git a/JavaScriptCore/tests/mozilla/js1_5/Array/regress-157652.js b/JavaScriptCore/tests/mozilla/js1_5/Array/regress-157652.js index 7c61686..226b871 100644 --- a/JavaScriptCore/tests/mozilla/js1_5/Array/regress-157652.js +++ b/JavaScriptCore/tests/mozilla/js1_5/Array/regress-157652.js @@ -116,7 +116,7 @@ var summary = "Testing that Array.sort() doesn't crash on very large arrays"; printBugNumber(bug); printStatus(summary); -// KJS doesn't run out of memory, so we don't expect an abnormal exit code +// JSC doesn't run out of memory, so we don't expect an abnormal exit code //expectExitCode(3); var IN_RHINO = inRhino(); diff --git a/JavaScriptCore/wrec/CharacterClass.cpp b/JavaScriptCore/wrec/CharacterClass.cpp new file mode 100644 index 0000000..e3f12f2 --- /dev/null +++ b/JavaScriptCore/wrec/CharacterClass.cpp @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2008 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "CharacterClass.h" + +#if ENABLE(WREC) + +using namespace WTF; + +namespace JSC { namespace WREC { + +const CharacterClass& CharacterClass::newline() { + static const UChar asciiNewlines[2] = { '\n', '\r' }; + static const UChar unicodeNewlines[2] = { 0x2028, 0x2029 }; + static const CharacterClass charClass = { + asciiNewlines, 2, + 0, 0, + unicodeNewlines, 2, + 0, 0, + }; + + return charClass; +} + +const CharacterClass& CharacterClass::digits() { + static const CharacterRange asciiDigitsRange[1] = { { '0', '9' } }; + static const CharacterClass charClass = { + 0, 0, + asciiDigitsRange, 1, + 0, 0, + 0, 0, + }; + + return charClass; +} + +const CharacterClass& CharacterClass::spaces() { + static const UChar asciiSpaces[1] = { ' ' }; + static const CharacterRange asciiSpacesRange[1] = { { '\t', '\r' } }; + static const UChar unicodeSpaces[8] = { 0x00a0, 0x1680, 0x180e, 0x2028, 0x2029, 0x202f, 0x205f, 0x3000 }; + static const CharacterRange unicodeSpacesRange[1] = { { 0x2000, 0x200a } }; + static const CharacterClass charClass = { + asciiSpaces, 1, + asciiSpacesRange, 1, + unicodeSpaces, 8, + unicodeSpacesRange, 1, + }; + + return charClass; +} + +const CharacterClass& CharacterClass::wordchar() { + static const UChar asciiWordchar[1] = { '_' }; + static const CharacterRange asciiWordcharRange[3] = { { '0', '9' }, { 'A', 'Z' }, { 'a', 'z' } }; + static const CharacterClass charClass = { + asciiWordchar, 1, + asciiWordcharRange, 3, + 0, 0, + 0, 0, + }; + + return charClass; +} + +const CharacterClass& CharacterClass::nondigits() { + static const CharacterRange asciiNondigitsRange[2] = { { 0, '0' - 1 }, { '9' + 1, 0x7f } }; + static const CharacterRange unicodeNondigitsRange[1] = { { 0x0080, 0xffff } }; + static const CharacterClass charClass = { + 0, 0, + asciiNondigitsRange, 2, + 0, 0, + unicodeNondigitsRange, 1, + }; + + return charClass; +} + +const CharacterClass& CharacterClass::nonspaces() { + static const CharacterRange asciiNonspacesRange[3] = { { 0, '\t' - 1 }, { '\r' + 1, ' ' - 1 }, { ' ' + 1, 0x7f } }; + static const CharacterRange unicodeNonspacesRange[9] = { + { 0x0080, 0x009f }, + { 0x00a1, 0x167f }, + { 0x1681, 0x180d }, + { 0x180f, 0x1fff }, + { 0x200b, 0x2027 }, + { 0x202a, 0x202e }, + { 0x2030, 0x205e }, + { 0x2060, 0x2fff }, + { 0x3001, 0xffff } + }; + static const CharacterClass charClass = { + 0, 0, + asciiNonspacesRange, 3, + 0, 0, + unicodeNonspacesRange, 9, + }; + + return charClass; +} + +const CharacterClass& CharacterClass::nonwordchar() { + static const UChar asciiNonwordchar[1] = { '`' }; + static const CharacterRange asciiNonwordcharRange[4] = { { 0, '0' - 1 }, { '9' + 1, 'A' - 1 }, { 'Z' + 1, '_' - 1 }, { 'z' + 1, 0x7f } }; + static const CharacterRange unicodeNonwordcharRange[1] = { { 0x0080, 0xffff } }; + static const CharacterClass charClass = { + asciiNonwordchar, 1, + asciiNonwordcharRange, 4, + 0, 0, + unicodeNonwordcharRange, 1, + }; + + return charClass; +} + +} } // namespace JSC::WREC + +#endif // ENABLE(WREC) diff --git a/JavaScriptCore/wrec/CharacterClass.h b/JavaScriptCore/wrec/CharacterClass.h new file mode 100644 index 0000000..8a9d2fc --- /dev/null +++ b/JavaScriptCore/wrec/CharacterClass.h @@ -0,0 +1,68 @@ +/* + * 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 CharacterClass_h +#define CharacterClass_h + +#include <wtf/Platform.h> + +#if ENABLE(WREC) + +#include <wtf/unicode/Unicode.h> + +namespace JSC { namespace WREC { + + struct CharacterRange { + UChar begin; + UChar end; + }; + + struct CharacterClass { + static const CharacterClass& newline(); + static const CharacterClass& digits(); + static const CharacterClass& spaces(); + static const CharacterClass& wordchar(); + static const CharacterClass& nondigits(); + static const CharacterClass& nonspaces(); + static const CharacterClass& nonwordchar(); + + const UChar* matches; + unsigned numMatches; + + const CharacterRange* ranges; + unsigned numRanges; + + const UChar* matchesUnicode; + unsigned numMatchesUnicode; + + const CharacterRange* rangesUnicode; + unsigned numRangesUnicode; + }; + +} } // namespace JSC::WREC + +#endif // ENABLE(WREC) + +#endif // CharacterClass_h diff --git a/JavaScriptCore/wrec/CharacterClassConstructor.cpp b/JavaScriptCore/wrec/CharacterClassConstructor.cpp index 85eccaa..06f4262 100644 --- a/JavaScriptCore/wrec/CharacterClassConstructor.cpp +++ b/JavaScriptCore/wrec/CharacterClassConstructor.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Apple Inc. All rights reserved. + * 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 @@ -33,110 +33,7 @@ using namespace WTF; -namespace JSC { - -static const UChar asciiNewlines[2] = { '\n', '\r' }; -static const UChar unicodeNewlines[2] = { 0x2028, 0x2029 }; -CharacterClass& getCharacterClassNewline() { - static CharacterClass charClass = { - asciiNewlines, 2, - 0, 0, - unicodeNewlines, 2, - 0, 0, - }; - - return charClass; -} - -static const CharacterClassRange asciiDigitsRange[1] = { { '0', '9' } }; -CharacterClass& getCharacterClassDigits() { - static CharacterClass charClass = { - 0, 0, - asciiDigitsRange, 1, - 0, 0, - 0, 0, - }; - - return charClass; -} - -static const UChar asciiSpaces[1] = { ' ' }; -static const CharacterClassRange asciiSpacesRange[1] = { { '\t', '\r' } }; -static const UChar unicodeSpaces[8] = { 0x00a0, 0x1680, 0x180e, 0x2028, 0x2029, 0x202f, 0x205f, 0x3000 }; -static const CharacterClassRange unicodeSpacesRange[1] = { { 0x2000, 0x200a } }; -CharacterClass& getCharacterClassSpaces() { - static CharacterClass charClass = { - asciiSpaces, 1, - asciiSpacesRange, 1, - unicodeSpaces, 8, - unicodeSpacesRange, 1, - }; - - return charClass; -} - -static const UChar asciiWordchar[1] = { '_' }; -static const CharacterClassRange asciiWordcharRange[3] = { { '0', '9' }, { 'A', 'Z' }, { 'a', 'z' } }; -CharacterClass& getCharacterClassWordchar() { - static CharacterClass charClass = { - asciiWordchar, 1, - asciiWordcharRange, 3, - 0, 0, - 0, 0, - }; - - return charClass; -} - -static const CharacterClassRange asciiNondigitsRange[2] = { { 0, '0' - 1 }, { '9' + 1, 0x7f } }; -static const CharacterClassRange unicodeNondigitsRange[1] = { { 0x0080, 0xffff } }; -CharacterClass& getCharacterClassNondigits() { - static CharacterClass charClass = { - 0, 0, - asciiNondigitsRange, 2, - 0, 0, - unicodeNondigitsRange, 1, - }; - - return charClass; -} - -static const CharacterClassRange asciiNonspacesRange[3] = { { 0, '\t' - 1 }, { '\r' + 1, ' ' - 1 }, { ' ' + 1, 0x7f } }; -static const CharacterClassRange unicodeNonspacesRange[9] = { - { 0x0080, 0x009f }, - { 0x00a1, 0x167f }, - { 0x1681, 0x180d }, - { 0x180f, 0x1fff }, - { 0x200b, 0x2027 }, - { 0x202a, 0x202e }, - { 0x2030, 0x205e }, - { 0x2060, 0x2fff }, - { 0x3001, 0xffff } -}; -CharacterClass& getCharacterClassNonspaces() { - static CharacterClass charClass = { - 0, 0, - asciiNonspacesRange, 3, - 0, 0, - unicodeNonspacesRange, 9, - }; - - return charClass; -} - -static const UChar asciiNonwordchar[1] = { '`' }; -static const CharacterClassRange asciiNonwordcharRange[4] = { { 0, '0' - 1 }, { '9' + 1, 'A' - 1 }, { 'Z' + 1, '_' - 1 }, { 'z' + 1, 0x7f } }; -static const CharacterClassRange unicodeNonwordcharRange[1] = { { 0x0080, 0xffff } }; -CharacterClass& getCharacterClassNonwordchar() { - static CharacterClass charClass = { - asciiNonwordchar, 1, - asciiNonwordcharRange, 4, - 0, 0, - unicodeNonwordcharRange, 1, - }; - - return charClass; -} +namespace JSC { namespace WREC { void CharacterClassConstructor::addSorted(Vector<UChar>& matches, UChar ch) { @@ -164,7 +61,7 @@ void CharacterClassConstructor::addSorted(Vector<UChar>& matches, UChar ch) matches.insert(pos, ch); } -void CharacterClassConstructor::addSortedRange(Vector<CharacterClassRange>& ranges, UChar lo, UChar hi) +void CharacterClassConstructor::addSortedRange(Vector<CharacterRange>& ranges, UChar lo, UChar hi) { unsigned end = ranges.size(); @@ -178,7 +75,7 @@ void CharacterClassConstructor::addSortedRange(Vector<CharacterClassRange>& rang ranges[i].begin = lo; return; } - CharacterClassRange r = {lo, hi}; + CharacterRange r = {lo, hi}; ranges.insert(i, r); return; } @@ -206,8 +103,8 @@ void CharacterClassConstructor::addSortedRange(Vector<CharacterClassRange>& rang } } - // Range comes after all existing ranges. - CharacterClassRange r = {lo, hi}; + // CharacterRange comes after all existing ranges. + CharacterRange r = {lo, hi}; ranges.append(r); } @@ -260,19 +157,19 @@ void CharacterClassConstructor::put(UChar ch) // we're going to scan along, updating the start of the range while (unicodeCurr <= hi) { // Spin forwards over any characters that don't have two cases. - for (; kjs_pcre_ucp_othercase(unicodeCurr) == -1; ++unicodeCurr) { + for (; jsc_pcre_ucp_othercase(unicodeCurr) == -1; ++unicodeCurr) { // if this was the last character in the range, we're done. if (unicodeCurr == hi) return; } // if we fall through to here, unicodeCurr <= hi & has another case. Get the other case. UChar rangeStart = unicodeCurr; - UChar otherCurr = kjs_pcre_ucp_othercase(unicodeCurr); + UChar otherCurr = jsc_pcre_ucp_othercase(unicodeCurr); // If unicodeCurr is not yet hi, check the next char in the range. If it also has another case, // and if it's other case value is one greater then the othercase value for the current last // character included in the range, we can include next into the range. - while ((unicodeCurr < hi) && (kjs_pcre_ucp_othercase(unicodeCurr + 1) == (otherCurr + 1))) { + while ((unicodeCurr < hi) && (jsc_pcre_ucp_othercase(unicodeCurr + 1) == (otherCurr + 1))) { // increment unicodeCurr; it points to the end of the range. // increment otherCurr, due to the check above other for next must be 1 greater than the currrent other value. ++unicodeCurr; @@ -317,7 +214,7 @@ void CharacterClassConstructor::flush() } else { addSorted(m_matchesUnicode, m_charBuffer); if (m_isCaseInsensitive) { - int other = kjs_pcre_ucp_othercase(m_charBuffer); + int other = jsc_pcre_ucp_othercase(m_charBuffer); if (other != -1) addSorted(m_matchesUnicode, other); } @@ -331,7 +228,7 @@ void CharacterClassConstructor::flush() } } -void CharacterClassConstructor::append(CharacterClass& other) +void CharacterClassConstructor::append(const CharacterClass& other) { // [x-\s] will add, 'x', '-', and all unicode spaces to new class (same as [x\s-]). // Need to check the spec, really, but think this matches PCRE behaviour. @@ -355,6 +252,6 @@ void CharacterClassConstructor::append(CharacterClass& other) } } -} +} } // namespace JSC::WREC #endif // ENABLE(WREC) diff --git a/JavaScriptCore/wrec/CharacterClassConstructor.h b/JavaScriptCore/wrec/CharacterClassConstructor.h index 5accdae..581733d 100644 --- a/JavaScriptCore/wrec/CharacterClassConstructor.h +++ b/JavaScriptCore/wrec/CharacterClassConstructor.h @@ -26,38 +26,16 @@ #ifndef CharacterClassConstructor_h #define CharacterClassConstructor_h -#if ENABLE(WREC) - -#include "ustring.h" - -namespace JSC { - - struct CharacterClassRange { - UChar begin; - UChar end; - }; +#include <wtf/Platform.h> - struct CharacterClass { - const UChar* matches; - unsigned numMatches; - - const CharacterClassRange* ranges; - unsigned numRanges; - - const UChar* matchesUnicode; - unsigned numMatchesUnicode; +#if ENABLE(WREC) - const CharacterClassRange* rangesUnicode; - unsigned numRangesUnicode; - }; +#include "CharacterClass.h" +#include <wtf/AlwaysInline.h> +#include <wtf/Vector.h> +#include <wtf/unicode/Unicode.h> - CharacterClass& getCharacterClassNewline(); - CharacterClass& getCharacterClassDigits(); - CharacterClass& getCharacterClassSpaces(); - CharacterClass& getCharacterClassWordchar(); - CharacterClass& getCharacterClassNondigits(); - CharacterClass& getCharacterClassNonspaces(); - CharacterClass& getCharacterClassNonwordchar(); +namespace JSC { namespace WREC { class CharacterClassConstructor { public: @@ -83,7 +61,7 @@ namespace JSC { } void put(UChar ch); - void append(CharacterClass& other); + void append(const CharacterClass& other); bool isUpsideDown() { return m_isUpsideDown; } @@ -101,7 +79,7 @@ namespace JSC { private: void addSorted(Vector<UChar>& matches, UChar ch); - void addSortedRange(Vector<CharacterClassRange>& ranges, UChar lo, UChar hi); + void addSortedRange(Vector<CharacterRange>& ranges, UChar lo, UChar hi); int m_charBuffer; bool m_isPendingDash; @@ -109,12 +87,12 @@ namespace JSC { bool m_isUpsideDown; Vector<UChar> m_matches; - Vector<CharacterClassRange> m_ranges; + Vector<CharacterRange> m_ranges; Vector<UChar> m_matchesUnicode; - Vector<CharacterClassRange> m_rangesUnicode; + Vector<CharacterRange> m_rangesUnicode; }; -} +} } // namespace JSC::WREC #endif // ENABLE(WREC) diff --git a/JavaScriptCore/wrec/Escapes.h b/JavaScriptCore/wrec/Escapes.h new file mode 100644 index 0000000..16c1d6f --- /dev/null +++ b/JavaScriptCore/wrec/Escapes.h @@ -0,0 +1,150 @@ +/* + * Copyright (C) 2008 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef Escapes_h +#define Escapes_h + +#include <wtf/Platform.h> + +#if ENABLE(WREC) + +#include <wtf/Assertions.h> + +namespace JSC { namespace WREC { + + class CharacterClass; + + class Escape { + public: + enum Type { + PatternCharacter, + CharacterClass, + Backreference, + WordBoundaryAssertion, + Error, + }; + + Escape(Type type) + : m_type(type) + { + } + + Type type() const { return m_type; } + + private: + Type m_type; + + protected: + // Used by subclasses to store data. + union { + int i; + const WREC::CharacterClass* c; + } m_u; + bool m_invert; + }; + + class PatternCharacterEscape : public Escape { + public: + static const PatternCharacterEscape& cast(const Escape& escape) + { + ASSERT(escape.type() == PatternCharacter); + return static_cast<const PatternCharacterEscape&>(escape); + } + + PatternCharacterEscape(int character) + : Escape(PatternCharacter) + { + m_u.i = character; + } + + operator Escape() const { return *this; } + + int character() const { return m_u.i; } + }; + + class CharacterClassEscape : public Escape { + public: + static const CharacterClassEscape& cast(const Escape& escape) + { + ASSERT(escape.type() == CharacterClass); + return static_cast<const CharacterClassEscape&>(escape); + } + + CharacterClassEscape(const WREC::CharacterClass& characterClass, bool invert) + : Escape(CharacterClass) + { + m_u.c = &characterClass; + m_invert = invert; + } + + operator Escape() { return *this; } + + const WREC::CharacterClass& characterClass() const { return *m_u.c; } + bool invert() const { return m_invert; } + }; + + class BackreferenceEscape : public Escape { + public: + static const BackreferenceEscape& cast(const Escape& escape) + { + ASSERT(escape.type() == Backreference); + return static_cast<const BackreferenceEscape&>(escape); + } + + BackreferenceEscape(int subpatternId) + : Escape(Backreference) + { + m_u.i = subpatternId; + } + + operator Escape() const { return *this; } + + int subpatternId() const { return m_u.i; } + }; + + class WordBoundaryAssertionEscape : public Escape { + public: + static const WordBoundaryAssertionEscape& cast(const Escape& escape) + { + ASSERT(escape.type() == WordBoundaryAssertion); + return static_cast<const WordBoundaryAssertionEscape&>(escape); + } + + WordBoundaryAssertionEscape(bool invert) + : Escape(WordBoundaryAssertion) + { + m_invert = invert; + } + + operator Escape() const { return *this; } + + bool invert() const { return m_invert; } + }; + +} } // namespace JSC::WREC + +#endif // ENABLE(WREC) + +#endif // Escapes_h diff --git a/JavaScriptCore/wrec/Quantifier.h b/JavaScriptCore/wrec/Quantifier.h new file mode 100644 index 0000000..3da74cd --- /dev/null +++ b/JavaScriptCore/wrec/Quantifier.h @@ -0,0 +1,66 @@ +/* + * 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 Quantifier_h +#define Quantifier_h + +#include <wtf/Platform.h> + +#if ENABLE(WREC) + +#include <wtf/Assertions.h> +#include <limits.h> + +namespace JSC { namespace WREC { + + struct Quantifier { + enum Type { + None, + Greedy, + NonGreedy, + Error, + }; + + Quantifier(Type type = None, unsigned min = 0, unsigned max = Infinity) + : type(type) + , min(min) + , max(max) + { + ASSERT(min <= max); + } + + Type type; + + unsigned min; + unsigned max; + + static const unsigned Infinity = UINT_MAX; + }; + +} } // namespace JSC::WREC + +#endif // ENABLE(WREC) + +#endif // Quantifier_h diff --git a/JavaScriptCore/wrec/WREC.cpp b/JavaScriptCore/wrec/WREC.cpp index 6d64a2c..099931b 100644 --- a/JavaScriptCore/wrec/WREC.cpp +++ b/JavaScriptCore/wrec/WREC.cpp @@ -29,1296 +29,61 @@ #if ENABLE(WREC) #include "CharacterClassConstructor.h" -#include "Machine.h" +#include "Interpreter.h" +#include "JSGlobalObject.h" +#include "RegisterFile.h" +#include "WRECFunctors.h" +#include "WRECParser.h" #include "pcre_internal.h" using namespace WTF; -namespace JSC { +namespace JSC { namespace WREC { -class GenerateAtomFunctor { -public: - virtual ~GenerateAtomFunctor() {} +// Patterns longer than this can hang the compiler. +static const int MaxPatternSize = (1 << 13); - virtual void generateAtom(WRECGenerator*, JmpSrcVector&) = 0; - virtual void backtrack(WRECGenerator*) = 0; -}; - -class GeneratePatternCharacterFunctor : public GenerateAtomFunctor { -public: - GeneratePatternCharacterFunctor(const UChar ch) - : m_ch(ch) - { - } - - virtual void generateAtom(WRECGenerator*, JmpSrcVector&); - virtual void backtrack(WRECGenerator*); - -private: - const UChar m_ch; -}; - -class GenerateCharacterClassFunctor : public GenerateAtomFunctor { -public: - GenerateCharacterClassFunctor(CharacterClass* charClass, bool invert) - : m_charClass(charClass) - , m_invert(invert) - { - } - - virtual void generateAtom(WRECGenerator*, JmpSrcVector&); - virtual void backtrack(WRECGenerator*); - -private: - CharacterClass* m_charClass; - bool m_invert; -}; - -class GenerateBackreferenceFunctor : public GenerateAtomFunctor { -public: - GenerateBackreferenceFunctor(unsigned subpatternId) - : m_subpatternId(subpatternId) - { - } - - virtual void generateAtom(WRECGenerator*, JmpSrcVector&); - virtual void backtrack(WRECGenerator*); - -private: - unsigned m_subpatternId; -}; - -class GenerateParenthesesNonGreedyFunctor : public GenerateAtomFunctor { -public: - GenerateParenthesesNonGreedyFunctor(WRECGenerator::JmpDst start, WRECGenerator::JmpSrc success, WRECGenerator::JmpSrc fail) - : m_start(start) - , m_success(success) - , m_fail(fail) - { - } - - virtual void generateAtom(WRECGenerator*, JmpSrcVector&); - virtual void backtrack(WRECGenerator*); - -private: - WRECGenerator::JmpDst m_start; - WRECGenerator::JmpSrc m_success; - WRECGenerator::JmpSrc m_fail; -}; - -void GeneratePatternCharacterFunctor::generateAtom(WRECGenerator* wrec, JmpSrcVector& failures) -{ - wrec->generatePatternCharacter(failures, m_ch); -} -void GeneratePatternCharacterFunctor::backtrack(WRECGenerator* wrec) +CompiledRegExp Generator::compileRegExp(JSGlobalData* globalData, const UString& pattern, unsigned* numSubpatterns_ptr, const char** error_ptr, RefPtr<ExecutablePool>& pool, bool ignoreCase, bool multiline) { - wrec->generateBacktrack1(); -} - -void GenerateCharacterClassFunctor::generateAtom(WRECGenerator* wrec, JmpSrcVector& failures) -{ - wrec->generateCharacterClass(failures, *m_charClass, m_invert); -} -void GenerateCharacterClassFunctor::backtrack(WRECGenerator* wrec) -{ - wrec->generateBacktrack1(); -} - -void GenerateBackreferenceFunctor::generateAtom(WRECGenerator* wrec, JmpSrcVector& failures) -{ - wrec->generateBackreference(failures, m_subpatternId); -} -void GenerateBackreferenceFunctor::backtrack(WRECGenerator* wrec) -{ - wrec->generateBacktrackBackreference(m_subpatternId); -} - -void GenerateParenthesesNonGreedyFunctor::generateAtom(WRECGenerator* wrec, JmpSrcVector& failures) -{ - wrec->generateParenthesesNonGreedy(failures, m_start, m_success, m_fail); -} - -void GenerateParenthesesNonGreedyFunctor::backtrack(WRECGenerator*) -{ - // FIXME: do something about this. - CRASH(); -} - -void WRECGenerator::generateBacktrack1() -{ - m_jit.subl_i8r(1, currentPositionRegister); -} - -void WRECGenerator::generateBacktrackBackreference(unsigned subpatternId) -{ - m_jit.subl_mr((2 * subpatternId + 1) * sizeof(int), outputRegister, currentPositionRegister); - m_jit.addl_mr((2 * subpatternId) * sizeof(int), outputRegister, currentPositionRegister); -} - -void WRECGenerator::generateBackreferenceQuantifier(JmpSrcVector& failures, Quantifier::Type quantifierType, unsigned subpatternId, unsigned min, unsigned max) -{ - GenerateBackreferenceFunctor functor(subpatternId); - - m_jit.movl_mr((2 * subpatternId) * sizeof(int), outputRegister, currentValueRegister); - m_jit.cmpl_rm(currentValueRegister, ((2 * subpatternId) + 1) * sizeof(int), outputRegister); - JmpSrc skipIfEmpty = m_jit.emitUnlinkedJe(); - - ASSERT(quantifierType == Quantifier::Greedy || quantifierType == Quantifier::NonGreedy); - if (quantifierType == Quantifier::Greedy) - generateGreedyQuantifier(failures, functor, min, max); - else - generateNonGreedyQuantifier(failures, functor, min, max); - - m_jit.link(skipIfEmpty, m_jit.label()); -} - -void WRECGenerator::generateNonGreedyQuantifier(JmpSrcVector& failures, GenerateAtomFunctor& functor, unsigned min, unsigned max) -{ - // comment me better! - JmpSrcVector newFailures; - - // (0) Setup: - // init quantifierCountRegister - m_jit.pushl_r(quantifierCountRegister); - m_jit.xorl_rr(quantifierCountRegister, quantifierCountRegister); - JmpSrc gotoStart = m_jit.emitUnlinkedJmp(); - - // (4) Failure case - - JmpDst quantifierFailed = m_jit.label(); - // (4.1) Restore original value of quantifierCountRegister from the stack - m_jit.popl_r(quantifierCountRegister); - failures.append(m_jit.emitUnlinkedJmp()); - - // (3) We just tried an alternative, and it failed - check we can try more. - - JmpDst alternativeFailed = m_jit.label(); - // (3.1) remove the value pushed prior to testing the alternative - m_jit.popl_r(currentPositionRegister); - // (3.2) if there is a limit, and we have reached it, game over. - if (max != Quantifier::noMaxSpecified) { - m_jit.cmpl_i32r(max, quantifierCountRegister); - m_jit.link(m_jit.emitUnlinkedJe(), quantifierFailed); + if (pattern.size() > MaxPatternSize) { + *error_ptr = "regular expression too large"; + return 0; } - // (1) Do a check for the atom + Parser parser(pattern, ignoreCase, multiline); + Generator& generator = parser.generator(); + MacroAssembler::JumpList failures; + MacroAssembler::Jump endOfInput; - // (1.0) This is where we start, if there is a minimum (then we must read at least one of the atom). - JmpDst testQuantifiedAtom = m_jit.label(); - if (min) - m_jit.link(gotoStart, testQuantifiedAtom); - // (1.1) Do a check for the atom check. - functor.generateAtom(this, newFailures); - // (1.2) If we get here, successful match! - m_jit.addl_i8r(1, quantifierCountRegister); - // (1.3) We needed to read the atom, and we failed - that's terminally bad news. - for (unsigned i = 0; i < newFailures.size(); ++i) - m_jit.link(newFailures[i], quantifierFailed); - newFailures.clear(); - // (1.4) If there is a minimum, check we have read enough ... - if (min) { - // ... except if min was 1 no need to keep checking! - if (min != 1) { - m_jit.cmpl_i32r(min, quantifierCountRegister); - m_jit.link(m_jit.emitUnlinkedJl(), testQuantifiedAtom); - } - } else - m_jit.link(gotoStart, m_jit.label()); - // if there was no minimum, this is where we start. + generator.generateEnter(); + generator.generateSaveIndex(); - // (2) Plant an alternative check for the remainder of the expression - - // (2.1) recursively call to parseAlternative, if it falls through, success! - m_jit.pushl_r(currentPositionRegister); - m_parser.parseAlternative(newFailures); - m_jit.addl_i8r(4, X86::esp); - m_jit.popl_r(quantifierCountRegister); - // (2.2) link failure cases to jump back up to alternativeFailed. - for (unsigned i = 0; i < newFailures.size(); ++i) - m_jit.link(newFailures[i], alternativeFailed); - newFailures.clear(); -} - -void WRECGenerator::generateGreedyQuantifier(JmpSrcVector& failures, GenerateAtomFunctor& functor, unsigned min, unsigned max) -{ - if (!max) - return; - - // comment me better! - JmpSrcVector newFailures; - - // (0) Setup: - // init quantifierCountRegister - m_jit.pushl_r(quantifierCountRegister); - m_jit.xorl_rr(quantifierCountRegister, quantifierCountRegister); - - // (1) Greedily read as many of the atom as possible - - JmpDst readMore = m_jit.label(); - - // (1.1) Do a character class check. - functor.generateAtom(this, newFailures); - // (1.2) If we get here, successful match! - m_jit.addl_i8r(1, quantifierCountRegister); - // (1.3) loop, unless we've read max limit. - if (max != Quantifier::noMaxSpecified) { - if (max != 1) { - // if there is a limit, only loop while less than limit, otherwise fall throught to... - m_jit.cmpl_i32r(max, quantifierCountRegister); - m_jit.link(m_jit.emitUnlinkedJne(), readMore); - } - // ...if there is no min we need jump to the alternative test, if there is we can just fall through to it. - if (!min) - newFailures.append(m_jit.emitUnlinkedJmp()); - } else - m_jit.link(m_jit.emitUnlinkedJmp(), readMore); - // (1.4) check enough matches to bother trying an alternative... - if (min) { - // We will fall through to here if (min && max), after the max check. - // First, also link a - JmpDst minimumTest = m_jit.label(); - for (unsigned i = 0; i < newFailures.size(); ++i) - m_jit.link(newFailures[i], minimumTest); - newFailures.clear(); - // - m_jit.cmpl_i32r(min, quantifierCountRegister); - newFailures.append(m_jit.emitUnlinkedJae()); - } - - // (4) Failure case - - JmpDst quantifierFailed = m_jit.label(); - // (4.1) Restore original value of quantifierCountRegister from the stack - m_jit.popl_r(quantifierCountRegister); - failures.append(m_jit.emitUnlinkedJmp()); - - // (3) Backtrack - - JmpDst backtrack = m_jit.label(); - // (3.1) this was preserved prior to executing the alternative - m_jit.popl_r(currentPositionRegister); - // (3.2) check we can retry with fewer matches - backtracking fails if already at the minimum - m_jit.cmpl_i32r(min, quantifierCountRegister); - m_jit.link(m_jit.emitUnlinkedJe(), quantifierFailed); - // (3.3) roll off one match, and retry. - functor.backtrack(this); - m_jit.subl_i8r(1, quantifierCountRegister); + Label beginPattern(&generator); + parser.parsePattern(failures); + generator.generateReturnSuccess(); - // (2) Try an alternative. - - // (2.1) point to retry - JmpDst tryAlternative = m_jit.label(); - for (unsigned i = 0; i < newFailures.size(); ++i) - m_jit.link(newFailures[i], tryAlternative); - newFailures.clear(); - // (2.2) recursively call to parseAlternative, if it falls through, success! - m_jit.pushl_r(currentPositionRegister); - m_parser.parseAlternative(newFailures); - m_jit.addl_i8r(4, X86::esp); - m_jit.popl_r(quantifierCountRegister); - // (2.3) link failure cases to here. - for (unsigned i = 0; i < newFailures.size(); ++i) - m_jit.link(newFailures[i], backtrack); - newFailures.clear(); -} - -void WRECGenerator::generatePatternCharacter(JmpSrcVector& failures, int ch) -{ - // check there is more input, read a char. - m_jit.cmpl_rr(lengthRegister, currentPositionRegister); - failures.append(m_jit.emitUnlinkedJe()); - m_jit.movzwl_mr(inputRegister, currentPositionRegister, 2, currentValueRegister); + failures.link(&generator); + generator.generateIncrementIndex(&endOfInput); + parser.parsePattern(failures); + generator.generateReturnSuccess(); - // used for unicode case insensitive - bool hasUpper = false; - JmpSrc isUpper; + failures.link(&generator); + generator.generateIncrementIndex(); + generator.generateJumpIfNotEndOfInput(beginPattern); - // if case insensitive match - if (m_parser.m_ignoreCase) { - UChar lower, upper; - - // check for ascii case sensitive characters - if (isASCIIAlpha(ch)) { - m_jit.orl_i32r(32, currentValueRegister); - ch |= 32; - } else if ((ch > 0x7f) && ((lower = Unicode::toLower(ch)) != (upper = Unicode::toUpper(ch)))) { - // handle unicode case sentitive characters - branch to success on upper - m_jit.cmpl_i32r(upper, currentValueRegister); - isUpper = m_jit.emitUnlinkedJe(); - hasUpper = true; - ch = lower; - } - } - - // checks for ch, or lower case version of ch, if insensitive - m_jit.cmpl_i32r((unsigned short)ch, currentValueRegister); - failures.append(m_jit.emitUnlinkedJne()); - - if (m_parser.m_ignoreCase && hasUpper) { - // for unicode case insensitive matches, branch here if upper matches. - m_jit.link(isUpper, m_jit.label()); - } - - // on success consume the char - m_jit.addl_i8r(1, currentPositionRegister); -} - -void WRECGenerator::generateCharacterClassInvertedRange(JmpSrcVector& failures, JmpSrcVector& matchDest, const CharacterClassRange* ranges, unsigned count, unsigned* matchIndex, const UChar* matches, unsigned matchCount) -{ - do { - // pick which range we're going to generate - int which = count >> 1; - char lo = ranges[which].begin; - char hi = ranges[which].end; - - m_jit.cmpl_i32r((unsigned short)lo, currentValueRegister); - - // check if there are any ranges or matches below lo. If not, just jl to failure - - // if there is anything else to check, check that first, if it falls through jmp to failure. - if ((*matchIndex < matchCount) && (matches[*matchIndex] < lo)) { - JmpSrc loOrAbove = m_jit.emitUnlinkedJge(); - - // generate code for all ranges before this one - if (which) - generateCharacterClassInvertedRange(failures, matchDest, ranges, which, matchIndex, matches, matchCount); - - do { - m_jit.cmpl_i32r((unsigned short)matches[*matchIndex], currentValueRegister); - matchDest.append(m_jit.emitUnlinkedJe()); - ++*matchIndex; - } while ((*matchIndex < matchCount) && (matches[*matchIndex] < lo)); - failures.append(m_jit.emitUnlinkedJmp()); - - m_jit.link(loOrAbove, m_jit.label()); - } else if (which) { - JmpSrc loOrAbove = m_jit.emitUnlinkedJge(); - - generateCharacterClassInvertedRange(failures, matchDest, ranges, which, matchIndex, matches, matchCount); - failures.append(m_jit.emitUnlinkedJmp()); - - m_jit.link(loOrAbove, m_jit.label()); - } else - failures.append(m_jit.emitUnlinkedJl()); - - while ((*matchIndex < matchCount) && (matches[*matchIndex] <= hi)) - ++*matchIndex; - - m_jit.cmpl_i32r((unsigned short)hi, currentValueRegister); - matchDest.append(m_jit.emitUnlinkedJle()); - // fall through to here, the value is above hi. - - // shuffle along & loop around if there are any more matches to handle. - unsigned next = which + 1; - ranges += next; - count -= next; - } while (count); -} - -void WRECGenerator::generateCharacterClassInverted(JmpSrcVector& matchDest, CharacterClass& charClass) -{ - JmpSrc unicodeFail; - if (charClass.numMatchesUnicode || charClass.numRangesUnicode) { - m_jit.cmpl_i8r(0x7f, currentValueRegister); - JmpSrc isAscii = m_jit.emitUnlinkedJle(); - - if (charClass.numMatchesUnicode) { - for (unsigned i = 0; i < charClass.numMatchesUnicode; ++i) { - UChar ch = charClass.matchesUnicode[i]; - m_jit.cmpl_i32r((unsigned short)ch, currentValueRegister); - matchDest.append(m_jit.emitUnlinkedJe()); - } - } - - if (charClass.numRangesUnicode) { - for (unsigned i = 0; i < charClass.numRangesUnicode; ++i) { - UChar lo = charClass.rangesUnicode[i].begin; - UChar hi = charClass.rangesUnicode[i].end; - - m_jit.cmpl_i32r((unsigned short)lo, currentValueRegister); - JmpSrc below = m_jit.emitUnlinkedJl(); - m_jit.cmpl_i32r((unsigned short)hi, currentValueRegister); - matchDest.append(m_jit.emitUnlinkedJle()); - m_jit.link(below, m_jit.label()); - } - } - - unicodeFail = m_jit.emitUnlinkedJmp(); - m_jit.link(isAscii, m_jit.label()); - } - - if (charClass.numRanges) { - unsigned matchIndex = 0; - JmpSrcVector failures; - generateCharacterClassInvertedRange(failures, matchDest, charClass.ranges, charClass.numRanges, &matchIndex, charClass.matches, charClass.numMatches); - while (matchIndex < charClass.numMatches) { - m_jit.cmpl_i32r((unsigned short)charClass.matches[matchIndex], currentValueRegister); - matchDest.append(m_jit.emitUnlinkedJe()); - ++matchIndex; - } - JmpDst noMatch = m_jit.label(); - for (unsigned i = 0; i < failures.size(); ++i) - m_jit.link(failures[i], noMatch); - failures.clear(); - } else if (charClass.numMatches) { - // optimization: gather 'a','A' etc back together, can mask & test once. - Vector<char> matchesAZaz; - - for (unsigned i = 0; i < charClass.numMatches; ++i) { - char ch = charClass.matches[i]; - if (m_parser.m_ignoreCase) { - if (isASCIILower(ch)) { - matchesAZaz.append(ch); - continue; - } - if (isASCIIUpper(ch)) - continue; - } - m_jit.cmpl_i32r((unsigned short)ch, currentValueRegister); - matchDest.append(m_jit.emitUnlinkedJe()); - } - - if (unsigned countAZaz = matchesAZaz.size()) { - m_jit.orl_i32r(32, currentValueRegister); - - for (unsigned i = 0; i < countAZaz; ++i) { - char ch = matchesAZaz[i]; - m_jit.cmpl_i32r((unsigned short)ch, currentValueRegister); - matchDest.append(m_jit.emitUnlinkedJe()); - } - } - } - - if (charClass.numMatchesUnicode || charClass.numRangesUnicode) - m_jit.link(unicodeFail, m_jit.label()); -} - -void WRECGenerator::generateCharacterClass(JmpSrcVector& failures, CharacterClass& charClass, bool invert) -{ - m_jit.cmpl_rr(lengthRegister, currentPositionRegister); - failures.append(m_jit.emitUnlinkedJe()); - m_jit.movzwl_mr(inputRegister, currentPositionRegister, 2, currentValueRegister); - - if (invert) - generateCharacterClassInverted(failures, charClass); - else { - JmpSrcVector successes; - generateCharacterClassInverted(successes, charClass); - failures.append(m_jit.emitUnlinkedJmp()); - JmpDst here = m_jit.label(); - for (unsigned i = 0; i < successes.size(); ++i) - m_jit.link(successes[i], here); - } - - m_jit.addl_i8r(1, currentPositionRegister); -} - -WRECGenerator::JmpSrc WRECGenerator::generateParentheses(ParenthesesType type) -{ - unsigned subpatternId = (type == capturing) ? ++m_parser.m_numSubpatterns : m_parser.m_numSubpatterns; + endOfInput.link(&generator); + generator.generateReturnFailure(); - // push pos, both to preserve for fail + reloaded in parseDisjunction - m_jit.pushl_r(currentPositionRegister); - - // Plant a disjunction, wrapped to invert behaviour - - JmpSrcVector newFailures; - m_parser.parseDisjunction(newFailures); - - if (type == capturing) { - m_jit.popl_r(currentValueRegister); - m_jit.movl_rm(currentValueRegister, (2 * subpatternId) * sizeof(int), outputRegister); - m_jit.movl_rm(currentPositionRegister, (2 * subpatternId + 1) * sizeof(int), outputRegister); - } else if (type == non_capturing) - m_jit.addl_i8r(4, X86::esp); - else - m_jit.popl_r(currentPositionRegister); - - // This is a little lame - jump to jump if there is a nested disjunction. - // (suggestion to fix: make parseDisjunction populate a JmpSrcVector of - // disjunct successes... this is probably not worth the compile cost in - // the common case to fix). - JmpSrc successfulMatch = m_jit.emitUnlinkedJmp(); - - JmpDst originalFailure = m_jit.label(); - for (unsigned i = 0; i < newFailures.size(); ++i) - m_jit.link(newFailures[i], originalFailure); - newFailures.clear(); - // fail: restore currentPositionRegister - m_jit.popl_r(currentPositionRegister); - - JmpSrc jumpToFail; - // If this was an inverted assert, fail = success! - just let the failure case drop through, - // success case goes to failures. Both paths restore curr pos. - if (type == inverted_assertion) - jumpToFail = successfulMatch; - else { - // plant a jump so any fail will link off to 'failures', - jumpToFail = m_jit.emitUnlinkedJmp(); - // link successes to jump here - m_jit.link(successfulMatch, m_jit.label()); - } - return jumpToFail; -} - -void WRECGenerator::generateParenthesesNonGreedy(JmpSrcVector& failures, JmpDst start, JmpSrc success, JmpSrc fail) -{ - m_jit.link(m_jit.emitUnlinkedJmp(), start); - m_jit.link(success, m_jit.label()); - - failures.append(fail); -} - -WRECGenerator::JmpSrc WRECGenerator::generateParenthesesResetTrampoline(JmpSrcVector& newFailures, unsigned subpatternIdBefore, unsigned subpatternIdAfter) -{ - JmpSrc skip = m_jit.emitUnlinkedJmp(); - - JmpDst subPatternResetTrampoline = m_jit.label(); - for (unsigned i = 0; i < newFailures.size(); ++i) - m_jit.link(newFailures[i], subPatternResetTrampoline); - newFailures.clear(); - for (unsigned i = subpatternIdBefore + 1; i <= subpatternIdAfter; ++i) { - m_jit.movl_i32m(-1, (2 * i) * sizeof(int), outputRegister); - m_jit.movl_i32m(-1, (2 * i + 1) * sizeof(int), outputRegister); - } - - JmpSrc newFailJump = m_jit.emitUnlinkedJmp(); - m_jit.link(skip, m_jit.label()); - - return newFailJump; -} - -void WRECGenerator::generateAssertionBOL(JmpSrcVector& failures) -{ - if (m_parser.m_multiline) { - JmpSrcVector previousIsNewline; - - // begin of input == success - m_jit.cmpl_i8r(0, currentPositionRegister); - previousIsNewline.append(m_jit.emitUnlinkedJe()); - - // now check prev char against newline characters. - m_jit.movzwl_mr(-2, inputRegister, currentPositionRegister, 2, currentValueRegister); - generateCharacterClassInverted(previousIsNewline, getCharacterClassNewline()); - - failures.append(m_jit.emitUnlinkedJmp()); - - JmpDst success = m_jit.label(); - for (unsigned i = 0; i < previousIsNewline.size(); ++i) - m_jit.link(previousIsNewline[i], success); - previousIsNewline.clear(); - } else { - m_jit.cmpl_i8r(0, currentPositionRegister); - failures.append(m_jit.emitUnlinkedJne()); - } -} - -void WRECGenerator::generateAssertionEOL(JmpSrcVector& failures) -{ - if (m_parser.m_multiline) { - JmpSrcVector nextIsNewline; - - // end of input == success - m_jit.cmpl_rr(lengthRegister, currentPositionRegister); - nextIsNewline.append(m_jit.emitUnlinkedJe()); - - // now check next char against newline characters. - m_jit.movzwl_mr(inputRegister, currentPositionRegister, 2, currentValueRegister); - generateCharacterClassInverted(nextIsNewline, getCharacterClassNewline()); - - failures.append(m_jit.emitUnlinkedJmp()); - - JmpDst success = m_jit.label(); - for (unsigned i = 0; i < nextIsNewline.size(); ++i) - m_jit.link(nextIsNewline[i], success); - nextIsNewline.clear(); - } else { - m_jit.cmpl_rr(lengthRegister, currentPositionRegister); - failures.append(m_jit.emitUnlinkedJne()); + if (parser.error()) { + *error_ptr = parser.syntaxError(); // NULL in the case of patterns that WREC doesn't support yet. + return 0; } -} - -void WRECGenerator::generateAssertionWordBoundary(JmpSrcVector& failures, bool invert) -{ - JmpSrcVector wordBoundary; - JmpSrcVector notWordBoundary; - - // (1) Check if the previous value was a word char - // (1.1) check for begin of input - m_jit.cmpl_i8r(0, currentPositionRegister); - JmpSrc atBegin = m_jit.emitUnlinkedJe(); - // (1.2) load the last char, and chck if is word character - m_jit.movzwl_mr(-2, inputRegister, currentPositionRegister, 2, currentValueRegister); - JmpSrcVector previousIsWord; - generateCharacterClassInverted(previousIsWord, getCharacterClassWordchar()); - // (1.3) if we get here, previous is not a word char - m_jit.link(atBegin, m_jit.label()); - - // (2) Handle situation where previous was NOT a \w - - // (2.1) check for end of input - m_jit.cmpl_rr(lengthRegister, currentPositionRegister); - notWordBoundary.append(m_jit.emitUnlinkedJe()); - // (2.2) load the next char, and chck if is word character - m_jit.movzwl_mr(inputRegister, currentPositionRegister, 2, currentValueRegister); - generateCharacterClassInverted(wordBoundary, getCharacterClassWordchar()); - // (2.3) If we get here, neither chars are word chars - notWordBoundary.append(m_jit.emitUnlinkedJmp()); - - // (3) Handle situation where previous was a \w - - // (3.0) link success in first match to here - JmpDst section3 = m_jit.label(); - for (unsigned i = 0; i < previousIsWord.size(); ++i) - m_jit.link(previousIsWord[i], section3); - previousIsWord.clear(); - // (3.1) check for end of input - m_jit.cmpl_rr(lengthRegister, currentPositionRegister); - wordBoundary.append(m_jit.emitUnlinkedJe()); - // (3.2) load the next char, and chck if is word character - m_jit.movzwl_mr(inputRegister, currentPositionRegister, 2, currentValueRegister); - generateCharacterClassInverted(notWordBoundary, getCharacterClassWordchar()); - // (3.3) If we get here, this is an end of a word, within the input. - - // (4) Link everything up - - if (invert) { - // handle the fall through case - wordBoundary.append(m_jit.emitUnlinkedJmp()); - - // looking for non word boundaries, so link boundary fails to here. - JmpDst success = m_jit.label(); - for (unsigned i = 0; i < notWordBoundary.size(); ++i) - m_jit.link(notWordBoundary[i], success); - notWordBoundary.clear(); - - failures.append(wordBoundary.begin(), wordBoundary.size()); - } else { - // looking for word boundaries, so link successes here. - JmpDst success = m_jit.label(); - for (unsigned i = 0; i < wordBoundary.size(); ++i) - m_jit.link(wordBoundary[i], success); - wordBoundary.clear(); - - failures.append(notWordBoundary.begin(), notWordBoundary.size()); - } -} - -void WRECGenerator::generateBackreference(JmpSrcVector& failures, unsigned subpatternId) -{ - m_jit.pushl_r(currentPositionRegister); - m_jit.pushl_r(quantifierCountRegister); - - // get the start pos of the backref into quantifierCountRegister (multipurpose!) - m_jit.movl_mr((2 * subpatternId) * sizeof(int), outputRegister, quantifierCountRegister); - - JmpSrc skipIncrement = m_jit.emitUnlinkedJmp(); - JmpDst topOfLoop = m_jit.label(); - m_jit.addl_i8r(1, currentPositionRegister); - m_jit.addl_i8r(1, quantifierCountRegister); - m_jit.link(skipIncrement, m_jit.label()); - - // check if we're at the end of backref (if we are, success!) - m_jit.cmpl_rm(quantifierCountRegister, ((2 * subpatternId) + 1) * sizeof(int), outputRegister); - JmpSrc endOfBackRef = m_jit.emitUnlinkedJe(); - - m_jit.movzwl_mr(inputRegister, quantifierCountRegister, 2, currentValueRegister); - - // check if we've run out of input (this would be a can o'fail) - m_jit.cmpl_rr(lengthRegister, currentPositionRegister); - JmpSrc endOfInput = m_jit.emitUnlinkedJe(); - - m_jit.cmpw_rm(currentValueRegister, inputRegister, currentPositionRegister, 2); - m_jit.link(m_jit.emitUnlinkedJe(), topOfLoop); - - m_jit.link(endOfInput, m_jit.label()); - // Failure - m_jit.popl_r(quantifierCountRegister); - m_jit.popl_r(currentPositionRegister); - failures.append(m_jit.emitUnlinkedJmp()); - - // Success - m_jit.link(endOfBackRef, m_jit.label()); - m_jit.popl_r(quantifierCountRegister); - m_jit.addl_i8r(4, X86::esp); -} - -void WRECGenerator::generateDisjunction(JmpSrcVector& successes, JmpSrcVector& failures) -{ - successes.append(m_jit.emitUnlinkedJmp()); - - JmpDst here = m_jit.label(); - - for (unsigned i = 0; i < failures.size(); ++i) - m_jit.link(failures[i], here); - failures.clear(); - - m_jit.movl_mr(X86::esp, currentPositionRegister); -} - -void WRECGenerator::terminateDisjunction(JmpSrcVector& successes) -{ - JmpDst here = m_jit.label(); - for (unsigned i = 0; i < successes.size(); ++i) - m_jit.link(successes[i], here); - successes.clear(); -} - -ALWAYS_INLINE Quantifier WRECParser::parseGreedyQuantifier() -{ - switch (peek()) { - case '?': - consume(); - return Quantifier(Quantifier::Greedy, 0, 1); - - case '*': - consume(); - return Quantifier(Quantifier::Greedy, 0); - - case '+': - consume(); - return Quantifier(Quantifier::Greedy, 1); - - case '{': { - consume(); - // a numeric quantifier should always have a lower bound - if (!peekIsDigit()) { - m_err = Error_malformedQuantifier; - return Quantifier(Quantifier::Error); - } - int min = consumeNumber(); - - // this should either be a , or a } - switch (peek()) { - case '}': - // {n} - exactly n times. (technically I think a '?' is valid in the bnf - bit meaningless). - consume(); - return Quantifier(Quantifier::Greedy, min, min); - - case ',': - consume(); - switch (peek()) { - case '}': - // {n,} - n to inf times. - consume(); - return Quantifier(Quantifier::Greedy, min); - - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': { - // {n,m} - n to m times. - int max = consumeNumber(); - - if (peek() != '}') { - m_err = Error_malformedQuantifier; - return Quantifier(Quantifier::Error); - } - consume(); - - return Quantifier(Quantifier::Greedy, min, max); - } - - default: - m_err = Error_malformedQuantifier; - return Quantifier(Quantifier::Error); - } - - default: - m_err = Error_malformedQuantifier; - return Quantifier(Quantifier::Error); - } - } - // None of the above - no quantifier - default: - return Quantifier(); - } -} - -Quantifier WRECParser::parseQuantifier() -{ - Quantifier q = parseGreedyQuantifier(); - - if ((q.type == Quantifier::Greedy) && (peek() == '?')) { - consume(); - q.type = Quantifier::NonGreedy; - } - - return q; -} - -bool WRECParser::parsePatternCharacterQualifier(JmpSrcVector& failures, int ch) -{ - Quantifier q = parseQuantifier(); - - switch (q.type) { - case Quantifier::None: { - m_generator.generatePatternCharacter(failures, ch); - break; - } - - case Quantifier::Greedy: { - GeneratePatternCharacterFunctor functor(ch); - m_generator.generateGreedyQuantifier(failures, functor, q.min, q.max); - break; - } - - case Quantifier::NonGreedy: { - GeneratePatternCharacterFunctor functor(ch); - m_generator.generateNonGreedyQuantifier(failures, functor, q.min, q.max); - break; - } - - case Quantifier::Error: - return false; - } - - return true; -} - -bool WRECParser::parseCharacterClassQuantifier(JmpSrcVector& failures, CharacterClass& charClass, bool invert) -{ - Quantifier q = parseQuantifier(); - - switch (q.type) { - case Quantifier::None: { - m_generator.generateCharacterClass(failures, charClass, invert); - break; - } - - case Quantifier::Greedy: { - GenerateCharacterClassFunctor functor(&charClass, invert); - m_generator.generateGreedyQuantifier(failures, functor, q.min, q.max); - break; - } - - case Quantifier::NonGreedy: { - GenerateCharacterClassFunctor functor(&charClass, invert); - m_generator.generateNonGreedyQuantifier(failures, functor, q.min, q.max); - break; - } - - case Quantifier::Error: - return false; - } - - return true; -} - -bool WRECParser::parseBackreferenceQuantifier(JmpSrcVector& failures, unsigned subpatternId) -{ - Quantifier q = parseQuantifier(); - - switch (q.type) { - case Quantifier::None: { - m_generator.generateBackreference(failures, subpatternId); - break; - } - - case Quantifier::Greedy: - case Quantifier::NonGreedy: - m_generator.generateBackreferenceQuantifier(failures, q.type, subpatternId, q.min, q.max); - return true; - - case Quantifier::Error: - return false; - } - - return true; -} - -bool WRECParser::parseParentheses(JmpSrcVector&) -{ - // FIXME: We don't currently backtrack correctly within parentheses in cases such as - // "c".match(/(.*)c/) so we fall back to PCRE for any regexp containing parentheses. - - m_err = TempError_unsupportedParentheses; - return false; -} - -bool WRECParser::parseCharacterClass(JmpSrcVector& failures) -{ - bool invert = false; - if (peek() == '^') { - consume(); - invert = true; - } - - CharacterClassConstructor charClassConstructor(m_ignoreCase); - - UChar ch; - while ((ch = peek()) != ']') { - switch (ch) { - case EndOfPattern: - m_err = Error_malformedCharacterClass; - return false; - - case '\\': - consume(); - switch (ch = peek()) { - case EndOfPattern: - m_err = Error_malformedEscape; - return false; - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - charClassConstructor.put(consumeOctal()); - break; - - // ControlEscape - case 'b': - consume(); - charClassConstructor.put('\b'); - break; - case 'f': - consume(); - charClassConstructor.put('\f'); - break; - case 'n': - consume(); - charClassConstructor.put('\n'); - break; - case 'r': - consume(); - charClassConstructor.put('\r'); - break; - case 't': - consume(); - charClassConstructor.put('\t'); - break; - case 'v': - consume(); - charClassConstructor.put('\v'); - break; - - // ControlLetter - case 'c': { - consume(); - int control = consume(); - if (!isASCIIAlpha(control)) { - m_err = Error_malformedEscape; - return false; - } - charClassConstructor.put(control&31); - break; - } - - // HexEscape - case 'x': { - consume(); - int x = consumeHex(2); - if (x == -1) { - m_err = Error_malformedEscape; - return false; - } - charClassConstructor.put(x); - break; - } - - // UnicodeEscape - case 'u': { - consume(); - int x = consumeHex(4); - if (x == -1) { - m_err = Error_malformedEscape; - return false; - } - charClassConstructor.put(x); - break; - } - - // CharacterClassEscape - case 'd': - consume(); - charClassConstructor.append(getCharacterClassDigits()); - break; - case 's': - consume(); - charClassConstructor.append(getCharacterClassSpaces()); - break; - case 'w': - consume(); - charClassConstructor.append(getCharacterClassWordchar()); - break; - case 'D': - consume(); - charClassConstructor.append(getCharacterClassNondigits()); - break; - case 'S': - consume(); - charClassConstructor.append(getCharacterClassNonspaces()); - break; - case 'W': - consume(); - charClassConstructor.append(getCharacterClassNonwordchar()); - break; - - case '-': - consume(); - charClassConstructor.flushBeforeEscapedHyphen(); - charClassConstructor.put(ch); - break; - - // IdentityEscape - default: { - // TODO: check this test for IdentifierPart. - int ch = consume(); - if (isASCIIAlphanumeric(ch) || (ch == '_')) { - m_err = Error_malformedEscape; - return false; - } - charClassConstructor.put(ch); - break; - } - } - break; - - default: - consume(); - charClassConstructor.put(ch); - } - } - consume(); - - // lazily catch reversed ranges ([z-a])in character classes - if (charClassConstructor.isUpsideDown()) { - m_err = Error_malformedCharacterClass; - return false; - } - - charClassConstructor.flush(); - CharacterClass charClass = charClassConstructor.charClass(); - return parseCharacterClassQuantifier(failures, charClass, invert); -} - -bool WRECParser::parseOctalEscape(JmpSrcVector& failures) -{ - return parsePatternCharacterQualifier(failures, consumeOctal()); -} - -bool WRECParser::parseEscape(JmpSrcVector& failures) -{ - switch (peek()) { - case EndOfPattern: - m_err = Error_malformedEscape; - return false; - - // Assertions - case 'b': - consume(); - m_generator.generateAssertionWordBoundary(failures, false); - return true; - - case 'B': - consume(); - m_generator.generateAssertionWordBoundary(failures, true); - return true; - - // Octal escape - case '0': - consume(); - return parseOctalEscape(failures); - - // DecimalEscape - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': { - // FIXME: This does not support forward references. It's not clear whether they - // should be valid. - unsigned value = peekDigit(); - if (value > m_numSubpatterns) - return parseOctalEscape(failures); - } - case '8': - case '9': { - unsigned value = peekDigit(); - if (value > m_numSubpatterns) { - consume(); - m_err = Error_malformedEscape; - return false; - } - consume(); - - while (peekIsDigit()) { - unsigned newValue = value * 10 + peekDigit(); - if (newValue > m_numSubpatterns) - break; - value = newValue; - consume(); - } - - parseBackreferenceQuantifier(failures, value); - return true; - } - - // ControlEscape - case 'f': - consume(); - return parsePatternCharacterQualifier(failures, '\f'); - case 'n': - consume(); - return parsePatternCharacterQualifier(failures, '\n'); - case 'r': - consume(); - return parsePatternCharacterQualifier(failures, '\r'); - case 't': - consume(); - return parsePatternCharacterQualifier(failures, '\t'); - case 'v': - consume(); - return parsePatternCharacterQualifier(failures, '\v'); - - // ControlLetter - case 'c': { - consume(); - int control = consume(); - if (!isASCIIAlpha(control)) { - m_err = Error_malformedEscape; - return false; - } - return parsePatternCharacterQualifier(failures, control&31); - } - - // HexEscape - case 'x': { - consume(); - int x = consumeHex(2); - if (x == -1) { - m_err = Error_malformedEscape; - return false; - } - return parsePatternCharacterQualifier(failures, x); - } - - // UnicodeEscape - case 'u': { - consume(); - int x = consumeHex(4); - if (x == -1) { - m_err = Error_malformedEscape; - return false; - } - return parsePatternCharacterQualifier(failures, x); - } - - // CharacterClassEscape - case 'd': - consume(); - return parseCharacterClassQuantifier(failures, getCharacterClassDigits(), false); - case 's': - consume(); - return parseCharacterClassQuantifier(failures, getCharacterClassSpaces(), false); - case 'w': - consume(); - return parseCharacterClassQuantifier(failures, getCharacterClassWordchar(), false); - case 'D': - consume(); - return parseCharacterClassQuantifier(failures, getCharacterClassDigits(), true); - case 'S': - consume(); - return parseCharacterClassQuantifier(failures, getCharacterClassSpaces(), true); - case 'W': - consume(); - return parseCharacterClassQuantifier(failures, getCharacterClassWordchar(), true); - - // IdentityEscape - default: { - // TODO: check this test for IdentifierPart. - int ch = consume(); - if (isASCIIAlphanumeric(ch) || (ch == '_')) { - m_err = Error_malformedEscape; - return false; - } - return parsePatternCharacterQualifier(failures, ch); - } - } -} - -bool WRECParser::parseTerm(JmpSrcVector& failures) -{ - switch (peek()) { - case EndOfPattern: - case '*': - case '+': - case '?': - case ')': - case ']': - case '{': - case '}': - case '|': - // Not allowed in a Term! - return false; - - case '^': - consume(); - m_generator.generateAssertionBOL(failures); - return true; - - case '$': - consume(); - m_generator.generateAssertionEOL(failures); - return true; - - case '\\': - // b & B are also assertions... - consume(); - return parseEscape(failures); - - case '.': - consume(); - return parseCharacterClassQuantifier(failures, getCharacterClassNewline(), true); - - case '[': - // CharacterClass - consume(); - return parseCharacterClass(failures); - - case '(': - consume(); - return parseParentheses(failures); - - default: - // Anything else is a PatternCharacter - return parsePatternCharacterQualifier(failures, consume()); - } -} - -/* - interface req: CURR_POS is on stack (can be reloaded). -*/ -void WRECParser::parseDisjunction(JmpSrcVector& failures) -{ - parseAlternative(failures); - - if (peek() == '|') { - JmpSrcVector successes; - - do { - consume(); - - m_generator.generateDisjunction(successes, failures); - - parseAlternative(failures); - } while (peek() == '|'); - - m_generator.terminateDisjunction(successes); - } + *numSubpatterns_ptr = parser.numSubpatterns(); + pool = globalData->poolForSize(generator.size()); + return reinterpret_cast<CompiledRegExp>(generator.copyCode(pool.get())); } -} // namespace JSC +} } // namespace JSC::WREC #endif // ENABLE(WREC) diff --git a/JavaScriptCore/wrec/WREC.h b/JavaScriptCore/wrec/WREC.h index 301bd3b..483dce0 100644 --- a/JavaScriptCore/wrec/WREC.h +++ b/JavaScriptCore/wrec/WREC.h @@ -26,232 +26,28 @@ #ifndef WREC_h #define WREC_h +#include <wtf/Platform.h> + #if ENABLE(WREC) -#include "ustring.h" -#include <masm/X86Assembler.h> -#include <wtf/ASCIICType.h> -#include <wtf/Vector.h> +#include <wtf/unicode/Unicode.h> -#if COMPILER(GCC) +#if COMPILER(GCC) && PLATFORM(X86) #define WREC_CALL __attribute__ ((regparm (3))) #else #define WREC_CALL #endif namespace JSC { + class Interpreter; + class UString; +} - typedef int (*WRECFunction)(const UChar* input, unsigned start, unsigned length, int* output) WREC_CALL; - - class GenerateAtomFunctor; - struct CharacterClassRange; - struct CharacterClass; - - struct Quantifier { - enum Type { - None, - Greedy, - NonGreedy, - Error, - }; - - Quantifier() - : type(None) - { - } - - Quantifier(Type type, unsigned min = 0, unsigned max = noMaxSpecified) - : type(type) - , min(min) - , max(max) - { - } - - Type type; - - unsigned min; - unsigned max; - - static const unsigned noMaxSpecified = UINT_MAX; - }; - - class WRECParser; - - typedef Vector<X86Assembler::JmpSrc> JmpSrcVector; - - class WRECGenerator { - public: - WRECGenerator(WRECParser& parser, X86Assembler& jit) - : m_parser(parser) - , m_jit(jit) - { - } - - typedef X86Assembler::JmpSrc JmpSrc; - typedef X86Assembler::JmpDst JmpDst; - - // these regs setup by the params - static const X86Assembler::RegisterID inputRegister = X86::eax; - static const X86Assembler::RegisterID currentPositionRegister = X86::edx; - static const X86Assembler::RegisterID lengthRegister = X86::ecx; - static const X86Assembler::RegisterID currentValueRegister = X86::esi; - static const X86Assembler::RegisterID outputRegister = X86::edi; - static const X86Assembler::RegisterID quantifierCountRegister = X86::ebx; - - friend class GenerateAtomFunctor; - friend class GeneratePatternCharacterFunctor; - friend class GenerateCharacterClassFunctor; - friend class GenerateBackreferenceFunctor; - friend class GenerateParenthesesNonGreedyFunctor; - - void generateGreedyQuantifier(JmpSrcVector& failures, GenerateAtomFunctor& functor, unsigned min, unsigned max); - void generateNonGreedyQuantifier(JmpSrcVector& failures, GenerateAtomFunctor& functor, unsigned min, unsigned max); - void generateBacktrack1(); - void generateBacktrackBackreference(unsigned subpatternId); - void generateCharacterClass(JmpSrcVector& failures, CharacterClass& charClass, bool invert); - void generateCharacterClassInverted(JmpSrcVector& failures, CharacterClass& charClass); - void generateCharacterClassInvertedRange(JmpSrcVector& failures, JmpSrcVector& matchDest, const CharacterClassRange* ranges, unsigned count, unsigned* matchIndex, const UChar* matches, unsigned matchCount); - void generatePatternCharacter(JmpSrcVector& failures, int ch); - void generateAssertionWordBoundary(JmpSrcVector& failures, bool invert); - void generateAssertionBOL(JmpSrcVector& failures); - void generateAssertionEOL(JmpSrcVector& failures); - void generateBackreference(JmpSrcVector& failures, unsigned subpatternID); - void generateBackreferenceQuantifier(JmpSrcVector& failures, Quantifier::Type quantifierType, unsigned subpatternId, unsigned min, unsigned max); - enum ParenthesesType { capturing, non_capturing, assertion, inverted_assertion }; // order is relied on in generateParentheses() - JmpSrc generateParentheses(ParenthesesType type); - JmpSrc generateParenthesesResetTrampoline(JmpSrcVector& newFailures, unsigned subpatternIdBefore, unsigned subpatternIdAfter); - void generateParenthesesNonGreedy(JmpSrcVector& failures, JmpDst start, JmpSrc success, JmpSrc fail); - - void generateDisjunction(JmpSrcVector& successes, JmpSrcVector& failures); - void terminateDisjunction(JmpSrcVector& successes); - - private: - WRECParser& m_parser; - X86Assembler& m_jit; - }; - - class WRECParser { - public: - bool m_ignoreCase; - bool m_multiline; - unsigned m_numSubpatterns; - enum WRECError { - NoError, - Error_malformedCharacterClass, - Error_malformedParentheses, - Error_malformedPattern, - Error_malformedQuantifier, - Error_malformedEscape, - TempError_unsupportedQuantifier, - TempError_unsupportedParentheses, - } m_err; - - WRECParser(const UString& pattern, bool ignoreCase, bool multiline, X86Assembler& jit) - : m_ignoreCase(ignoreCase) - , m_multiline(multiline) - , m_numSubpatterns(0) - , m_err(NoError) - , m_generator(*this, jit) - , m_data(pattern.data()) - , m_size(pattern.size()) - , m_index(0) - { - } - - void parseAlternative(JmpSrcVector& failures) - { - while (parseTerm(failures)) { } - } - - void parseDisjunction(JmpSrcVector& failures); - - bool parseTerm(JmpSrcVector& failures); - bool parseEscape(JmpSrcVector& failures); - bool parseOctalEscape(JmpSrcVector& failures); - bool parseParentheses(JmpSrcVector& failures); - bool parseCharacterClass(JmpSrcVector& failures); - bool parseCharacterClassQuantifier(JmpSrcVector& failures, CharacterClass& charClass, bool invert); - bool parsePatternCharacterQualifier(JmpSrcVector& failures, int ch); - bool parseBackreferenceQuantifier(JmpSrcVector& failures, unsigned subpatternId); - - ALWAYS_INLINE Quantifier parseGreedyQuantifier(); - Quantifier parseQuantifier(); - - static const int EndOfPattern = -1; - - int peek() - { - if (m_index >= m_size) - return EndOfPattern; - return m_data[m_index]; - } - - int consume() - { - if (m_index >= m_size) - return EndOfPattern; - return m_data[m_index++]; - } - - bool peekIsDigit() - { - return WTF::isASCIIDigit(peek()); - } - - unsigned peekDigit() - { - ASSERT(peekIsDigit()); - return peek() - '0'; - } - - unsigned consumeDigit() - { - ASSERT(peekIsDigit()); - return consume() - '0'; - } - - unsigned consumeNumber() - { - int n = consumeDigit(); - while (peekIsDigit()) { - n *= 10; - n += consumeDigit(); - } - return n; - } - - int consumeHex(int count) - { - int n = 0; - while (count--) { - if (!WTF::isASCIIHexDigit(peek())) - return -1; - n = (n<<4) | WTF::toASCIIHexValue(consume()); - } - return n; - } - - unsigned consumeOctal() - { - unsigned n = 0; - while (n < 32 && WTF::isASCIIOctalDigit(peek())) - n = n * 8 + (consume() - '0'); - return n; - } +namespace JSC { namespace WREC { - bool isEndOfPattern() - { - return peek() != EndOfPattern; - } - - private: - WRECGenerator m_generator; - const UChar* m_data; - unsigned m_size; - unsigned m_index; - }; + typedef int (*CompiledRegExp)(const UChar* input, unsigned start, unsigned length, int* output) WREC_CALL; -} // namespace JSC +} } // namespace JSC::WREC #endif // ENABLE(WREC) diff --git a/JavaScriptCore/wrec/WRECFunctors.cpp b/JavaScriptCore/wrec/WRECFunctors.cpp new file mode 100644 index 0000000..5f1674e --- /dev/null +++ b/JavaScriptCore/wrec/WRECFunctors.cpp @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2008 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "WRECFunctors.h" + +#if ENABLE(WREC) + +#include "WRECGenerator.h" + +using namespace WTF; + +namespace JSC { namespace WREC { + +void GeneratePatternCharacterFunctor::generateAtom(Generator* generator, Generator::JumpList& failures) +{ + generator->generatePatternCharacter(failures, m_ch); +} + +void GeneratePatternCharacterFunctor::backtrack(Generator* generator) +{ + generator->generateBacktrack1(); +} + +void GenerateCharacterClassFunctor::generateAtom(Generator* generator, Generator::JumpList& failures) +{ + generator->generateCharacterClass(failures, *m_charClass, m_invert); +} + +void GenerateCharacterClassFunctor::backtrack(Generator* generator) +{ + generator->generateBacktrack1(); +} + +void GenerateBackreferenceFunctor::generateAtom(Generator* generator, Generator::JumpList& failures) +{ + generator->generateBackreference(failures, m_subpatternId); +} + +void GenerateBackreferenceFunctor::backtrack(Generator* generator) +{ + generator->generateBacktrackBackreference(m_subpatternId); +} + +void GenerateParenthesesNonGreedyFunctor::generateAtom(Generator* generator, Generator::JumpList& failures) +{ + generator->generateParenthesesNonGreedy(failures, m_start, m_success, m_fail); +} + +void GenerateParenthesesNonGreedyFunctor::backtrack(Generator*) +{ + // FIXME: do something about this. + CRASH(); +} + +} } // namespace JSC::WREC + +#endif // ENABLE(WREC) diff --git a/JavaScriptCore/wrec/WRECFunctors.h b/JavaScriptCore/wrec/WRECFunctors.h new file mode 100644 index 0000000..610ce55 --- /dev/null +++ b/JavaScriptCore/wrec/WRECFunctors.h @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2008 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <wtf/Platform.h> + +#if ENABLE(WREC) + +#include "WRECGenerator.h" +#include <wtf/unicode/Unicode.h> + +namespace JSC { namespace WREC { + + struct CharacterClass; + + class GenerateAtomFunctor { + public: + virtual ~GenerateAtomFunctor() {} + + virtual void generateAtom(Generator*, Generator::JumpList&) = 0; + virtual void backtrack(Generator*) = 0; + }; + + class GeneratePatternCharacterFunctor : public GenerateAtomFunctor { + public: + GeneratePatternCharacterFunctor(const UChar ch) + : m_ch(ch) + { + } + + virtual void generateAtom(Generator*, Generator::JumpList&); + virtual void backtrack(Generator*); + + private: + const UChar m_ch; + }; + + class GenerateCharacterClassFunctor : public GenerateAtomFunctor { + public: + GenerateCharacterClassFunctor(const CharacterClass* charClass, bool invert) + : m_charClass(charClass) + , m_invert(invert) + { + } + + virtual void generateAtom(Generator*, Generator::JumpList&); + virtual void backtrack(Generator*); + + private: + const CharacterClass* m_charClass; + bool m_invert; + }; + + class GenerateBackreferenceFunctor : public GenerateAtomFunctor { + public: + GenerateBackreferenceFunctor(unsigned subpatternId) + : m_subpatternId(subpatternId) + { + } + + virtual void generateAtom(Generator*, Generator::JumpList&); + virtual void backtrack(Generator*); + + private: + unsigned m_subpatternId; + }; + + class GenerateParenthesesNonGreedyFunctor : public GenerateAtomFunctor { + public: + GenerateParenthesesNonGreedyFunctor(Generator::Label start, Generator::Jump success, Generator::Jump fail) + : m_start(start) + , m_success(success) + , m_fail(fail) + { + } + + virtual void generateAtom(Generator*, Generator::JumpList&); + virtual void backtrack(Generator*); + + private: + Generator::Label m_start; + Generator::Jump m_success; + Generator::Jump m_fail; + }; + +} } // namespace JSC::WREC + +#endif // ENABLE(WREC) diff --git a/JavaScriptCore/wrec/WRECGenerator.cpp b/JavaScriptCore/wrec/WRECGenerator.cpp new file mode 100644 index 0000000..4b5f3d4 --- /dev/null +++ b/JavaScriptCore/wrec/WRECGenerator.cpp @@ -0,0 +1,665 @@ +/* + * Copyright (C) 2008 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "WREC.h" + +#if ENABLE(WREC) + +#include "CharacterClassConstructor.h" +#include "Interpreter.h" +#include "WRECFunctors.h" +#include "WRECParser.h" +#include "pcre_internal.h" + +using namespace WTF; + +namespace JSC { namespace WREC { + +void Generator::generateEnter() +{ +#if PLATFORM(X86_64) + // On x86-64 edi and esi are caller preserved, so nothing to do here. + // The four arguments have been passed in the registers %rdi, %rsi, + // %rdx, %rcx - shuffle these into the expected locations. + move(X86::edi, input); // (arg 1) edi -> eax + move(X86::ecx, output); // (arg 4) ecx -> edi + move(X86::edx, length); // (arg 3) edx -> ecx + move(X86::esi, index); // (arg 2) esi -> edx + +#else + // On x86 edi & esi are callee preserved registers. + push(X86::edi); + push(X86::esi); + +#if COMPILER(MSVC) + // Move the arguments into registers. + peek(input, 3); + peek(index, 4); + peek(length, 5); + peek(output, 6); +#else + // On gcc the function is regparm(3), so the input, index, and length registers + // (eax, edx, and ecx respectively) already contain the appropriate values. + // Just load the fourth argument (output) into edi + peek(output, 3); +#endif +#endif + +#ifndef NDEBUG + // ASSERT that the output register is not null. + Jump outputNotNull = jnzPtr(output); + breakpoint(); + outputNotNull.link(this); +#endif +} + +void Generator::generateReturnSuccess() +{ + // Set return value. + pop(X86::eax); // match begin + store32(X86::eax, output); + store32(index, Address(output, 4)); // match end + + // Restore callee save registers. +#if !PLATFORM(X86_64) + pop(X86::esi); + pop(X86::edi); +#endif + ret(); +} + +void Generator::generateSaveIndex() +{ + push(index); +} + +void Generator::generateIncrementIndex(Jump* failure) +{ + peek(index); + if (failure) + *failure = je32(length, index); + add32(Imm32(1), index); + poke(index); +} + +void Generator::generateLoadCharacter(JumpList& failures) +{ + failures.append(je32(length, index)); + load16(BaseIndex(input, index, TimesTwo), character); +} + +// For the sake of end-of-line assertions, we treat one-past-the-end as if it +// were part of the input string. +void Generator::generateJumpIfNotEndOfInput(Label target) +{ + jle32(index, length, target); +} + +void Generator::generateReturnFailure() +{ + pop(); + move(Imm32(-1), X86::eax); +#if !PLATFORM(X86_64) + pop(X86::esi); + pop(X86::edi); +#endif + ret(); +} + +void Generator::generateBacktrack1() +{ + sub32(Imm32(1), index); +} + +void Generator::generateBacktrackBackreference(unsigned subpatternId) +{ + sub32(Address(output, (2 * subpatternId + 1) * sizeof(int)), index); + add32(Address(output, (2 * subpatternId) * sizeof(int)), index); +} + +void Generator::generateBackreferenceQuantifier(JumpList& failures, Quantifier::Type quantifierType, unsigned subpatternId, unsigned min, unsigned max) +{ + GenerateBackreferenceFunctor functor(subpatternId); + + load32(Address(output, (2 * subpatternId) * sizeof(int)), character); + Jump skipIfEmpty = je32(Address(output, ((2 * subpatternId) + 1) * sizeof(int)), character); + + ASSERT(quantifierType == Quantifier::Greedy || quantifierType == Quantifier::NonGreedy); + if (quantifierType == Quantifier::Greedy) + generateGreedyQuantifier(failures, functor, min, max); + else + generateNonGreedyQuantifier(failures, functor, min, max); + + skipIfEmpty.link(this); +} + +void Generator::generateNonGreedyQuantifier(JumpList& failures, GenerateAtomFunctor& functor, unsigned min, unsigned max) +{ + JumpList atomFailedList; + JumpList alternativeFailedList; + + // (0) Setup: Save, then init repeatCount. + push(repeatCount); + move(Imm32(0), repeatCount); + Jump start = jump(); + + // (4) Quantifier failed: No more atom reading possible. + Label quantifierFailed(this); + pop(repeatCount); + failures.append(jump()); + + // (3) Alternative failed: If we can, read another atom, then fall through to (2) to try again. + Label alternativeFailed(this); + pop(index); + if (max != Quantifier::Infinity) + je32(repeatCount, Imm32(max), quantifierFailed); + + // (1) Read an atom. + if (min) + start.link(this); + Label readAtom(this); + functor.generateAtom(this, atomFailedList); + atomFailedList.linkTo(quantifierFailed, this); + add32(Imm32(1), repeatCount); + + // (2) Keep reading if we're under the minimum. + if (min > 1) + jl32(repeatCount, Imm32(min), readAtom); + + // (3) Test the rest of the alternative. + if (!min) + start.link(this); + push(index); + m_parser.parseAlternative(alternativeFailedList); + alternativeFailedList.linkTo(alternativeFailed, this); + + pop(); + pop(repeatCount); +} + +void Generator::generateGreedyQuantifier(JumpList& failures, GenerateAtomFunctor& functor, unsigned min, unsigned max) +{ + if (!max) + return; + + JumpList doneReadingAtomsList; + JumpList alternativeFailedList; + + // (0) Setup: Save, then init repeatCount. + push(repeatCount); + move(Imm32(0), repeatCount); + + // (1) Greedily read as many copies of the atom as possible, then jump to (2). + Label readAtom(this); + functor.generateAtom(this, doneReadingAtomsList); + add32(Imm32(1), repeatCount); + if (max == Quantifier::Infinity) + jump(readAtom); + else if (max == 1) + doneReadingAtomsList.append(jump()); + else { + jne32(repeatCount, Imm32(max), readAtom); + doneReadingAtomsList.append(jump()); + } + + // (5) Quantifier failed: No more backtracking possible. + Label quantifierFailed(this); + pop(repeatCount); + failures.append(jump()); + + // (4) Alternative failed: Backtrack, then fall through to (2) to try again. + Label alternativeFailed(this); + pop(index); + functor.backtrack(this); + sub32(Imm32(1), repeatCount); + + // (2) Verify that we have enough atoms. + doneReadingAtomsList.link(this); + jl32(repeatCount, Imm32(min), quantifierFailed); + + // (3) Test the rest of the alternative. + push(index); + m_parser.parseAlternative(alternativeFailedList); + alternativeFailedList.linkTo(alternativeFailed, this); + + pop(); + pop(repeatCount); +} + +void Generator::generatePatternCharacterSequence(JumpList& failures, int* sequence, size_t count) +{ + for (size_t i = 0; i < count;) { + if (i < count - 1) { + if (generatePatternCharacterPair(failures, sequence[i], sequence[i + 1])) { + i += 2; + continue; + } + } + + generatePatternCharacter(failures, sequence[i]); + ++i; + } +} + +bool Generator::generatePatternCharacterPair(JumpList& failures, int ch1, int ch2) +{ + if (m_parser.ignoreCase()) { + // Non-trivial case folding requires more than one test, so we can't + // test as a pair with an adjacent character. + if (!isASCII(ch1) && Unicode::toLower(ch1) != Unicode::toUpper(ch1)) + return false; + if (!isASCII(ch2) && Unicode::toLower(ch2) != Unicode::toUpper(ch2)) + return false; + } + + // Optimistically consume 2 characters. + add32(Imm32(2), index); + failures.append(jg32(index, length)); + + // Load the characters we just consumed, offset -2 characters from index. + load32(BaseIndex(input, index, TimesTwo, -2 * 2), character); + + if (m_parser.ignoreCase()) { + // Convert ASCII alphabet characters to upper case before testing for + // equality. (ASCII non-alphabet characters don't require upper-casing + // because they have no uppercase equivalents. Unicode characters don't + // require upper-casing because we only handle Unicode characters whose + // upper and lower cases are equal.) + int ch1Mask = 0; + if (isASCIIAlpha(ch1)) { + ch1 |= 32; + ch1Mask = 32; + } + + int ch2Mask = 0; + if (isASCIIAlpha(ch2)) { + ch2 |= 32; + ch2Mask = 32; + } + + int mask = ch1Mask | (ch2Mask << 16); + if (mask) + or32(Imm32(mask), character); + } + int pair = ch1 | (ch2 << 16); + + failures.append(jne32(character, Imm32(pair))); + return true; +} + +void Generator::generatePatternCharacter(JumpList& failures, int ch) +{ + generateLoadCharacter(failures); + + // used for unicode case insensitive + bool hasUpper = false; + Jump isUpper; + + // if case insensitive match + if (m_parser.ignoreCase()) { + UChar lower, upper; + + // check for ascii case sensitive characters + if (isASCIIAlpha(ch)) { + or32(Imm32(32), character); + ch |= 32; + } else if (!isASCII(ch) && ((lower = Unicode::toLower(ch)) != (upper = Unicode::toUpper(ch)))) { + // handle unicode case sentitive characters - branch to success on upper + isUpper = je32(character, Imm32(upper)); + hasUpper = true; + ch = lower; + } + } + + // checks for ch, or lower case version of ch, if insensitive + failures.append(jne32(character, Imm32((unsigned short)ch))); + + if (m_parser.ignoreCase() && hasUpper) { + // for unicode case insensitive matches, branch here if upper matches. + isUpper.link(this); + } + + // on success consume the char + add32(Imm32(1), index); +} + +void Generator::generateCharacterClassInvertedRange(JumpList& failures, JumpList& matchDest, const CharacterRange* ranges, unsigned count, unsigned* matchIndex, const UChar* matches, unsigned matchCount) +{ + do { + // pick which range we're going to generate + int which = count >> 1; + char lo = ranges[which].begin; + char hi = ranges[which].end; + + // check if there are any ranges or matches below lo. If not, just jl to failure - + // if there is anything else to check, check that first, if it falls through jmp to failure. + if ((*matchIndex < matchCount) && (matches[*matchIndex] < lo)) { + Jump loOrAbove = jge32(character, Imm32((unsigned short)lo)); + + // generate code for all ranges before this one + if (which) + generateCharacterClassInvertedRange(failures, matchDest, ranges, which, matchIndex, matches, matchCount); + + while ((*matchIndex < matchCount) && (matches[*matchIndex] < lo)) { + matchDest.append(je32(character, Imm32((unsigned short)matches[*matchIndex]))); + ++*matchIndex; + } + failures.append(jump()); + + loOrAbove.link(this); + } else if (which) { + Jump loOrAbove = jge32(character, Imm32((unsigned short)lo)); + + generateCharacterClassInvertedRange(failures, matchDest, ranges, which, matchIndex, matches, matchCount); + failures.append(jump()); + + loOrAbove.link(this); + } else + failures.append(jl32(character, Imm32((unsigned short)lo))); + + while ((*matchIndex < matchCount) && (matches[*matchIndex] <= hi)) + ++*matchIndex; + + matchDest.append(jle32(character, Imm32((unsigned short)hi))); + // fall through to here, the value is above hi. + + // shuffle along & loop around if there are any more matches to handle. + unsigned next = which + 1; + ranges += next; + count -= next; + } while (count); +} + +void Generator::generateCharacterClassInverted(JumpList& matchDest, const CharacterClass& charClass) +{ + Jump unicodeFail; + if (charClass.numMatchesUnicode || charClass.numRangesUnicode) { + Jump isAscii = jle32(character, Imm32(0x7f)); + + if (charClass.numMatchesUnicode) { + for (unsigned i = 0; i < charClass.numMatchesUnicode; ++i) { + UChar ch = charClass.matchesUnicode[i]; + matchDest.append(je32(character, Imm32(ch))); + } + } + + if (charClass.numRangesUnicode) { + for (unsigned i = 0; i < charClass.numRangesUnicode; ++i) { + UChar lo = charClass.rangesUnicode[i].begin; + UChar hi = charClass.rangesUnicode[i].end; + + Jump below = jl32(character, Imm32(lo)); + matchDest.append(jle32(character, Imm32(hi))); + below.link(this); + } + } + + unicodeFail = jump(); + isAscii.link(this); + } + + if (charClass.numRanges) { + unsigned matchIndex = 0; + JumpList failures; + generateCharacterClassInvertedRange(failures, matchDest, charClass.ranges, charClass.numRanges, &matchIndex, charClass.matches, charClass.numMatches); + while (matchIndex < charClass.numMatches) + matchDest.append(je32(character, Imm32((unsigned short)charClass.matches[matchIndex++]))); + + failures.link(this); + } else if (charClass.numMatches) { + // optimization: gather 'a','A' etc back together, can mask & test once. + Vector<char> matchesAZaz; + + for (unsigned i = 0; i < charClass.numMatches; ++i) { + char ch = charClass.matches[i]; + if (m_parser.ignoreCase()) { + if (isASCIILower(ch)) { + matchesAZaz.append(ch); + continue; + } + if (isASCIIUpper(ch)) + continue; + } + matchDest.append(je32(character, Imm32((unsigned short)ch))); + } + + if (unsigned countAZaz = matchesAZaz.size()) { + or32(Imm32(32), character); + for (unsigned i = 0; i < countAZaz; ++i) + matchDest.append(je32(character, Imm32(matchesAZaz[i]))); + } + } + + if (charClass.numMatchesUnicode || charClass.numRangesUnicode) + unicodeFail.link(this); +} + +void Generator::generateCharacterClass(JumpList& failures, const CharacterClass& charClass, bool invert) +{ + generateLoadCharacter(failures); + + if (invert) + generateCharacterClassInverted(failures, charClass); + else { + JumpList successes; + generateCharacterClassInverted(successes, charClass); + failures.append(jump()); + successes.link(this); + } + + add32(Imm32(1), index); +} + +void Generator::generateParenthesesAssertion(JumpList& failures) +{ + JumpList disjunctionFailed; + + push(index); + m_parser.parseDisjunction(disjunctionFailed); + Jump success = jump(); + + disjunctionFailed.link(this); + pop(index); + failures.append(jump()); + + success.link(this); + pop(index); +} + +void Generator::generateParenthesesInvertedAssertion(JumpList& failures) +{ + JumpList disjunctionFailed; + + push(index); + m_parser.parseDisjunction(disjunctionFailed); + + // If the disjunction succeeded, the inverted assertion failed. + pop(index); + failures.append(jump()); + + // If the disjunction failed, the inverted assertion succeeded. + disjunctionFailed.link(this); + pop(index); +} + +void Generator::generateParenthesesNonGreedy(JumpList& failures, Label start, Jump success, Jump fail) +{ + jump(start); + success.link(this); + failures.append(fail); +} + +Generator::Jump Generator::generateParenthesesResetTrampoline(JumpList& newFailures, unsigned subpatternIdBefore, unsigned subpatternIdAfter) +{ + Jump skip = jump(); + newFailures.link(this); + for (unsigned i = subpatternIdBefore + 1; i <= subpatternIdAfter; ++i) { + store32(Imm32(-1), Address(output, (2 * i) * sizeof(int))); + store32(Imm32(-1), Address(output, (2 * i + 1) * sizeof(int))); + } + + Jump newFailJump = jump(); + skip.link(this); + + return newFailJump; +} + +void Generator::generateAssertionBOL(JumpList& failures) +{ + if (m_parser.multiline()) { + JumpList previousIsNewline; + + // begin of input == success + previousIsNewline.append(je32(index, Imm32(0))); + + // now check prev char against newline characters. + load16(BaseIndex(input, index, TimesTwo, -2), character); + generateCharacterClassInverted(previousIsNewline, CharacterClass::newline()); + + failures.append(jump()); + + previousIsNewline.link(this); + } else + failures.append(jne32(index, Imm32(0))); +} + +void Generator::generateAssertionEOL(JumpList& failures) +{ + if (m_parser.multiline()) { + JumpList nextIsNewline; + + generateLoadCharacter(nextIsNewline); // end of input == success + generateCharacterClassInverted(nextIsNewline, CharacterClass::newline()); + failures.append(jump()); + nextIsNewline.link(this); + } else { + failures.append(jne32(length, index)); + } +} + +void Generator::generateAssertionWordBoundary(JumpList& failures, bool invert) +{ + JumpList wordBoundary; + JumpList notWordBoundary; + + // (1) Check if the previous value was a word char + + // (1.1) check for begin of input + Jump atBegin = je32(index, Imm32(0)); + // (1.2) load the last char, and chck if is word character + load16(BaseIndex(input, index, TimesTwo, -2), character); + JumpList previousIsWord; + generateCharacterClassInverted(previousIsWord, CharacterClass::wordchar()); + // (1.3) if we get here, previous is not a word char + atBegin.link(this); + + // (2) Handle situation where previous was NOT a \w + + generateLoadCharacter(notWordBoundary); + generateCharacterClassInverted(wordBoundary, CharacterClass::wordchar()); + // (2.1) If we get here, neither chars are word chars + notWordBoundary.append(jump()); + + // (3) Handle situation where previous was a \w + + // (3.0) link success in first match to here + previousIsWord.link(this); + generateLoadCharacter(wordBoundary); + generateCharacterClassInverted(notWordBoundary, CharacterClass::wordchar()); + // (3.1) If we get here, this is an end of a word, within the input. + + // (4) Link everything up + + if (invert) { + // handle the fall through case + wordBoundary.append(jump()); + + // looking for non word boundaries, so link boundary fails to here. + notWordBoundary.link(this); + + failures.append(wordBoundary); + } else { + // looking for word boundaries, so link successes here. + wordBoundary.link(this); + + failures.append(notWordBoundary); + } +} + +void Generator::generateBackreference(JumpList& failures, unsigned subpatternId) +{ + push(index); + push(repeatCount); + + // get the start pos of the backref into repeatCount (multipurpose!) + load32(Address(output, (2 * subpatternId) * sizeof(int)), repeatCount); + + Jump skipIncrement = jump(); + Label topOfLoop(this); + + add32(Imm32(1), index); + add32(Imm32(1), repeatCount); + skipIncrement.link(this); + + // check if we're at the end of backref (if we are, success!) + Jump endOfBackRef = je32(Address(output, ((2 * subpatternId) + 1) * sizeof(int)), repeatCount); + + load16(BaseIndex(input, repeatCount, MacroAssembler::TimesTwo), character); + + // check if we've run out of input (this would be a can o'fail) + Jump endOfInput = je32(length, index); + + je16(character, BaseIndex(input, index, TimesTwo), topOfLoop); + + endOfInput.link(this); + + // Failure + pop(repeatCount); + pop(index); + failures.append(jump()); + + // Success + endOfBackRef.link(this); + pop(repeatCount); + pop(); +} + +void Generator::terminateAlternative(JumpList& successes, JumpList& failures) +{ + successes.append(jump()); + + failures.link(this); + peek(index); +} + +void Generator::terminateDisjunction(JumpList& successes) +{ + successes.link(this); +} + +} } // namespace JSC::WREC + +#endif // ENABLE(WREC) diff --git a/JavaScriptCore/wrec/WRECGenerator.h b/JavaScriptCore/wrec/WRECGenerator.h new file mode 100644 index 0000000..af4101a --- /dev/null +++ b/JavaScriptCore/wrec/WRECGenerator.h @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2008 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef WRECGenerator_h +#define WRECGenerator_h + +#include <wtf/Platform.h> + +#if ENABLE(WREC) + +#include "Quantifier.h" +#include "MacroAssembler.h" +#include <wtf/ASCIICType.h> +#include <wtf/unicode/Unicode.h> +#include "WREC.h" + +namespace JSC { + + class JSGlobalData; + + namespace WREC { + + class CharacterRange; + class GenerateAtomFunctor; + class Parser; + struct CharacterClass; + + class Generator : private MacroAssembler { + public: + using MacroAssembler::Jump; + using MacroAssembler::JumpList; + using MacroAssembler::Label; + + enum ParenthesesType { Capturing, NonCapturing, Assertion, InvertedAssertion, Error }; + + static CompiledRegExp compileRegExp(JSGlobalData*, const UString& pattern, unsigned* numSubpatterns_ptr, const char** error_ptr, RefPtr<ExecutablePool>& pool, bool ignoreCase = false, bool multiline = false); + + Generator(Parser& parser) + : m_parser(parser) + { + } + + static const RegisterID input = X86::eax; + static const RegisterID length = X86::ecx; + static const RegisterID index = X86::edx; + static const RegisterID character = X86::esi; + static const RegisterID output = X86::edi; + static const RegisterID repeatCount = X86::ebx; // How many times the current atom repeats in the current match. + + void generateEnter(); + void generateSaveIndex(); + void generateIncrementIndex(Jump* failure = 0); + void generateLoadCharacter(JumpList& failures); + void generateJumpIfNotEndOfInput(Label); + void generateReturnSuccess(); + void generateReturnFailure(); + + void generateGreedyQuantifier(JumpList& failures, GenerateAtomFunctor& functor, unsigned min, unsigned max); + void generateNonGreedyQuantifier(JumpList& failures, GenerateAtomFunctor& functor, unsigned min, unsigned max); + void generateBacktrack1(); + void generateBacktrackBackreference(unsigned subpatternId); + void generateCharacterClass(JumpList& failures, const CharacterClass& charClass, bool invert); + void generateCharacterClassInverted(JumpList& failures, const CharacterClass& charClass); + void generateCharacterClassInvertedRange(JumpList& failures, JumpList& matchDest, const CharacterRange* ranges, unsigned count, unsigned* matchIndex, const UChar* matches, unsigned matchCount); + void generatePatternCharacter(JumpList& failures, int ch); + void generatePatternCharacterSequence(JumpList& failures, int* sequence, size_t count); + void generateAssertionWordBoundary(JumpList& failures, bool invert); + void generateAssertionBOL(JumpList& failures); + void generateAssertionEOL(JumpList& failures); + void generateBackreference(JumpList& failures, unsigned subpatternID); + void generateBackreferenceQuantifier(JumpList& failures, Quantifier::Type quantifierType, unsigned subpatternId, unsigned min, unsigned max); + void generateParenthesesAssertion(JumpList& failures); + void generateParenthesesInvertedAssertion(JumpList& failures); + Jump generateParenthesesResetTrampoline(JumpList& newFailures, unsigned subpatternIdBefore, unsigned subpatternIdAfter); + void generateParenthesesNonGreedy(JumpList& failures, Label start, Jump success, Jump fail); + + void terminateAlternative(JumpList& successes, JumpList& failures); + void terminateDisjunction(JumpList& successes); + + private: + bool generatePatternCharacterPair(JumpList& failures, int ch1, int ch2); + + Parser& m_parser; + }; + +} } // namespace JSC::WREC + +#endif // ENABLE(WREC) + +#endif // WRECGenerator_h diff --git a/JavaScriptCore/wrec/WRECParser.cpp b/JavaScriptCore/wrec/WRECParser.cpp new file mode 100644 index 0000000..1709bf9 --- /dev/null +++ b/JavaScriptCore/wrec/WRECParser.cpp @@ -0,0 +1,643 @@ +/* + * Copyright (C) 2008 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "WRECParser.h" + +#if ENABLE(WREC) + +#include "CharacterClassConstructor.h" +#include "WRECFunctors.h" + +using namespace WTF; + +namespace JSC { namespace WREC { + +// These error messages match the error messages used by PCRE. +const char* Parser::QuantifierOutOfOrder = "numbers out of order in {} quantifier"; +const char* Parser::QuantifierWithoutAtom = "nothing to repeat"; +const char* Parser::ParenthesesUnmatched = "unmatched parentheses"; +const char* Parser::ParenthesesTypeInvalid = "unrecognized character after (?"; +const char* Parser::ParenthesesNotSupported = ""; // Not a user-visible syntax error -- just signals a syntax that WREC doesn't support yet. +const char* Parser::CharacterClassUnmatched = "missing terminating ] for character class"; +const char* Parser::CharacterClassOutOfOrder = "range out of order in character class"; +const char* Parser::EscapeUnterminated = "\\ at end of pattern"; + +class PatternCharacterSequence { +typedef Generator::JumpList JumpList; + +public: + PatternCharacterSequence(Generator& generator, JumpList& failures) + : m_generator(generator) + , m_failures(failures) + { + } + + size_t size() { return m_sequence.size(); } + + void append(int ch) + { + m_sequence.append(ch); + } + + void flush() + { + if (!m_sequence.size()) + return; + + m_generator.generatePatternCharacterSequence(m_failures, m_sequence.begin(), m_sequence.size()); + m_sequence.clear(); + } + + void flush(const Quantifier& quantifier) + { + if (!m_sequence.size()) + return; + + m_generator.generatePatternCharacterSequence(m_failures, m_sequence.begin(), m_sequence.size() - 1); + + switch (quantifier.type) { + case Quantifier::None: + case Quantifier::Error: + ASSERT_NOT_REACHED(); + break; + + case Quantifier::Greedy: { + GeneratePatternCharacterFunctor functor(m_sequence.last()); + m_generator.generateGreedyQuantifier(m_failures, functor, quantifier.min, quantifier.max); + break; + } + + case Quantifier::NonGreedy: { + GeneratePatternCharacterFunctor functor(m_sequence.last()); + m_generator.generateNonGreedyQuantifier(m_failures, functor, quantifier.min, quantifier.max); + break; + } + } + + m_sequence.clear(); + } + +private: + Generator& m_generator; + JumpList& m_failures; + Vector<int, 8> m_sequence; +}; + +ALWAYS_INLINE Quantifier Parser::consumeGreedyQuantifier() +{ + switch (peek()) { + case '?': + consume(); + return Quantifier(Quantifier::Greedy, 0, 1); + + case '*': + consume(); + return Quantifier(Quantifier::Greedy, 0); + + case '+': + consume(); + return Quantifier(Quantifier::Greedy, 1); + + case '{': { + SavedState state(*this); + consume(); + + // Accept: {n}, {n,}, {n,m}. + // Reject: {n,m} where n > m. + // Ignore: Anything else, such as {n, m}. + + if (!peekIsDigit()) { + state.restore(); + return Quantifier(); + } + + unsigned min = consumeNumber(); + unsigned max = min; + + if (peek() == ',') { + consume(); + max = peekIsDigit() ? consumeNumber() : Quantifier::Infinity; + } + + if (peek() != '}') { + state.restore(); + return Quantifier(); + } + consume(); + + if (min > max) { + setError(QuantifierOutOfOrder); + return Quantifier(Quantifier::Error); + } + + return Quantifier(Quantifier::Greedy, min, max); + } + + default: + return Quantifier(); // No quantifier. + } +} + +Quantifier Parser::consumeQuantifier() +{ + Quantifier q = consumeGreedyQuantifier(); + + if ((q.type == Quantifier::Greedy) && (peek() == '?')) { + consume(); + q.type = Quantifier::NonGreedy; + } + + return q; +} + +bool Parser::parseCharacterClassQuantifier(JumpList& failures, const CharacterClass& charClass, bool invert) +{ + Quantifier q = consumeQuantifier(); + + switch (q.type) { + case Quantifier::None: { + m_generator.generateCharacterClass(failures, charClass, invert); + break; + } + + case Quantifier::Greedy: { + GenerateCharacterClassFunctor functor(&charClass, invert); + m_generator.generateGreedyQuantifier(failures, functor, q.min, q.max); + break; + } + + case Quantifier::NonGreedy: { + GenerateCharacterClassFunctor functor(&charClass, invert); + m_generator.generateNonGreedyQuantifier(failures, functor, q.min, q.max); + break; + } + + case Quantifier::Error: + return false; + } + + return true; +} + +bool Parser::parseBackreferenceQuantifier(JumpList& failures, unsigned subpatternId) +{ + Quantifier q = consumeQuantifier(); + + switch (q.type) { + case Quantifier::None: { + m_generator.generateBackreference(failures, subpatternId); + break; + } + + case Quantifier::Greedy: + case Quantifier::NonGreedy: + m_generator.generateBackreferenceQuantifier(failures, q.type, subpatternId, q.min, q.max); + return true; + + case Quantifier::Error: + return false; + } + + return true; +} + +bool Parser::parseParentheses(JumpList& failures) +{ + ParenthesesType type = consumeParenthesesType(); + + // FIXME: WREC originally failed to backtrack correctly in cases such as + // "c".match(/(.*)c/). Now, most parentheses handling is disabled. For + // unsupported parentheses, we fall back on PCRE. + + switch (type) { + case Generator::Assertion: { + m_generator.generateParenthesesAssertion(failures); + + if (consume() != ')') { + setError(ParenthesesUnmatched); + return false; + } + + Quantifier quantifier = consumeQuantifier(); + if (quantifier.type != Quantifier::None && quantifier.min == 0) { + setError(ParenthesesNotSupported); + return false; + } + + return true; + } + case Generator::InvertedAssertion: { + m_generator.generateParenthesesInvertedAssertion(failures); + + if (consume() != ')') { + setError(ParenthesesUnmatched); + return false; + } + + Quantifier quantifier = consumeQuantifier(); + if (quantifier.type != Quantifier::None && quantifier.min == 0) { + setError(ParenthesesNotSupported); + return false; + } + + return true; + } + default: + setError(ParenthesesNotSupported); + return false; + } +} + +bool Parser::parseCharacterClass(JumpList& failures) +{ + bool invert = false; + if (peek() == '^') { + consume(); + invert = true; + } + + CharacterClassConstructor constructor(m_ignoreCase); + + int ch; + while ((ch = peek()) != ']') { + switch (ch) { + case EndOfPattern: + setError(CharacterClassUnmatched); + return false; + + case '\\': { + consume(); + Escape escape = consumeEscape(true); + + switch (escape.type()) { + case Escape::PatternCharacter: { + int character = PatternCharacterEscape::cast(escape).character(); + if (character == '-') + constructor.flushBeforeEscapedHyphen(); + constructor.put(character); + break; + } + case Escape::CharacterClass: { + const CharacterClassEscape& characterClassEscape = CharacterClassEscape::cast(escape); + ASSERT(!characterClassEscape.invert()); + constructor.append(characterClassEscape.characterClass()); + break; + } + case Escape::Error: + return false; + case Escape::Backreference: + case Escape::WordBoundaryAssertion: { + ASSERT_NOT_REACHED(); + break; + } + } + break; + } + + default: + consume(); + constructor.put(ch); + } + } + consume(); + + // lazily catch reversed ranges ([z-a])in character classes + if (constructor.isUpsideDown()) { + setError(CharacterClassOutOfOrder); + return false; + } + + constructor.flush(); + CharacterClass charClass = constructor.charClass(); + return parseCharacterClassQuantifier(failures, charClass, invert); +} + +bool Parser::parseNonCharacterEscape(JumpList& failures, const Escape& escape) +{ + switch (escape.type()) { + case Escape::PatternCharacter: + ASSERT_NOT_REACHED(); + return false; + + case Escape::CharacterClass: + return parseCharacterClassQuantifier(failures, CharacterClassEscape::cast(escape).characterClass(), CharacterClassEscape::cast(escape).invert()); + + case Escape::Backreference: + return parseBackreferenceQuantifier(failures, BackreferenceEscape::cast(escape).subpatternId()); + + case Escape::WordBoundaryAssertion: + m_generator.generateAssertionWordBoundary(failures, WordBoundaryAssertionEscape::cast(escape).invert()); + return true; + + case Escape::Error: + return false; + } + + ASSERT_NOT_REACHED(); + return false; +} + +Escape Parser::consumeEscape(bool inCharacterClass) +{ + switch (peek()) { + case EndOfPattern: + setError(EscapeUnterminated); + return Escape(Escape::Error); + + // Assertions + case 'b': + consume(); + if (inCharacterClass) + return PatternCharacterEscape('\b'); + return WordBoundaryAssertionEscape(false); // do not invert + case 'B': + consume(); + if (inCharacterClass) + return PatternCharacterEscape('B'); + return WordBoundaryAssertionEscape(true); // invert + + // CharacterClassEscape + case 'd': + consume(); + return CharacterClassEscape(CharacterClass::digits(), false); + case 's': + consume(); + return CharacterClassEscape(CharacterClass::spaces(), false); + case 'w': + consume(); + return CharacterClassEscape(CharacterClass::wordchar(), false); + case 'D': + consume(); + return inCharacterClass + ? CharacterClassEscape(CharacterClass::nondigits(), false) + : CharacterClassEscape(CharacterClass::digits(), true); + case 'S': + consume(); + return inCharacterClass + ? CharacterClassEscape(CharacterClass::nonspaces(), false) + : CharacterClassEscape(CharacterClass::spaces(), true); + case 'W': + consume(); + return inCharacterClass + ? CharacterClassEscape(CharacterClass::nonwordchar(), false) + : CharacterClassEscape(CharacterClass::wordchar(), true); + + // DecimalEscape + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': { + if (peekDigit() > m_numSubpatterns || inCharacterClass) { + // To match Firefox, we parse an invalid backreference in the range [1-7] + // as an octal escape. + return peekDigit() > 7 ? PatternCharacterEscape('\\') : PatternCharacterEscape(consumeOctal()); + } + + int value = 0; + do { + unsigned newValue = value * 10 + peekDigit(); + if (newValue > m_numSubpatterns) + break; + value = newValue; + consume(); + } while (peekIsDigit()); + + return BackreferenceEscape(value); + } + + // Octal escape + case '0': + consume(); + return PatternCharacterEscape(consumeOctal()); + + // ControlEscape + case 'f': + consume(); + return PatternCharacterEscape('\f'); + case 'n': + consume(); + return PatternCharacterEscape('\n'); + case 'r': + consume(); + return PatternCharacterEscape('\r'); + case 't': + consume(); + return PatternCharacterEscape('\t'); + case 'v': + consume(); + return PatternCharacterEscape('\v'); + + // ControlLetter + case 'c': { + SavedState state(*this); + consume(); + + int control = consume(); + // To match Firefox, inside a character class, we also accept numbers + // and '_' as control characters. + if ((!inCharacterClass && !isASCIIAlpha(control)) || (!isASCIIAlphanumeric(control) && control != '_')) { + state.restore(); + return PatternCharacterEscape('\\'); + } + return PatternCharacterEscape(control & 31); + } + + // HexEscape + case 'x': { + consume(); + + SavedState state(*this); + int x = consumeHex(2); + if (x == -1) { + state.restore(); + return PatternCharacterEscape('x'); + } + return PatternCharacterEscape(x); + } + + // UnicodeEscape + case 'u': { + consume(); + + SavedState state(*this); + int x = consumeHex(4); + if (x == -1) { + state.restore(); + return PatternCharacterEscape('u'); + } + return PatternCharacterEscape(x); + } + + // IdentityEscape + default: + return PatternCharacterEscape(consume()); + } +} + +void Parser::parseAlternative(JumpList& failures) +{ + PatternCharacterSequence sequence(m_generator, failures); + + while (1) { + switch (peek()) { + case EndOfPattern: + case '|': + case ')': + sequence.flush(); + return; + + case '*': + case '+': + case '?': + case '{': { + Quantifier q = consumeQuantifier(); + + if (q.type == Quantifier::None) { + sequence.append(consume()); + continue; + } + + if (q.type == Quantifier::Error) + return; + + if (!sequence.size()) { + setError(QuantifierWithoutAtom); + return; + } + + sequence.flush(q); + continue; + } + + case '^': + consume(); + + sequence.flush(); + m_generator.generateAssertionBOL(failures); + continue; + + case '$': + consume(); + + sequence.flush(); + m_generator.generateAssertionEOL(failures); + continue; + + case '.': + consume(); + + sequence.flush(); + if (!parseCharacterClassQuantifier(failures, CharacterClass::newline(), true)) + return; + continue; + + case '[': + consume(); + + sequence.flush(); + if (!parseCharacterClass(failures)) + return; + continue; + + case '(': + consume(); + + sequence.flush(); + if (!parseParentheses(failures)) + return; + continue; + + case '\\': { + consume(); + + Escape escape = consumeEscape(false); + if (escape.type() == Escape::PatternCharacter) { + sequence.append(PatternCharacterEscape::cast(escape).character()); + continue; + } + + sequence.flush(); + if (!parseNonCharacterEscape(failures, escape)) + return; + continue; + } + + default: + sequence.append(consume()); + continue; + } + } +} + +/* + TOS holds index. +*/ +void Parser::parseDisjunction(JumpList& failures) +{ + parseAlternative(failures); + if (peek() != '|') + return; + + JumpList successes; + do { + consume(); + m_generator.terminateAlternative(successes, failures); + parseAlternative(failures); + } while (peek() == '|'); + + m_generator.terminateDisjunction(successes); +} + +Generator::ParenthesesType Parser::consumeParenthesesType() +{ + if (peek() != '?') + return Generator::Capturing; + consume(); + + switch (consume()) { + case ':': + return Generator::NonCapturing; + + case '=': + return Generator::Assertion; + + case '!': + return Generator::InvertedAssertion; + + default: + setError(ParenthesesTypeInvalid); + return Generator::Error; + } +} + +} } // namespace JSC::WREC + +#endif // ENABLE(WREC) diff --git a/JavaScriptCore/wrec/WRECParser.h b/JavaScriptCore/wrec/WRECParser.h new file mode 100644 index 0000000..a3e151b --- /dev/null +++ b/JavaScriptCore/wrec/WRECParser.h @@ -0,0 +1,214 @@ +/* + * Copyright (C) 2008 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef Parser_h +#define Parser_h + +#include <wtf/Platform.h> + +#if ENABLE(WREC) + +#include "Escapes.h" +#include "Quantifier.h" +#include "UString.h" +#include "WRECGenerator.h" +#include <wtf/ASCIICType.h> + +namespace JSC { namespace WREC { + + struct CharacterClass; + + class Parser { + typedef Generator::JumpList JumpList; + typedef Generator::ParenthesesType ParenthesesType; + + friend class SavedState; + + public: + Parser(const UString& pattern, bool ignoreCase, bool multiline) + : m_generator(*this) + , m_data(pattern.data()) + , m_size(pattern.size()) + , m_ignoreCase(ignoreCase) + , m_multiline(multiline) + { + reset(); + } + + Generator& generator() { return m_generator; } + + bool ignoreCase() const { return m_ignoreCase; } + bool multiline() const { return m_multiline; } + + void recordSubpattern() { ++m_numSubpatterns; } + unsigned numSubpatterns() const { return m_numSubpatterns; } + + const char* error() const { return m_error; } + const char* syntaxError() const { return m_error == ParenthesesNotSupported ? 0 : m_error; } + + void parsePattern(JumpList& failures) + { + reset(); + + parseDisjunction(failures); + + if (peek() != EndOfPattern) + setError(ParenthesesUnmatched); // Parsing the pattern should fully consume it. + } + + void parseDisjunction(JumpList& failures); + void parseAlternative(JumpList& failures); + bool parseTerm(JumpList& failures); + bool parseNonCharacterEscape(JumpList& failures, const Escape&); + bool parseParentheses(JumpList& failures); + bool parseCharacterClass(JumpList& failures); + bool parseCharacterClassQuantifier(JumpList& failures, const CharacterClass& charClass, bool invert); + bool parseBackreferenceQuantifier(JumpList& failures, unsigned subpatternId); + + private: + class SavedState { + public: + SavedState(Parser& parser) + : m_parser(parser) + , m_index(parser.m_index) + { + } + + void restore() + { + m_parser.m_index = m_index; + } + + private: + Parser& m_parser; + unsigned m_index; + }; + + void reset() + { + m_index = 0; + m_numSubpatterns = 0; + m_error = 0; + } + + void setError(const char* error) + { + if (m_error) + return; + m_error = error; + } + + int peek() + { + if (m_index >= m_size) + return EndOfPattern; + return m_data[m_index]; + } + + int consume() + { + if (m_index >= m_size) + return EndOfPattern; + return m_data[m_index++]; + } + + bool peekIsDigit() + { + return WTF::isASCIIDigit(peek()); + } + + unsigned peekDigit() + { + ASSERT(peekIsDigit()); + return peek() - '0'; + } + + unsigned consumeDigit() + { + ASSERT(peekIsDigit()); + return consume() - '0'; + } + + unsigned consumeNumber() + { + int n = consumeDigit(); + while (peekIsDigit()) { + n *= 10; + n += consumeDigit(); + } + return n; + } + + int consumeHex(int count) + { + int n = 0; + while (count--) { + if (!WTF::isASCIIHexDigit(peek())) + return -1; + n = (n << 4) | WTF::toASCIIHexValue(consume()); + } + return n; + } + + unsigned consumeOctal() + { + unsigned n = 0; + while (n < 32 && WTF::isASCIIOctalDigit(peek())) + n = n * 8 + consumeDigit(); + return n; + } + + ALWAYS_INLINE Quantifier consumeGreedyQuantifier(); + Quantifier consumeQuantifier(); + Escape consumeEscape(bool inCharacterClass); + ParenthesesType consumeParenthesesType(); + + static const int EndOfPattern = -1; + + // Error messages. + static const char* QuantifierOutOfOrder; + static const char* QuantifierWithoutAtom; + static const char* ParenthesesUnmatched; + static const char* ParenthesesTypeInvalid; + static const char* ParenthesesNotSupported; + static const char* CharacterClassUnmatched; + static const char* CharacterClassOutOfOrder; + static const char* EscapeUnterminated; + + Generator m_generator; + const UChar* m_data; + unsigned m_size; + unsigned m_index; + bool m_ignoreCase; + bool m_multiline; + unsigned m_numSubpatterns; + const char* m_error; + }; + +} } // namespace JSC::WREC + +#endif // ENABLE(WREC) + +#endif // Parser_h diff --git a/JavaScriptCore/wtf/ASCIICType.h b/JavaScriptCore/wtf/ASCIICType.h index b1ee3dc..0c2ca70 100644 --- a/JavaScriptCore/wtf/ASCIICType.h +++ b/JavaScriptCore/wtf/ASCIICType.h @@ -44,6 +44,13 @@ namespace WTF { + inline bool isASCII(char c) { return !(c & ~0x7F); } + inline bool isASCII(unsigned short c) { return !(c & ~0x7F); } +#if !COMPILER(MSVC) || defined(_NATIVE_WCHAR_T_DEFINED) + inline bool isASCII(wchar_t c) { return !(c & ~0x7F); } +#endif + inline bool isASCII(int c) { return !(c & ~0x7F); } + inline bool isASCIIAlpha(char c) { return (c | 0x20) >= 'a' && (c | 0x20) <= 'z'; } inline bool isASCIIAlpha(unsigned short c) { return (c | 0x20) >= 'a' && (c | 0x20) <= 'z'; } #if !COMPILER(MSVC) || defined(_NATIVE_WCHAR_T_DEFINED) diff --git a/JavaScriptCore/wtf/AVLTree.h b/JavaScriptCore/wtf/AVLTree.h index cd1511f..18db8ff 100644 --- a/JavaScriptCore/wtf/AVLTree.h +++ b/JavaScriptCore/wtf/AVLTree.h @@ -29,12 +29,12 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef KJS_AVL_TREE_H_ -#define KJS_AVL_TREE_H_ +#ifndef AVL_TREE_H_ +#define AVL_TREE_H_ #include "Assertions.h" -namespace JSC { +namespace WTF { // Here is the reference class for BSet. // @@ -203,17 +203,19 @@ public: break; } cmp = -target_cmp; - } else if (target_cmp != 0) - if (!((cmp ^ target_cmp) & MASK_HIGH_BIT)) + } 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; + } } + 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) { @@ -822,7 +824,7 @@ AVLTree<Abstractor, maxDepth, BSet>::remove(key k) cmp_shortened_sub_with_path = cmp; // Get the handle of the opposite child, which may not be null. - child = cmp > 0 ? get_lt(h, false) : get_gt(h, false); + child = cmp > 0 ? get_lt(h) : get_gt(h); } if (parent == null()) @@ -841,8 +843,8 @@ AVLTree<Abstractor, maxDepth, BSet>::remove(key k) if (h != rm) { // Poke in the replacement for the node to be removed. - set_lt(h, get_lt(rm, false)); - set_gt(h, get_gt(rm, false)); + 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; @@ -934,8 +936,8 @@ AVLTree<Abstractor, maxDepth, BSet>::subst(handle new_node) } /* Copy tree housekeeping fields from node in tree to new node. */ - set_lt(new_node, get_lt(h, false)); - set_gt(new_node, get_gt(h, false)); + set_lt(new_node, get_lt(h)); + set_gt(new_node, get_gt(h)); set_bf(new_node, get_bf(h)); if (parent == null()) @@ -952,7 +954,6 @@ AVLTree<Abstractor, maxDepth, BSet>::subst(handle new_node) return h; } - } #endif diff --git a/JavaScriptCore/wtf/AlwaysInline.h b/JavaScriptCore/wtf/AlwaysInline.h index d39b2b9..64fdd99 100644 --- a/JavaScriptCore/wtf/AlwaysInline.h +++ b/JavaScriptCore/wtf/AlwaysInline.h @@ -22,7 +22,7 @@ #ifndef ALWAYS_INLINE #if COMPILER(GCC) && defined(NDEBUG) && !COMPILER(MINGW) -#define ALWAYS_INLINE inline __attribute__ ((__always_inline__)) +#define ALWAYS_INLINE inline __attribute__((__always_inline__)) #elif COMPILER(MSVC) && defined(NDEBUG) #define ALWAYS_INLINE __forceinline #else @@ -32,7 +32,7 @@ #ifndef NEVER_INLINE #if COMPILER(GCC) -#define NEVER_INLINE __attribute__ ((__noinline__)) +#define NEVER_INLINE __attribute__((__noinline__)) #else #define NEVER_INLINE #endif @@ -53,3 +53,11 @@ #define LIKELY(x) (x) #endif #endif + +#ifndef NO_RETURN +#if COMPILER(GCC) +#define NO_RETURN __attribute((__noreturn__)) +#else +#define NO_RETURN +#endif +#endif diff --git a/JavaScriptCore/wtf/Assertions.cpp b/JavaScriptCore/wtf/Assertions.cpp index 98de91c..6e04fe1 100644 --- a/JavaScriptCore/wtf/Assertions.cpp +++ b/JavaScriptCore/wtf/Assertions.cpp @@ -34,7 +34,7 @@ #include <CoreFoundation/CFString.h> #endif -#if COMPILER(MSVC) +#if COMPILER(MSVC) && !PLATFORM(WIN_CE) #ifndef WINVER #define WINVER 0x0500 #endif @@ -66,7 +66,7 @@ static void vprintf_stderr_common(const char* format, va_list args) CFRelease(str); CFRelease(cfFormat); } else -#elif COMPILER(MSVC) +#elif COMPILER(MSVC) && !PLATFORM(WIN_CE) if (IsDebuggerPresent()) { size_t size = 1024; diff --git a/JavaScriptCore/wtf/Assertions.h b/JavaScriptCore/wtf/Assertions.h index 8449563..c17e501 100644 --- a/JavaScriptCore/wtf/Assertions.h +++ b/JavaScriptCore/wtf/Assertions.h @@ -120,11 +120,22 @@ void WTFLogVerbose(const char* file, int line, const char* function, WTFLogChann /* CRASH -- gets us into the debugger or the crash reporter -- signals are ignored by the crash reporter so we must do better */ #ifndef CRASH -#define CRASH() *(int *)(uintptr_t)0xbbadbeef = 0 +#define CRASH() do { \ + *(int *)(uintptr_t)0xbbadbeef = 0; \ + ((void(*)())0)(); /* More reliable, but doesn't say BBADBEEF */ \ +} while(false) #endif /* ASSERT, ASSERT_WITH_MESSAGE, ASSERT_NOT_REACHED */ +#if PLATFORM(WIN_CE) +/* 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 PLATFORM(WIN_OS) /* FIXME: Change to use something other than ASSERT to avoid this conflict with win32. */ #undef ASSERT @@ -135,6 +146,7 @@ void WTFLogVerbose(const char* file, int line, const char* function, WTFLogChann #define ASSERT(assertion) ((void)0) #define ASSERT_WITH_MESSAGE(assertion, ...) ((void)0) #define ASSERT_NOT_REACHED() ((void)0) +#define ASSERT_UNUSED(variable, assertion) ((void)variable) #else @@ -159,6 +171,8 @@ while (0) CRASH(); \ } while (0) +#define ASSERT_UNUSED(variable, assertion) ASSERT(assertion) + #endif /* ASSERT_ARG */ diff --git a/JavaScriptCore/wtf/ByteArray.cpp b/JavaScriptCore/wtf/ByteArray.cpp new file mode 100644 index 0000000..526f147 --- /dev/null +++ b/JavaScriptCore/wtf/ByteArray.cpp @@ -0,0 +1,38 @@ +/* + * 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 "ByteArray.h" + +namespace WTF { + +PassRefPtr<ByteArray> ByteArray::create(size_t size) +{ + unsigned char* buffer = new unsigned char[size + sizeof(ByteArray) - sizeof(size_t)]; + ASSERT((reinterpret_cast<size_t>(buffer) & 3) == 0); + return adoptRef(new (buffer) ByteArray(size)); +} + +} diff --git a/JavaScriptCore/wtf/ByteArray.h b/JavaScriptCore/wtf/ByteArray.h new file mode 100644 index 0000000..865c30e --- /dev/null +++ b/JavaScriptCore/wtf/ByteArray.h @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2009 Apple Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ByteArray_h +#define ByteArray_h + +#include "wtf/PassRefPtr.h" +#include "wtf/RefCounted.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); + } + + bool get(unsigned index, unsigned char& result) const + { + if (index >= m_size) + return false; + result = m_data[index]; + return true; + } + + unsigned char* data() { return m_data; } + + 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); + } + } + + static PassRefPtr<ByteArray> create(size_t size); + + private: + ByteArray(size_t size) + : RefCountedBase(1) + , m_size(size) + { + } + size_t m_size; + unsigned char m_data[sizeof(size_t)]; + }; +} + +#endif diff --git a/JavaScriptCore/wtf/CONTRIBUTORS.pthreads-win32 b/JavaScriptCore/wtf/CONTRIBUTORS.pthreads-win32 new file mode 100644 index 0000000..7de0f26 --- /dev/null +++ b/JavaScriptCore/wtf/CONTRIBUTORS.pthreads-win32 @@ -0,0 +1,137 @@ +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/JavaScriptCore/wtf/CurrentTime.cpp b/JavaScriptCore/wtf/CurrentTime.cpp new file mode 100644 index 0000000..d9ea448 --- /dev/null +++ b/JavaScriptCore/wtf/CurrentTime.cpp @@ -0,0 +1,246 @@ +/* + * 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. + */ + +#include "config.h" +#include "CurrentTime.h" + +#if PLATFORM(MAC) +#include <CoreFoundation/CFDate.h> +#elif PLATFORM(GTK) +#include <glib.h> +#elif PLATFORM(WX) +#include <wx/datetime.h> +#elif PLATFORM(WIN_OS) +// If defined, WIN32_LEAN_AND_MEAN disables timeBeginPeriod/timeEndPeriod. +#undef WIN32_LEAN_AND_MEAN +#include <windows.h> +#include <math.h> +#include <stdint.h> +#include <sys/timeb.h> +#include <sys/types.h> +#include <time.h> +#else // Posix systems relying on the gettimeofday() +#include <sys/time.h> +#endif + +namespace WTF { + +const double msPerSecond = 1000.0; + +#if PLATFORM(MAC) + +double currentTime() +{ + return CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970; +} + +#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(WIN_OS) + +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 PLATFORM(WIN_CE) + 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 // PLATFORM(WIN_CE) + struct _timeb timebuffer; + _ftime(&timebuffer); + return timebuffer.time * msPerSecond + timebuffer.millitm; +#endif // PLATFORM(WIN_CE) +} + +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 bool started; + 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 // Other Posix systems rely on the gettimeofday(). + +double currentTime() +{ + struct timeval now; + struct timezone zone; + + gettimeofday(&now, &zone); + return static_cast<double>(now.tv_sec) + (double)(now.tv_usec / 1000000.0); +} + +#endif + +#if PLATFORM(ANDROID) + +uint32_t get_thread_msec() +{ +#if defined(HAVE_POSIX_CLOCKS) + struct timespec tm; + + clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tm); + return tm.tv_sec * 1000LL + tm.tv_nsec / 1000000; +#else + struct timeval now; + struct timezone zone; + + gettimeofday(&now, &zone); + return now.tv_sec * 1000LL + now.tv_usec / 1000; +#endif +} + +#endif + +} // namespace WTF diff --git a/JavaScriptCore/wtf/CurrentTime.h b/JavaScriptCore/wtf/CurrentTime.h new file mode 100644 index 0000000..f70f98f --- /dev/null +++ b/JavaScriptCore/wtf/CurrentTime.h @@ -0,0 +1,51 @@ +/* + * 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 + +namespace WTF { + + // Returns the current system (UTC) time in seconds, starting January 1, 1970. + // Precision varies depending on a platform but usually is as good or better + // then a millisecond. + double currentTime(); + +#if PLATFORM(ANDROID) + uint32_t get_thread_msec(); +#endif + +} // namespace WTF + +using WTF::currentTime; + +#endif // CurrentTime_h + diff --git a/JavaScriptCore/wtf/FastMalloc.cpp b/JavaScriptCore/wtf/FastMalloc.cpp index 8f7d5ef..88c10ca 100644 --- a/JavaScriptCore/wtf/FastMalloc.cpp +++ b/JavaScriptCore/wtf/FastMalloc.cpp @@ -191,7 +191,7 @@ void* fastMalloc(size_t n) ASSERT(!isForbidden()); void* result = malloc(n); if (!result) - abort(); + CRASH(); return result; } @@ -206,7 +206,7 @@ void* fastCalloc(size_t n_elements, size_t element_size) ASSERT(!isForbidden()); void* result = calloc(n_elements, element_size); if (!result) - abort(); + CRASH(); return result; } @@ -227,33 +227,17 @@ void* fastRealloc(void* p, size_t n) ASSERT(!isForbidden()); void* result = realloc(p, n); if (!result) - abort(); + CRASH(); return result; } void releaseFastMallocFreeMemory() { } - -#if HAVE(VIRTUALALLOC) -void* fastMallocExecutable(size_t n) -{ - return VirtualAlloc(0, n, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); -} - -void fastFreeExecutable(void* p) -{ - VirtualFree(p, 0, MEM_RELEASE); -} -#else -void* fastMallocExecutable(size_t n) + +FastMallocStatistics fastMallocStatistics() { - return fastMalloc(n); -} - -void fastFreeExecutable(void* p) -{ - fastFree(p); + FastMallocStatistics statistics = { 0, 0, 0, 0 }; + return statistics; } -#endif } // namespace WTF @@ -686,11 +670,11 @@ 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)); - abort(); + CRASH(); } if (static_cast<size_t>(ClassIndex(kMaxSize)) >= sizeof(class_array)) { MESSAGE("Invalid class index %d for kMaxSize\n", ClassIndex(kMaxSize)); - abort(); + CRASH(); } // Compute the size classes we want to use @@ -742,7 +726,7 @@ static void InitSizeClasses() { if (sc != kNumClasses) { MESSAGE("wrong number of size classes: found %" PRIuS " instead of %d\n", sc, int(kNumClasses)); - abort(); + CRASH(); } // Initialize the mapping arrays @@ -760,25 +744,25 @@ static void InitSizeClasses() { const size_t sc = SizeClass(size); if (sc == 0) { MESSAGE("Bad size class %" PRIuS " for %" PRIuS "\n", sc, size); - abort(); + CRASH(); } if (sc > 1 && size <= class_to_size[sc-1]) { MESSAGE("Allocating unnecessarily large class %" PRIuS " for %" PRIuS "\n", sc, size); - abort(); + CRASH(); } if (sc >= kNumClasses) { MESSAGE("Bad size class %" PRIuS " for %" PRIuS "\n", sc, size); - abort(); + CRASH(); } const size_t s = class_to_size[sc]; if (size > s) { MESSAGE("Bad size %" PRIuS " for %" PRIuS " (sc = %" PRIuS ")\n", s, size, sc); - abort(); + CRASH(); } if (s == 0) { MESSAGE("Bad size %" PRIuS " for %" PRIuS " (sc = %" PRIuS ")\n", s, size, sc); - abort(); + CRASH(); } } @@ -861,7 +845,7 @@ class PageHeapAllocator { if (free_avail_ < kAlignedSize) { // Need more room free_area_ = reinterpret_cast<char*>(MetaDataAlloc(kAllocIncrement)); - if (free_area_ == NULL) abort(); + if (free_area_ == NULL) CRASH(); free_avail_ = kAllocIncrement; } result = free_area_; @@ -995,7 +979,6 @@ static ALWAYS_INLINE bool DLL_IsEmpty(const Span* list) { return list->next == list; } -#ifndef WTF_CHANGES static int DLL_Length(const Span* list) { int result = 0; for (Span* s = list->next; s != list; s = s->next) { @@ -1003,7 +986,6 @@ static int DLL_Length(const Span* list) { } return result; } -#endif #if 0 /* Not needed at the moment -- causes compiler warnings if not used */ static void DLL_Print(const char* label, const Span* list) { @@ -1055,11 +1037,30 @@ template <int BITS> class MapSelector { typedef PackedCache<BITS, uint64_t> CacheType; }; +#if defined(WTF_CHANGES) +#if PLATFORM(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; + typedef TCMalloc_PageMap2<32 - kPageShift> Type; + typedef PackedCache<32 - kPageShift, uint16_t> CacheType; }; // ------------------------------------------------------------------------- @@ -1109,6 +1110,8 @@ class TCMalloc_PageHeap { pagemap_.Ensure(p, 1); return GetDescriptor(p); } + + size_t ReturnedBytes() const; #endif // Dump state to stderr @@ -1491,6 +1494,21 @@ void TCMalloc_PageHeap::RegisterSizeClass(Span* span, size_t sc) { 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) { @@ -3023,7 +3041,7 @@ static inline void* SpanToMallocResult(Span *span) { } #ifdef WTF_CHANGES -template <bool abortOnFailure> +template <bool crashOnFailure> #endif static ALWAYS_INLINE void* do_malloc(size_t size) { void* ret = NULL; @@ -3056,8 +3074,8 @@ static ALWAYS_INLINE void* do_malloc(size_t size) { } if (!ret) { #ifdef WTF_CHANGES - if (abortOnFailure) // This branch should be optimized out by the compiler. - abort(); + if (crashOnFailure) // This branch should be optimized out by the compiler. + CRASH(); #else errno = ENOMEM; #endif @@ -3226,9 +3244,9 @@ static inline struct mallinfo do_mallinfo() { #ifndef WTF_CHANGES extern "C" #else -#define do_malloc do_malloc<abortOnFailure> +#define do_malloc do_malloc<crashOnFailure> -template <bool abortOnFailure> +template <bool crashOnFailure> void* malloc(size_t); void* fastMalloc(size_t size) @@ -3241,7 +3259,7 @@ void* tryFastMalloc(size_t size) return malloc<false>(size); } -template <bool abortOnFailure> +template <bool crashOnFailure> ALWAYS_INLINE #endif void* malloc(size_t size) { @@ -3265,7 +3283,7 @@ void free(void* ptr) { #ifndef WTF_CHANGES extern "C" #else -template <bool abortOnFailure> +template <bool crashOnFailure> void* calloc(size_t, size_t); void* fastCalloc(size_t n, size_t elem_size) @@ -3278,7 +3296,7 @@ void* tryFastCalloc(size_t n, size_t elem_size) return calloc<false>(n, elem_size); } -template <bool abortOnFailure> +template <bool crashOnFailure> ALWAYS_INLINE #endif void* calloc(size_t n, size_t elem_size) { @@ -3298,6 +3316,8 @@ void* calloc(size_t n, size_t elem_size) { return result; } +// Since cfree isn't used anywhere, we don't compile it in. +#ifndef WTF_CHANGES #ifndef WTF_CHANGES extern "C" #endif @@ -3307,11 +3327,12 @@ void cfree(void* ptr) { #endif do_free(ptr); } +#endif #ifndef WTF_CHANGES extern "C" #else -template <bool abortOnFailure> +template <bool crashOnFailure> void* realloc(void*, size_t); void* fastRealloc(void* old_ptr, size_t new_size) @@ -3324,7 +3345,7 @@ void* tryFastRealloc(void* old_ptr, size_t new_size) return realloc<false>(old_ptr, new_size); } -template <bool abortOnFailure> +template <bool crashOnFailure> ALWAYS_INLINE #endif void* realloc(void* old_ptr, size_t new_size) { @@ -3385,16 +3406,6 @@ void* realloc(void* old_ptr, size_t new_size) { } } -void* fastMallocExecutable(size_t n) -{ - return malloc<false>(n); -} - -void fastFreeExecutable(void* p) -{ - free(p); -} - #ifdef WTF_CHANGES #undef do_malloc #else @@ -3821,13 +3832,41 @@ void FastMallocZone::init() #endif +#if WTF_CHANGES void releaseFastMallocFreeMemory() { + // Flush free pages in the current thread cache back to the page heap. + // Low watermark mechanism in Scavenge() prevents full return on the first pass. + // The second pass flushes everything. + if (TCMalloc_ThreadCache* threadCache = TCMalloc_ThreadCache::GetCacheIfPresent()) { + threadCache->Scavenge(); + threadCache->Scavenge(); + } + SpinLockHolder h(&pageheap_lock); pageheap->ReleaseFreePages(); } + +FastMallocStatistics fastMallocStatistics() +{ + FastMallocStatistics statistics; + { + SpinLockHolder lockHolder(&pageheap_lock); + statistics.heapSize = static_cast<size_t>(pageheap->SystemBytes()); + statistics.freeSizeInHeap = static_cast<size_t>(pageheap->FreeBytes()); + statistics.returnedSize = pageheap->ReturnedBytes(); + statistics.freeSizeInCaches = 0; + for (TCMalloc_ThreadCache* threadCache = thread_heaps; threadCache ; threadCache = threadCache->next_) + statistics.freeSizeInCaches += threadCache->Size(); + } + for (unsigned cl = 0; cl < kNumClasses; ++cl) { + const int length = central_cache[cl].length(); + const int tc_length = central_cache[cl].tc_length(); + statistics.freeSizeInCaches += ByteSizeForClass(cl) * (length + tc_length); + } + return statistics; +} -#if WTF_CHANGES } // namespace WTF #endif diff --git a/JavaScriptCore/wtf/FastMalloc.h b/JavaScriptCore/wtf/FastMalloc.h index fb2762c..f1264ac 100644 --- a/JavaScriptCore/wtf/FastMalloc.h +++ b/JavaScriptCore/wtf/FastMalloc.h @@ -27,7 +27,7 @@ namespace WTF { - // These functions call abort() if an allocation fails. + // These functions call CRASH() if an allocation fails. void* fastMalloc(size_t n); void* fastZeroedMalloc(size_t n); void* fastCalloc(size_t n_elements, size_t element_size); @@ -41,15 +41,20 @@ namespace WTF { void fastFree(void* p); - void* fastMallocExecutable(size_t n); - void fastFreeExecutable(void* p); - #ifndef NDEBUG void fastMallocForbid(); void fastMallocAllow(); #endif void releaseFastMallocFreeMemory(); + + struct FastMallocStatistics { + size_t heapSize; + size_t freeSizeInHeap; + size_t freeSizeInCaches; + size_t returnedSize; + }; + FastMallocStatistics fastMallocStatistics(); } // namespace WTF diff --git a/JavaScriptCore/wtf/HashCountedSet.h b/JavaScriptCore/wtf/HashCountedSet.h index 8095a2b..6fc0234 100644 --- a/JavaScriptCore/wtf/HashCountedSet.h +++ b/JavaScriptCore/wtf/HashCountedSet.h @@ -1,6 +1,5 @@ /* - * This file is part of the KDE libraries - * Copyright (C) 2005 Apple Computer, Inc. + * 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 diff --git a/JavaScriptCore/wtf/HashFunctions.h b/JavaScriptCore/wtf/HashFunctions.h index 2c66a2d..13afb72 100644 --- a/JavaScriptCore/wtf/HashFunctions.h +++ b/JavaScriptCore/wtf/HashFunctions.h @@ -173,6 +173,9 @@ namespace WTF { template<typename P> struct DefaultHash<RefPtr<P> > { typedef PtrHash<RefPtr<P> > Hash; }; template<typename T, typename U> struct DefaultHash<std::pair<T, U> > { typedef PairHash<T, U> Hash; }; + + // Golden ratio - arbitrary start value to avoid mapping all 0's to all 0's + static const unsigned stringHashingStartValue = 0x9e3779b9U; } // namespace WTF diff --git a/JavaScriptCore/wtf/HashTable.cpp b/JavaScriptCore/wtf/HashTable.cpp index f1f2a4f..71d3f86 100644 --- a/JavaScriptCore/wtf/HashTable.cpp +++ b/JavaScriptCore/wtf/HashTable.cpp @@ -34,9 +34,17 @@ int HashTableStats::numReinserts; static HashTableStats logger; +static Mutex& hashTableStatsMutex() +{ + AtomicallyInitializedStatic(Mutex&, mutex = *new Mutex); + return mutex; +} + HashTableStats::~HashTableStats() { - printf("\nkhtml::HashTable statistics\n\n"); + // Don't lock hashTableStatsMutex here because it can cause deadlocks at shutdown + // if any thread was killed while holding the mutex. + printf("\nWTF::HashTable statistics\n\n"); printf("%d accesses\n", numAccesses); printf("%d total collisions, average %.2f probes per access\n", numCollisions, 1.0 * (numAccesses + numCollisions) / numAccesses); printf("longest collision chain: %d\n", maxCollisions); @@ -49,6 +57,7 @@ HashTableStats::~HashTableStats() void HashTableStats::recordCollisionAtCount(int count) { + MutexLocker lock(hashTableStatsMutex()); if (count > maxCollisions) maxCollisions = count; numCollisions++; diff --git a/JavaScriptCore/wtf/HashTable.h b/JavaScriptCore/wtf/HashTable.h index 4c7790a..3b283f8 100644 --- a/JavaScriptCore/wtf/HashTable.h +++ b/JavaScriptCore/wtf/HashTable.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2005, 2006, 2007, 2008 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 @@ -24,6 +25,7 @@ #include "FastMalloc.h" #include "HashTraits.h" #include <wtf/Assertions.h> +#include <wtf/Threading.h> namespace WTF { @@ -42,13 +44,19 @@ namespace WTF { 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 numCollisions; - static int collisionGraph[4096]; - static int maxCollisions; 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); }; @@ -201,6 +209,8 @@ namespace WTF { #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; @@ -397,7 +407,9 @@ namespace WTF { #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 }; @@ -466,7 +478,7 @@ namespace WTF { return 0; #if DUMP_HASHTABLE_STATS - ++HashTableStats::numAccesses; + atomicIncrement(&HashTableStats::numAccesses); int probeCount = 0; #endif @@ -511,7 +523,7 @@ namespace WTF { int i = h & sizeMask; #if DUMP_HASHTABLE_STATS - ++HashTableStats::numAccesses; + atomicIncrement(&HashTableStats::numAccesses); int probeCount = 0; #endif @@ -563,7 +575,7 @@ namespace WTF { int i = h & sizeMask; #if DUMP_HASHTABLE_STATS - ++HashTableStats::numAccesses; + atomicIncrement(&HashTableStats::numAccesses); int probeCount = 0; #endif @@ -623,7 +635,7 @@ namespace WTF { int i = h & sizeMask; #if DUMP_HASHTABLE_STATS - ++HashTableStats::numAccesses; + atomicIncrement(&HashTableStats::numAccesses); int probeCount = 0; #endif @@ -738,7 +750,7 @@ namespace WTF { ASSERT(!lookupForWriting(Extractor::extract(entry)).second); ASSERT(!isDeletedBucket(*(lookupForWriting(Extractor::extract(entry)).first))); #if DUMP_HASHTABLE_STATS - ++HashTableStats::numReinserts; + atomicIncrement(&HashTableStats::numReinserts); #endif Mover<ValueType, Traits::needsDestruction>::move(entry, *lookupForWriting(Extractor::extract(entry)).first); @@ -801,7 +813,7 @@ namespace WTF { void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::remove(ValueType* pos) { #if DUMP_HASHTABLE_STATS - ++HashTableStats::numRemoves; + atomicIncrement(&HashTableStats::numRemoves); #endif deleteBucket(*pos); @@ -887,7 +899,7 @@ namespace WTF { #if DUMP_HASHTABLE_STATS if (oldTableSize != 0) - ++HashTableStats::numRehashes; + atomicIncrement(&HashTableStats::numRehashes); #endif m_tableSize = newTableSize; @@ -1016,6 +1028,7 @@ namespace WTF { 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; @@ -1037,6 +1050,7 @@ namespace WTF { 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; @@ -1058,6 +1072,7 @@ namespace WTF { 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; diff --git a/JavaScriptCore/wtf/ListHashSet.h b/JavaScriptCore/wtf/ListHashSet.h index 2f75c33..38cc998 100644 --- a/JavaScriptCore/wtf/ListHashSet.h +++ b/JavaScriptCore/wtf/ListHashSet.h @@ -60,6 +60,8 @@ namespace WTF { typedef ListHashSetNodeHashFunctions<ValueArg, HashArg> NodeHash; typedef HashTable<Node*, Node*, IdentityExtractor<Node*>, NodeHash, NodeTraits, NodeTraits> ImplType; + typedef HashTableIterator<Node*, Node*, IdentityExtractor<Node*>, NodeHash, NodeTraits, NodeTraits> ImplTypeIterator; + typedef HashTableConstIterator<Node*, Node*, IdentityExtractor<Node*>, NodeHash, NodeTraits, NodeTraits> ImplTypeConstIterator; typedef HashArg HashFunctions; @@ -441,7 +443,7 @@ namespace WTF { inline typename ListHashSet<T, U>::iterator ListHashSet<T, U>::find(const ValueType& value) { typedef ListHashSetTranslator<ValueType, HashFunctions> Translator; - typename ImplType::iterator it = m_impl.template find<ValueType, Translator>(value); + ImplTypeIterator it = m_impl.template find<ValueType, Translator>(value); if (it == m_impl.end()) return end(); return makeIterator(*it); @@ -451,7 +453,7 @@ namespace WTF { inline typename ListHashSet<T, U>::const_iterator ListHashSet<T, U>::find(const ValueType& value) const { typedef ListHashSetTranslator<ValueType, HashFunctions> Translator; - typename ImplType::const_iterator it = m_impl.template find<ValueType, Translator>(value); + ImplTypeConstIterator it = m_impl.template find<ValueType, Translator>(value); if (it == m_impl.end()) return end(); return makeConstIterator(*it); diff --git a/JavaScriptCore/wtf/MainThread.cpp b/JavaScriptCore/wtf/MainThread.cpp index 6fe3021..c7a6caa 100644 --- a/JavaScriptCore/wtf/MainThread.cpp +++ b/JavaScriptCore/wtf/MainThread.cpp @@ -29,6 +29,7 @@ #include "config.h" #include "MainThread.h" +#include "StdLibExtras.h" #include "Threading.h" #include "Vector.h" @@ -49,17 +50,17 @@ struct FunctionWithContext { typedef Vector<FunctionWithContext> FunctionQueue; -static bool callbacksPaused; // This global varialble is only accessed from main thread. +static bool callbacksPaused; // This global variable is only accessed from main thread. Mutex& mainThreadFunctionQueueMutex() { - static Mutex staticMutex; + DEFINE_STATIC_LOCAL(Mutex, staticMutex, ()); return staticMutex; } static FunctionQueue& functionQueue() { - static FunctionQueue staticFunctionQueue; + DEFINE_STATIC_LOCAL(FunctionQueue, staticFunctionQueue, ()); return staticFunctionQueue; } diff --git a/JavaScriptCore/wtf/MathExtras.h b/JavaScriptCore/wtf/MathExtras.h index cfe5468..76488b4 100644 --- a/JavaScriptCore/wtf/MathExtras.h +++ b/JavaScriptCore/wtf/MathExtras.h @@ -28,7 +28,6 @@ #include <math.h> #include <stdlib.h> -#include <time.h> #if PLATFORM(SOLARIS) #include <ieeefp.h> @@ -40,8 +39,11 @@ #endif #if COMPILER(MSVC) - +#if PLATFORM(WIN_CE) +#include <stdlib.h> +#else #include <xmath.h> +#endif #include <limits> #if HAVE(FLOAT_H) @@ -100,17 +102,22 @@ inline bool signbit(double x) { struct ieee_double *p = (struct ieee_double *)&x #endif -#if COMPILER(MSVC) +#if COMPILER(MSVC) || COMPILER(RVCT) -inline bool isinf(double num) { return !_finite(num) && !_isnan(num); } -inline bool isnan(double num) { return !!_isnan(num); } inline long lround(double num) { return static_cast<long>(num > 0 ? num + 0.5 : ceil(num - 0.5)); } inline long lroundf(float num) { return static_cast<long>(num > 0 ? num + 0.5f : ceilf(num - 0.5f)); } inline double round(double num) { return num > 0 ? floor(num + 0.5) : ceil(num - 0.5); } inline float roundf(float num) { return num > 0 ? floorf(num + 0.5f) : ceilf(num - 0.5f); } -inline bool signbit(double num) { return _copysign(1.0, num) < 0; } inline double trunc(double num) { return num > 0 ? floor(num) : ceil(num); } +#endif + +#if COMPILER(MSVC) + +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; } @@ -150,45 +157,14 @@ inline double wtf_pow(double x, double y) { return y == 0 ? 1 : pow(x, y); } #define fmod(x, y) wtf_fmod(x, y) #define pow(x, y) wtf_pow(x, y) -#if defined(_CRT_RAND_S) -// Initializes the random number generator. -inline void wtf_random_init() -{ - // No need to initialize for rand_s. -} - -// Returns a pseudo-random number in the range [0, 1). -inline double wtf_random() -{ - unsigned u; - rand_s(&u); - - return static_cast<double>(u) / (static_cast<double>(UINT_MAX) + 1.0); -} -#endif // _CRT_RAND_S - #endif // COMPILER(MSVC) -#if !COMPILER(MSVC) || !defined(_CRT_RAND_S) - -// Initializes the random number generator. -inline void wtf_random_init() -{ - srand(static_cast<unsigned>(time(0))); -} - -// Returns a pseudo-random number in the range [0, 1). -inline double wtf_random() -{ - return static_cast<double>(rand()) / (static_cast<double>(RAND_MAX) + 1.0); -} - -#endif // #if 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; } @@ -196,6 +172,8 @@ 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; } diff --git a/JavaScriptCore/wtf/MessageQueue.h b/JavaScriptCore/wtf/MessageQueue.h index 481211d..19c5c10 100644 --- a/JavaScriptCore/wtf/MessageQueue.h +++ b/JavaScriptCore/wtf/MessageQueue.h @@ -36,6 +36,12 @@ 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. + }; + template<typename DataType> class MessageQueue : Noncopyable { public: @@ -44,6 +50,7 @@ namespace WTF { void append(const DataType&); void prepend(const DataType&); bool waitForMessage(DataType&); + MessageQueueWaitResult waitForMessageTimed(DataType&, double absoluteTime); void kill(); bool tryGetMessage(DataType&); @@ -79,7 +86,7 @@ namespace WTF { inline bool MessageQueue<DataType>::waitForMessage(DataType& result) { MutexLocker lock(m_mutex); - + while (!m_killed && m_queue.isEmpty()) m_condition.wait(m_mutex); @@ -93,6 +100,27 @@ namespace WTF { } template<typename DataType> + inline MessageQueueWaitResult MessageQueue<DataType>::waitForMessageTimed(DataType& result, double absoluteTime) + { + MutexLocker lock(m_mutex); + bool timedOut = false; + + while (!m_killed && !timedOut && m_queue.isEmpty()) + timedOut = !m_condition.timedWait(m_mutex, absoluteTime); + + if (m_killed) + return MessageQueueTerminated; + + if (timedOut) + return MessageQueueTimeout; + + ASSERT(!m_queue.isEmpty()); + result = m_queue.first(); + m_queue.removeFirst(); + return MessageQueueMessageReceived; + } + + template<typename DataType> inline bool MessageQueue<DataType>::tryGetMessage(DataType& result) { MutexLocker lock(m_mutex); @@ -132,5 +160,10 @@ 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/JavaScriptCore/wtf/OwnPtr.h b/JavaScriptCore/wtf/OwnPtr.h index 969950f..256b55c 100644 --- a/JavaScriptCore/wtf/OwnPtr.h +++ b/JavaScriptCore/wtf/OwnPtr.h @@ -22,6 +22,7 @@ #define WTF_OwnPtr_h #include <algorithm> +#include <memory> #include <wtf/Assertions.h> #include <wtf/Noncopyable.h> @@ -66,12 +67,17 @@ namespace WTF { typedef ValueType* PtrType; explicit OwnPtr(PtrType ptr = 0) : m_ptr(ptr) { } + OwnPtr(std::auto_ptr<ValueType> autoPtr) : m_ptr(autoPtr.release()) { } ~OwnPtr() { deleteOwnedPtr(m_ptr); } PtrType get() const { return m_ptr; } PtrType release() { PtrType ptr = m_ptr; m_ptr = 0; return ptr; } + // FIXME: This should be renamed to adopt. void set(PtrType ptr) { ASSERT(!ptr || m_ptr != ptr); deleteOwnedPtr(m_ptr); m_ptr = ptr; } + + void adopt(std::auto_ptr<ValueType> autoPtr) { ASSERT(!autoPtr.get() || m_ptr != autoPtr.get()); deleteOwnedPtr(m_ptr); m_ptr = autoPtr.release(); } + void clear() { deleteOwnedPtr(m_ptr); m_ptr = 0; } ValueType& operator*() const { ASSERT(m_ptr); return *m_ptr; } diff --git a/JavaScriptCore/wtf/PassRefPtr.h b/JavaScriptCore/wtf/PassRefPtr.h index ca8f2cb..c1dc309 100644 --- a/JavaScriptCore/wtf/PassRefPtr.h +++ b/JavaScriptCore/wtf/PassRefPtr.h @@ -56,9 +56,12 @@ namespace WTF { bool operator!() const { return !m_ptr; } // This conversion operator allows implicit conversion to bool but not to other integer types. +#if COMPILER(WINSCW) + operator bool() const { return m_ptr; } +#else typedef T* PassRefPtr::*UnspecifiedBoolType; operator UnspecifiedBoolType() const { return m_ptr ? &PassRefPtr::m_ptr : 0; } - +#endif PassRefPtr& operator=(T*); PassRefPtr& operator=(const PassRefPtr&); template <typename U> PassRefPtr& operator=(const PassRefPtr<U>&); diff --git a/JavaScriptCore/wtf/Platform.h b/JavaScriptCore/wtf/Platform.h index 80a7bf1..fea00c4 100644 --- a/JavaScriptCore/wtf/Platform.h +++ b/JavaScriptCore/wtf/Platform.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2006, 2007, 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 @@ -78,15 +78,33 @@ #define WTF_PLATFORM_SOLARIS 1 #endif +#if defined (__S60__) || defined (__SYMBIAN32__) +/* we are cross-compiling, it is not really windows */ +#undef WTF_PLATFORM_WIN_OS +#undef WTF_PLATFORM_WIN +#undef WTF_PLATFORM_CAIRO +#define WTF_PLATFORM_S60 1 +#define WTF_PLATFORM_SYMBIAN 1 +#endif + + +/* PLATFORM(NETBSD) */ +/* Operating system level dependencies for NetBSD that should be used */ +/* regardless of operating environment */ +#if defined(__NetBSD__) +#define WTF_PLATFORM_NETBSD 1 +#endif + /* PLATFORM(UNIX) */ /* Operating system level dependencies for Unix-like systems that */ /* should be used regardless of operating environment */ #if PLATFORM(DARWIN) \ || PLATFORM(FREEBSD) \ + || PLATFORM(S60) \ + || PLATFORM(NETBSD) \ || defined(unix) \ || defined(__unix) \ || defined(__unix__) \ - || defined (__NetBSD__) \ || defined(_AIX) #define WTF_PLATFORM_UNIX 1 #endif @@ -126,25 +144,23 @@ #define WTF_PLATFORM_CI 1 #endif -/* PLATFORM(SKIA) */ +/* PLATFORM(SKIA) for Win/Linux, CG/CI for Mac */ #if PLATFORM(CHROMIUM) +#if PLATFORM(DARWIN) +#define WTF_PLATFORM_CG 1 +#define WTF_PLATFORM_CI 1 +#define WTF_USE_ATSUI 1 +#else #define WTF_PLATFORM_SKIA 1 #endif +#endif /* Makes PLATFORM(WIN) default to PLATFORM(CAIRO) */ -#if !PLATFORM(MAC) && !PLATFORM(QT) && !PLATFORM(WX) +/* FIXME: This should be changed from a blacklist to a whitelist */ +#if !PLATFORM(MAC) && !PLATFORM(QT) && !PLATFORM(WX) && !PLATFORM(CHROMIUM) #define WTF_PLATFORM_CAIRO 1 #endif -#ifdef __S60__ -// we are cross-compiling, it is not really windows -#undef WTF_PLATFORM_WIN_OS -#undef WTF_PLATFORM_WIN -#undef WTF_PLATFORM_CAIRO -#define WTF_PLATFORM_S60 1 -#define WTF_PLATFORM_SYMBIAN 1 -#endif - #ifdef ANDROID #define WTF_PLATFORM_ANDROID 1 #define WTF_PLATFORM_LINUX 1 @@ -228,6 +244,20 @@ #define WTF_PLATFORM_BIG_ENDIAN 1 #endif +/* PLATFORM(WIN_CE) && PLATFORM(QT) + We can not determine the endianess at compile time. For + Qt for Windows CE the endianess is specified in the + device specific makespec +*/ +#if PLATFORM(WIN_CE) && PLATFORM(QT) +# include <QtGlobal> +# undef WTF_PLATFORM_BIG_ENDIAN +# undef WTF_PLATFORM_MIDDLE_ENDIAN +# if Q_BYTE_ORDER == Q_BIG_EDIAN +# define WTF_PLATFORM_BIG_ENDIAN 1 +# endif +#endif + /* Compiler */ /* COMPILER(MSVC) */ @@ -260,6 +290,16 @@ #define WTF_COMPILER_CYGWIN 1 #endif +/* COMPILER(RVCT) */ +#if defined(__CC_ARM) || defined(__ARMCC__) +#define WTF_COMPILER_RVCT 1 +#endif + +/* COMPILER(WINSCW) */ +#if defined(__WINSCW__) +#define WTF_COMPILER_WINSCW 1 +#endif + #if (PLATFORM(MAC) || PLATFORM(WIN)) && !defined(ENABLE_JSC_MULTIPLE_THREADS) #define ENABLE_JSC_MULTIPLE_THREADS 1 #endif @@ -290,6 +330,11 @@ #endif #endif +#if PLATFORM(CHROMIUM) && PLATFORM(DARWIN) +#define WTF_PLATFORM_CF 1 +#define WTF_USE_PTHREADS 1 +#endif + #if PLATFORM(WIN) #define WTF_USE_WININET 1 #endif @@ -305,9 +350,11 @@ #endif #endif +#if !defined(HAVE_ACCESSIBILITY) #if PLATFORM(MAC) || PLATFORM(WIN) || PLATFORM(GTK) || PLATFORM(CHROMIUM) #define HAVE_ACCESSIBILITY 1 #endif +#endif /* !defined(HAVE_ACCESSIBILITY) */ #if COMPILER(GCC) #define HAVE_COMPUTED_GOTO 1 @@ -327,9 +374,26 @@ #elif PLATFORM(WIN_OS) #define HAVE_FLOAT_H 1 +#if PLATFORM(WIN_CE) +#define HAVE_ERRNO_H 0 +#else #define HAVE_SYS_TIMEB_H 1 +#endif #define HAVE_VIRTUALALLOC 1 +#elif PLATFORM(SYMBIAN) + +#define HAVE_ERRNO_H 1 +#define HAVE_MMAP 0 +#define HAVE_SBRK 1 + +#define HAVE_SYS_TIME_H 1 +#define HAVE_STRINGS_H 1 + +#if !COMPILER(RVCT) +#define HAVE_SYS_PARAM_H 1 +#endif + #else /* FIXME: is this actually used or do other platforms generate their own config.h? */ @@ -402,24 +466,58 @@ #define ENABLE_ARCHIVE 1 #endif -// CTI only supports x86 at the moment, and has only been tested on Mac and Windows. -#if !defined(ENABLE_CTI) && PLATFORM(X86) && (PLATFORM(MAC) || PLATFORM(WIN)) -#define ENABLE_CTI 1 +#if !defined(WTF_USE_ALTERNATE_JSIMMEDIATE) && PLATFORM(X86_64) && PLATFORM(MAC) +#define WTF_USE_ALTERNATE_JSIMMEDIATE 1 #endif -// WREC only supports x86 at the moment, and has only been tested on Mac and Windows. -#if !defined(ENABLE_WREC) && ENABLE(CTI) && PLATFORM(X86) && (PLATFORM(MAC) || PLATFORM(WIN)) +#if !defined(ENABLE_JIT) +/* x86-64 support is under development. */ +#if PLATFORM(X86_64) && PLATFORM(MAC) + #define ENABLE_JIT 0 + #define WTF_USE_JIT_STUB_ARGUMENT_REGISTER 1 +/* The JIT is tested & working on x86 Mac */ +#elif PLATFORM(X86) && PLATFORM(MAC) + #define ENABLE_JIT 1 + #define WTF_USE_JIT_STUB_ARGUMENT_VA_LIST 1 +/* The JIT is tested & working on x86 Windows */ +#elif PLATFORM(X86) && PLATFORM(WIN) + #define ENABLE_JIT 1 + #define WTF_USE_JIT_STUB_ARGUMENT_REGISTER 1 +#endif + #define ENABLE_JIT_OPTIMIZE_CALL 1 + #define ENABLE_JIT_OPTIMIZE_PROPERTY_ACCESS 1 + #define ENABLE_JIT_OPTIMIZE_ARITHMETIC 1 +#endif + +#if ENABLE(JIT) +#if !(USE(JIT_STUB_ARGUMENT_VA_LIST) || USE(JIT_STUB_ARGUMENT_REGISTER) || USE(JIT_STUB_ARGUMENT_STACK)) +#error Please define one of the JIT_STUB_ARGUMENT settings. +#elif (USE(JIT_STUB_ARGUMENT_VA_LIST) && USE(JIT_STUB_ARGUMENT_REGISTER)) \ + || (USE(JIT_STUB_ARGUMENT_VA_LIST) && USE(JIT_STUB_ARGUMENT_STACK)) \ + || (USE(JIT_STUB_ARGUMENT_REGISTER) && USE(JIT_STUB_ARGUMENT_STACK)) +#error Please do not define more than one of the JIT_STUB_ARGUMENT settings. +#endif +#endif + +/* WREC supports x86 & x86-64, and has been tested on Mac and Windows ('cept on 64-bit on Mac). */ +#if (!defined(ENABLE_WREC) && PLATFORM(X86) && PLATFORM(MAC)) \ + || (!defined(ENABLE_WREC) && PLATFORM(X86_64) && PLATFORM(MAC)) \ + || (!defined(ENABLE_WREC) && PLATFORM(X86) && PLATFORM(WIN)) #define ENABLE_WREC 1 #endif -#if ENABLE(CTI) || ENABLE(WREC) -#define ENABLE_MASM 1 +#if ENABLE(JIT) || ENABLE(WREC) +#define ENABLE_ASSEMBLER 1 #endif -#if !defined(ENABLE_PAN_SCROLLING) && (PLATFORM(WIN) || PLATFORM(CHROMIUM) || (PLATFORM(WX) && PLATFORM(WIN_OS))) +#if !defined(ENABLE_PAN_SCROLLING) && PLATFORM(WIN_OS) #define ENABLE_PAN_SCROLLING 1 #endif +#if !defined(ENABLE_ACTIVEX_TYPE_CONVERSION_WMPLAYER) +#define ENABLE_ACTIVEX_TYPE_CONVERSION_WMPLAYER 1 +#endif + /* Use the QtXmlStreamReader implementation for XMLTokenizer */ #if PLATFORM(QT) #if !ENABLE(XSLT) @@ -427,10 +525,8 @@ #endif #endif -// Use "fastcall" calling convention on MSVC -#if COMPILER(MSVC) -#define WTF_USE_FAST_CALL_CTI_ARGUMENT 1 -#define WTF_USE_CTI_ARGUMENT 1 +#if !PLATFORM(QT) +#define WTF_USE_FONT_FAST_PATH 1 #endif #endif /* WTF_Platform_h */ diff --git a/JavaScriptCore/wtf/PtrAndFlags.h b/JavaScriptCore/wtf/PtrAndFlags.h new file mode 100644 index 0000000..477e893 --- /dev/null +++ b/JavaScriptCore/wtf/PtrAndFlags.h @@ -0,0 +1,53 @@ +/* + * 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 PtrAndFlags_h +#define PtrAndFlags_h + +#include <wtf/Assertions.h> + +namespace WTF { + template<class T, typename FlagEnum> class PtrAndFlags { + public: + PtrAndFlags() : m_ptrAndFlags(0) {} + + bool isFlagSet(FlagEnum flagNumber) const { ASSERT(flagNumber < 2); return m_ptrAndFlags & (1 << flagNumber); } + void setFlag(FlagEnum flagNumber) { ASSERT(flagNumber < 2); m_ptrAndFlags |= (1 << flagNumber);} + void clearFlag(FlagEnum flagNumber) { ASSERT(flagNumber < 2); m_ptrAndFlags &= ~(1 << flagNumber);} + T* get() const { return reinterpret_cast<T*>(m_ptrAndFlags & ~3); } + void set(T* ptr) { ASSERT(!(reinterpret_cast<intptr_t>(ptr) & 3)); m_ptrAndFlags = reinterpret_cast<intptr_t>(ptr) | (m_ptrAndFlags & 3);} + private: + intptr_t m_ptrAndFlags; + }; +} // namespace WTF + +using WTF::PtrAndFlags; + +#endif // PtrAndFlags_h diff --git a/JavaScriptCore/wtf/RandomNumber.cpp b/JavaScriptCore/wtf/RandomNumber.cpp new file mode 100644 index 0000000..c94d5a4 --- /dev/null +++ b/JavaScriptCore/wtf/RandomNumber.cpp @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. + * (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. + */ + +#include "config.h" +#include "RandomNumber.h" + +#include "RandomNumberSeed.h" + +#include <limits> +#include <limits.h> +#include <stdint.h> +#include <stdlib.h> + +namespace WTF { + +double weakRandomNumber() +{ +#if COMPILER(MSVC) && defined(_CRT_RAND_S) + // rand_s is incredibly slow on windows so we fall back on rand for Math.random + return (rand() + (rand() / (RAND_MAX + 1.0))) / (RAND_MAX + 1.0); +#else + return randomNumber(); +#endif +} + +double randomNumber() +{ +#if !ENABLE(JSC_MULTIPLE_THREADS) + static bool s_initialized = false; + if (!s_initialized) { + initializeRandomNumberGenerator(); + s_initialized = true; + } +#endif + +#if COMPILER(MSVC) && defined(_CRT_RAND_S) + uint32_t bits; + rand_s(&bits); + return static_cast<double>(bits) / (static_cast<double>(std::numeric_limits<uint32_t>::max()) + 1.0); +#elif PLATFORM(DARWIN) + uint32_t bits = arc4random(); + return static_cast<double>(bits) / (static_cast<double>(std::numeric_limits<uint32_t>::max()) + 1.0); +#elif PLATFORM(UNIX) + uint32_t part1 = random() & (RAND_MAX - 1); + uint32_t part2 = random() & (RAND_MAX - 1); + // random only provides 31 bits + uint64_t fullRandom = part1; + fullRandom <<= 31; + fullRandom |= part2; + + // Mask off the low 53bits + fullRandom &= (1LL << 53) - 1; + return static_cast<double>(fullRandom)/static_cast<double>(1LL << 53); +#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 +} + +} diff --git a/JavaScriptCore/wtf/RandomNumber.h b/JavaScriptCore/wtf/RandomNumber.h new file mode 100644 index 0000000..fe1687c --- /dev/null +++ b/JavaScriptCore/wtf/RandomNumber.h @@ -0,0 +1,42 @@ +/* + * 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 + double randomNumber(); + + // Returns a pseudo-random number in the range [0, 1), attempts to + // produce a reasonable "random" number fast. + // We only need this because rand_s is so slow on windows. + double weakRandomNumber(); + +} + +#endif diff --git a/JavaScriptCore/wtf/RandomNumberSeed.h b/JavaScriptCore/wtf/RandomNumberSeed.h new file mode 100644 index 0000000..f994fd9 --- /dev/null +++ b/JavaScriptCore/wtf/RandomNumberSeed.h @@ -0,0 +1,71 @@ +/* + * 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 PLATFORM(UNIX) +#include <sys/types.h> +#include <unistd.h> +#endif + +// Internal JavaScriptCore usage only +namespace WTF { + +inline void initializeRandomNumberGenerator() +{ +#if PLATFORM(DARWIN) + // On Darwin we use arc4random which initialises itself. +#elif COMPILER(MSVC) && defined(_CRT_RAND_S) + // On Windows we use rand_s which intialises itself +#elif PLATFORM(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 +} + +inline void initializeWeakRandomNumberGenerator() +{ +#if COMPILER(MSVC) && defined(_CRT_RAND_S) + // We need to initialise windows rand() explicitly for Math.random + unsigned seed = 0; + rand_s(&seed); + srand(seed); +#endif +} +} + +#endif diff --git a/JavaScriptCore/wtf/RefCounted.h b/JavaScriptCore/wtf/RefCounted.h index 2dd5b2a..ac8e167 100644 --- a/JavaScriptCore/wtf/RefCounted.h +++ b/JavaScriptCore/wtf/RefCounted.h @@ -75,7 +75,7 @@ protected: return false; } -private: +protected: int m_refCount; #ifndef NDEBUG bool m_deletionHasBegun; diff --git a/JavaScriptCore/wtf/RefPtr.h b/JavaScriptCore/wtf/RefPtr.h index 78bd257..929e745 100644 --- a/JavaScriptCore/wtf/RefPtr.h +++ b/JavaScriptCore/wtf/RefPtr.h @@ -62,8 +62,12 @@ namespace WTF { bool operator!() const { return !m_ptr; } // This conversion operator allows implicit conversion to bool but not to other integer types. +#if COMPILER(WINSCW) + operator bool() const { return m_ptr; } +#else typedef T* RefPtr::*UnspecifiedBoolType; operator UnspecifiedBoolType() const { return m_ptr ? &RefPtr::m_ptr : 0; } +#endif RefPtr& operator=(const RefPtr&); RefPtr& operator=(T*); diff --git a/JavaScriptCore/wtf/RetainPtr.h b/JavaScriptCore/wtf/RetainPtr.h index 2d73603..a66a127 100644 --- a/JavaScriptCore/wtf/RetainPtr.h +++ b/JavaScriptCore/wtf/RetainPtr.h @@ -1,6 +1,5 @@ /* - * This file is part of the KDE libraries - * Copyright (C) 2005, 2006 Apple Computer, Inc. + * 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 diff --git a/JavaScriptCore/wtf/StdLibExtras.h b/JavaScriptCore/wtf/StdLibExtras.h new file mode 100644 index 0000000..14227ab --- /dev/null +++ b/JavaScriptCore/wtf/StdLibExtras.h @@ -0,0 +1,63 @@ +/* + * 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/Platform.h> +#include <wtf/Assertions.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. +#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 + +namespace WTF { + + /* + * C++'s idea of a reinterpret_cast lacks sufficient cojones. + */ + template<typename TO, typename FROM> + TO bitwise_cast(FROM in) + { + COMPILE_ASSERT(sizeof(TO) == sizeof(FROM), WTF_wtf_reinterpret_cast_sizeof_types_is_equal); + union { + FROM from; + TO to; + } u; + u.from = in; + return u.to; + } + +} // namespace WTF + +#endif diff --git a/JavaScriptCore/wtf/TCSpinLock.h b/JavaScriptCore/wtf/TCSpinLock.h index 3c6ac11..d651e31 100644 --- a/JavaScriptCore/wtf/TCSpinLock.h +++ b/JavaScriptCore/wtf/TCSpinLock.h @@ -46,7 +46,6 @@ #else #include <sys/types.h> #endif -#include <stdlib.h> /* for abort() */ #if PLATFORM(WIN_OS) #ifndef WIN32_LEAN_AND_MEAN @@ -199,16 +198,16 @@ struct TCMalloc_SpinLock { pthread_mutex_t private_lock_; inline void Init() { - if (pthread_mutex_init(&private_lock_, NULL) != 0) abort(); + if (pthread_mutex_init(&private_lock_, NULL) != 0) CRASH(); } inline void Finalize() { - if (pthread_mutex_destroy(&private_lock_) != 0) abort(); + if (pthread_mutex_destroy(&private_lock_) != 0) CRASH(); } inline void Lock() { - if (pthread_mutex_lock(&private_lock_) != 0) abort(); + if (pthread_mutex_lock(&private_lock_) != 0) CRASH(); } inline void Unlock() { - if (pthread_mutex_unlock(&private_lock_) != 0) abort(); + if (pthread_mutex_unlock(&private_lock_) != 0) CRASH(); } }; diff --git a/JavaScriptCore/wtf/TCSystemAlloc.cpp b/JavaScriptCore/wtf/TCSystemAlloc.cpp index bd6eb33..3a8908d 100644 --- a/JavaScriptCore/wtf/TCSystemAlloc.cpp +++ b/JavaScriptCore/wtf/TCSystemAlloc.cpp @@ -170,7 +170,7 @@ static void* TryMmap(size_t size, size_t *actual_size, size_t alignment) { extra = alignment - pagesize; } void* result = mmap(NULL, size + extra, - PROT_READ|PROT_WRITE, + PROT_READ | PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); if (result == reinterpret_cast<void*>(MAP_FAILED)) { @@ -224,7 +224,7 @@ static void* TryVirtualAlloc(size_t size, size_t *actual_size, size_t alignment) } void* result = VirtualAlloc(NULL, size + extra, MEM_RESERVE | MEM_COMMIT | MEM_TOP_DOWN, - PAGE_EXECUTE_READWRITE); + PAGE_READWRITE); if (result == NULL) { VirtualAlloc_failure = true; @@ -302,7 +302,7 @@ static void* TryDevMem(size_t size, size_t *actual_size, size_t alignment) { devmem_failure = true; return NULL; } - void *result = mmap(0, size + extra, PROT_WRITE|PROT_READ, + 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; @@ -383,8 +383,6 @@ void* TCMalloc_SystemAlloc(size_t size, size_t *actual_size, size_t alignment) { void TCMalloc_SystemRelease(void* start, size_t length) { - UNUSED_PARAM(start); - UNUSED_PARAM(length); #if HAVE(MADV_DONTNEED) if (FLAGS_malloc_devmem_start) { // It's not safe to use MADV_DONTNEED if we've been mapping @@ -421,18 +419,20 @@ void TCMalloc_SystemRelease(void* start, size_t length) #endif #if HAVE(MMAP) - void *newAddress = mmap(start, length, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, -1, 0); - UNUSED_PARAM(newAddress); + 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(newAddress == start || newAddress == reinterpret_cast<void*>(MAP_FAILED)); + ASSERT_UNUSED(newAddress, newAddress == start || newAddress == reinterpret_cast<void*>(MAP_FAILED)); return; #endif + +#if !HAVE(MADV_DONTNEED) && !HAVE(MMAP) + UNUSED_PARAM(start); + UNUSED_PARAM(length); +#endif } #if HAVE(VIRTUALALLOC) -void TCMalloc_SystemCommit(void* start, size_t length) +void TCMalloc_SystemCommit(void*, size_t) { - UNUSED_PARAM(start); - UNUSED_PARAM(length); } #endif diff --git a/JavaScriptCore/wtf/ThreadSpecific.h b/JavaScriptCore/wtf/ThreadSpecific.h index 87709a1..7603802 100644 --- a/JavaScriptCore/wtf/ThreadSpecific.h +++ b/JavaScriptCore/wtf/ThreadSpecific.h @@ -1,5 +1,6 @@ /* * 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 @@ -26,19 +27,36 @@ * 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> -#if USE(PTHREADS) || PLATFORM(WIN) -// Windows currently doesn't use pthreads for basic threading, but implementing destructor functions is easier -// with pthreads, so we use it here. +#if USE(PTHREADS) #include <pthread.h> +#elif PLATFORM(WIN_OS) +#include <windows.h> #endif namespace WTF { +#if !USE(PTHREADS) && PLATFORM(WIN_OS) +// 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 : Noncopyable { public: ThreadSpecific(); @@ -48,23 +66,34 @@ public: ~ThreadSpecific(); private: +#if !USE(PTHREADS) && PLATFORM(WIN_OS) + friend void ThreadSpecificThreadExit(); +#endif + T* get(); void set(T*); void static destroy(void* ptr); -#if USE(PTHREADS) || PLATFORM(WIN) +#if USE(PTHREADS) || PLATFORM(WIN_OS) struct Data : Noncopyable { Data(T* value, ThreadSpecific<T>* owner) : value(value), owner(owner) {} T* value; ThreadSpecific<T>* owner; +#if !USE(PTHREADS) + void (*destructor)(void*); +#endif }; +#endif +#if USE(PTHREADS) pthread_key_t m_key; +#elif PLATFORM(WIN_OS) + int m_index; #endif }; -#if USE(PTHREADS) || PLATFORM(WIN) +#if USE(PTHREADS) template<typename T> inline ThreadSpecific<T>::ThreadSpecific() { @@ -93,26 +122,92 @@ inline void ThreadSpecific<T>::set(T* ptr) pthread_setspecific(m_key, new Data(ptr, this)); } +#elif PLATFORM(WIN_OS) + +// 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; + +extern long g_tls_key_count; +extern DWORD g_tls_keys[kMaxTlsKeySize]; + +template<typename T> +inline ThreadSpecific<T>::ThreadSpecific() + : m_index(-1) +{ + DWORD tls_key = TlsAlloc(); + if (tls_key == TLS_OUT_OF_INDEXES) + CRASH(); + + m_index = InterlockedIncrement(&g_tls_key_count) - 1; + if (m_index >= kMaxTlsKeySize) + CRASH(); + g_tls_keys[m_index] = tls_key; +} + +template<typename T> +inline ThreadSpecific<T>::~ThreadSpecific() +{ + // Does not invoke destructor functions. They will be called from ThreadSpecificThreadExit when the thread is detached. + TlsFree(g_tls_keys[m_index]); +} + +template<typename T> +inline T* ThreadSpecific<T>::get() +{ + Data* data = static_cast<Data*>(TlsGetValue(g_tls_keys[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(g_tls_keys[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); - pthread_setspecific(data->owner->m_key, 0); - delete data->value; - delete data; -} +#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 PLATFORM(WIN_OS) + TlsSetValue(g_tls_keys[data->owner->m_index], 0); #else #error ThreadSpecific is not implemented for this platform. #endif + delete data; +} + template<typename T> inline ThreadSpecific<T>::operator T*() { T* ptr = static_cast<T*>(get()); if (!ptr) { - ptr = new T(); + // 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*>(fastMalloc(sizeof(T))); set(ptr); + new (ptr) T; } return ptr; } diff --git a/JavaScriptCore/wtf/ThreadSpecificWin.cpp b/JavaScriptCore/wtf/ThreadSpecificWin.cpp new file mode 100644 index 0000000..1a3febb --- /dev/null +++ b/JavaScriptCore/wtf/ThreadSpecificWin.cpp @@ -0,0 +1,45 @@ +/* + * 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" +#include <wtf/Noncopyable.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 g_tls_key_count = 0; +DWORD g_tls_keys[kMaxTlsKeySize]; + +void ThreadSpecificThreadExit() +{ + for (long i = 0; i < g_tls_key_count; 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(g_tls_keys[i])); + if (data) + data->destructor(data); + } +} + +} // namespace WTF diff --git a/JavaScriptCore/wtf/Threading.cpp b/JavaScriptCore/wtf/Threading.cpp new file mode 100644 index 0000000..41c9135 --- /dev/null +++ b/JavaScriptCore/wtf/Threading.cpp @@ -0,0 +1,83 @@ +/* + * 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 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" + +namespace WTF { + +struct NewThreadContext { + NewThreadContext(ThreadFunction entryPoint, void* data) + : entryPoint(entryPoint) + , data(data) + { } + + ThreadFunction entryPoint; + void* data; + + Mutex creationMutex; +}; + +static void* threadEntryPoint(void* contextData) +{ + NewThreadContext* context = reinterpret_cast<NewThreadContext*>(contextData); + + // Block until our creating thread has completed any extra setup work + { + MutexLocker locker(context->creationMutex); + } + + // Grab the info that we need out of the context, then deallocate it. + ThreadFunction entryPoint = context->entryPoint; + void* data = context->data; + delete context; + + return entryPoint(data); +} + +ThreadIdentifier createThread(ThreadFunction entryPoint, void* data, const char* name) +{ + NewThreadContext* context = new NewThreadContext(entryPoint, data); + + // 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) + +// This function is deprecated but needs to be kept around for backward +// compatibility. Use the 3-argument version of createThread above. + +ThreadIdentifier createThread(ThreadFunction entryPoint, void* data); + +ThreadIdentifier createThread(ThreadFunction entryPoint, void* data) +{ + return createThread(entryPoint, data, 0); +} +#endif + +} // namespace WTF diff --git a/JavaScriptCore/wtf/Threading.h b/JavaScriptCore/wtf/Threading.h index b464da3..1c0dab1 100644 --- a/JavaScriptCore/wtf/Threading.h +++ b/JavaScriptCore/wtf/Threading.h @@ -59,11 +59,15 @@ #ifndef Threading_h #define Threading_h +#if PLATFORM(WIN_CE) +#include <windows.h> +#endif + #include <wtf/Assertions.h> #include <wtf/Locker.h> #include <wtf/Noncopyable.h> -#if PLATFORM(WIN_OS) +#if PLATFORM(WIN_OS) && !PLATFORM(WIN_CE) #include <windows.h> #elif PLATFORM(DARWIN) #include <libkern/OSAtomic.h> @@ -108,6 +112,7 @@ typedef void* (*ThreadFunction)(void* argument); // Returns 0 if thread creation failed ThreadIdentifier createThread(ThreadFunction, void*, const char* threadName); +ThreadIdentifier createThreadInternal(ThreadFunction, void*, const char* threadName); ThreadIdentifier currentThread(); bool isMainThread(); @@ -129,12 +134,15 @@ struct PlatformMutex { size_t m_recursionCount; }; struct PlatformCondition { - size_t m_timedOut; - size_t m_blocked; - size_t m_waitingForRemoval; - HANDLE m_gate; - HANDLE m_queue; - HANDLE m_mutex; + 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; @@ -164,8 +172,9 @@ public: ~ThreadCondition(); void wait(Mutex& mutex); - // Returns true if the condition was signaled before the timeout, false if the timeout was reached - bool timedWait(Mutex&, double interval); + // 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(). + bool timedWait(Mutex&, double absoluteTime); void signal(); void broadcast(); @@ -176,7 +185,7 @@ private: #if PLATFORM(WIN_OS) #define WTF_USE_LOCKFREE_THREADSAFESHARED 1 -#if COMPILER(MINGW) || COMPILER(MSVC7) +#if COMPILER(MINGW) || COMPILER(MSVC7) || PLATFORM(WIN_CE) inline void atomicIncrement(int* addend) { InterlockedIncrement(reinterpret_cast<long*>(addend)); } inline int atomicDecrement(int* addend) { return InterlockedDecrement(reinterpret_cast<long*>(addend)); } #else @@ -258,14 +267,8 @@ private: // 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. void initializeThreading(); -#if !PLATFORM(WIN_OS) || PLATFORM(WX) -extern Mutex* atomicallyInitializedStaticMutex; -inline void lockAtomicallyInitializedStaticMutex() { atomicallyInitializedStaticMutex->lock(); } -inline void unlockAtomicallyInitializedStaticMutex() { atomicallyInitializedStaticMutex->unlock(); } -#else void lockAtomicallyInitializedStaticMutex(); void unlockAtomicallyInitializedStaticMutex(); -#endif } // namespace WTF diff --git a/JavaScriptCore/wtf/ThreadingGtk.cpp b/JavaScriptCore/wtf/ThreadingGtk.cpp index 53fd1fe..24c34ca 100644 --- a/JavaScriptCore/wtf/ThreadingGtk.cpp +++ b/JavaScriptCore/wtf/ThreadingGtk.cpp @@ -32,15 +32,17 @@ #if !USE(PTHREADS) +#include "CurrentTime.h" #include "HashMap.h" #include "MainThread.h" -#include "MathExtras.h" +#include "RandomNumberSeed.h" #include <glib.h> +#include <limits.h> namespace WTF { -Mutex* atomicallyInitializedStaticMutex; +static Mutex* atomicallyInitializedStaticMutex; static ThreadIdentifier mainThreadIdentifier; @@ -59,27 +61,27 @@ void initializeThreading() if (!atomicallyInitializedStaticMutex) { atomicallyInitializedStaticMutex = new Mutex; threadMapMutex(); - wtf_random_init(); + initializeRandomNumberGenerator(); mainThreadIdentifier = currentThread(); initializeMainThread(); } } -static HashMap<ThreadIdentifier, GThread*>& threadMap() +void lockAtomicallyInitializedStaticMutex() { - static HashMap<ThreadIdentifier, GThread*> map; - return map; + ASSERT(atomicallyInitializedStaticMutex); + atomicallyInitializedStaticMutex->lock(); } -static ThreadIdentifier establishIdentifierForThread(GThread*& thread) +void unlockAtomicallyInitializedStaticMutex() { - MutexLocker locker(threadMapMutex()); - - static ThreadIdentifier identifierCount = 1; - - threadMap().add(identifierCount, thread); + atomicallyInitializedStaticMutex->unlock(); +} - return identifierCount++; +static HashMap<ThreadIdentifier, GThread*>& threadMap() +{ + static HashMap<ThreadIdentifier, GThread*> map; + return map; } static ThreadIdentifier identifierByGthreadHandle(GThread*& thread) @@ -95,6 +97,19 @@ static ThreadIdentifier identifierByGthreadHandle(GThread*& thread) return 0; } +static ThreadIdentifier establishIdentifierForThread(GThread*& thread) +{ + ASSERT(!identifierByGthreadHandle(thread)); + + MutexLocker locker(threadMapMutex()); + + static ThreadIdentifier identifierCount = 1; + + threadMap().add(identifierCount, thread); + + return identifierCount++; +} + static GThread* threadForIdentifier(ThreadIdentifier id) { MutexLocker locker(threadMapMutex()); @@ -111,7 +126,7 @@ static void clearThreadForIdentifier(ThreadIdentifier id) threadMap().remove(id); } -ThreadIdentifier createThread(ThreadFunction entryPoint, void* data, const char*) +ThreadIdentifier createThreadInternal(ThreadFunction entryPoint, void* data, const char*) { GThread* thread; if (!(thread = g_thread_create(entryPoint, data, TRUE, 0))) { @@ -129,7 +144,9 @@ int waitForThreadCompletion(ThreadIdentifier threadID, void** result) GThread* thread = threadForIdentifier(threadID); - *result = g_thread_join(thread); + void* joinResult = g_thread_join(thread); + if (result) + *result = joinResult; clearThreadForIdentifier(threadID); return 0; @@ -190,25 +207,24 @@ void ThreadCondition::wait(Mutex& mutex) g_cond_wait(m_condition.get(), mutex.impl().get()); } -bool ThreadCondition::timedWait(Mutex& mutex, double interval) +bool ThreadCondition::timedWait(Mutex& mutex, double absoluteTime) { - if (interval < 0.0) { + // Time is in the past - return right away. + if (absoluteTime < currentTime()) + return false; + + // Time is too far in the future for g_cond_timed_wait - wait forever. + if (absoluteTime > INT_MAX) { wait(mutex); return true; } - - int intervalSeconds = static_cast<int>(interval); - int intervalMicroseconds = static_cast<int>((interval - intervalSeconds) * 1000000.0); + + int timeSeconds = static_cast<int>(absoluteTime); + int timeMicroseconds = static_cast<int>((absoluteTime - timeSeconds) * 1000000.0); GTimeVal targetTime; - g_get_current_time(&targetTime); - - targetTime.tv_sec += intervalSeconds; - targetTime.tv_usec += intervalMicroseconds; - if (targetTime.tv_usec > 1000000) { - targetTime.tv_usec -= 1000000; - targetTime.tv_sec++; - } + targetTime.tv_sec = timeSeconds; + targetTime.tv_usec = timeMicroseconds; return g_cond_timed_wait(m_condition.get(), mutex.impl().get(), &targetTime); } diff --git a/JavaScriptCore/wtf/ThreadingNone.cpp b/JavaScriptCore/wtf/ThreadingNone.cpp index c17b3b2..0be2a4b 100644 --- a/JavaScriptCore/wtf/ThreadingNone.cpp +++ b/JavaScriptCore/wtf/ThreadingNone.cpp @@ -26,31 +26,33 @@ * (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" namespace WTF { -Mutex* atomicallyInitializedStaticMutex; - -void initializeThreading() {} -ThreadIdentifier createThread(ThreadFunction, void*, const char*) { return 0; } +void initializeThreading() { } +ThreadIdentifier createThreadInternal(ThreadFunction, void*, const char*) { return 0; } int waitForThreadCompletion(ThreadIdentifier, void**) { return 0; } void detachThread(ThreadIdentifier) { } ThreadIdentifier currentThread() { return 0; } -bool isMainThread() { return false; } +bool isMainThread() { return true; } -Mutex::Mutex() {} -Mutex::~Mutex() {} -void Mutex::lock() {} +Mutex::Mutex() { } +Mutex::~Mutex() { } +void Mutex::lock() { } bool Mutex::tryLock() { return false; } -void Mutex::unlock() {}; +void Mutex::unlock() { } + +ThreadCondition::ThreadCondition() { } +ThreadCondition::~ThreadCondition() { } +void ThreadCondition::wait(Mutex& mutex) { } +bool ThreadCondition::timedWait(Mutex& mutex, double absoluteTime) { return false; } +void ThreadCondition::signal() { } +void ThreadCondition::broadcast() { } -ThreadCondition::ThreadCondition() {} -ThreadCondition::~ThreadCondition() {} -void ThreadCondition::wait(Mutex& mutex) {} -bool ThreadCondition::timedWait(Mutex& mutex, double interval) { return false; } -void ThreadCondition::signal() {} -void ThreadCondition::broadcast() {} +void lockAtomicallyInitializedStaticMutex() { } +void unlockAtomicallyInitializedStaticMutex() { } } // namespace WebCore diff --git a/JavaScriptCore/wtf/ThreadingPthreads.cpp b/JavaScriptCore/wtf/ThreadingPthreads.cpp index d17a03d..105e42a 100644 --- a/JavaScriptCore/wtf/ThreadingPthreads.cpp +++ b/JavaScriptCore/wtf/ThreadingPthreads.cpp @@ -29,18 +29,24 @@ #include "config.h" #include "Threading.h" +#include "StdLibExtras.h" + #if USE(PTHREADS) +#include "CurrentTime.h" #include "HashMap.h" #include "MainThread.h" -#include "MathExtras.h" +#include "RandomNumberSeed.h" #include <errno.h> +#include <limits.h> #include <sys/time.h> namespace WTF { -Mutex* atomicallyInitializedStaticMutex; +typedef HashMap<ThreadIdentifier, pthread_t> ThreadMap; + +static Mutex* atomicallyInitializedStaticMutex; #if !PLATFORM(DARWIN) static ThreadIdentifier mainThreadIdentifier; // The thread that was the first to call initializeThreading(), which must be the main thread. @@ -48,7 +54,7 @@ static ThreadIdentifier mainThreadIdentifier; // The thread that was the first t static Mutex& threadMapMutex() { - static Mutex mutex; + DEFINE_STATIC_LOCAL(Mutex, mutex, ()); return mutex; } @@ -57,7 +63,7 @@ void initializeThreading() if (!atomicallyInitializedStaticMutex) { atomicallyInitializedStaticMutex = new Mutex; threadMapMutex(); - wtf_random_init(); + initializeRandomNumberGenerator(); #if !PLATFORM(DARWIN) mainThreadIdentifier = currentThread(); #endif @@ -65,28 +71,28 @@ void initializeThreading() } } -static HashMap<ThreadIdentifier, pthread_t>& threadMap() +void lockAtomicallyInitializedStaticMutex() { - static HashMap<ThreadIdentifier, pthread_t> map; - return map; + ASSERT(atomicallyInitializedStaticMutex); + atomicallyInitializedStaticMutex->lock(); } -static ThreadIdentifier establishIdentifierForPthreadHandle(pthread_t& pthreadHandle) +void unlockAtomicallyInitializedStaticMutex() { - MutexLocker locker(threadMapMutex()); - - static ThreadIdentifier identifierCount = 1; + atomicallyInitializedStaticMutex->unlock(); +} - threadMap().add(identifierCount, pthreadHandle); - - return identifierCount++; +static ThreadMap& threadMap() +{ + DEFINE_STATIC_LOCAL(ThreadMap, map, ()); + return map; } static ThreadIdentifier identifierByPthreadHandle(const pthread_t& pthreadHandle) { MutexLocker locker(threadMapMutex()); - HashMap<ThreadIdentifier, pthread_t>::iterator i = threadMap().begin(); + ThreadMap::iterator i = threadMap().begin(); for (; i != threadMap().end(); ++i) { if (pthread_equal(i->second, pthreadHandle)) return i->first; @@ -95,6 +101,19 @@ static ThreadIdentifier identifierByPthreadHandle(const pthread_t& pthreadHandle return 0; } +static ThreadIdentifier establishIdentifierForPthreadHandle(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()); @@ -111,7 +130,7 @@ static void clearPthreadHandleForIdentifier(ThreadIdentifier id) threadMap().remove(id); } -ThreadIdentifier createThread(ThreadFunction entryPoint, void* data, const char*) +ThreadIdentifier createThreadInternal(ThreadFunction entryPoint, void* data, const char*) { pthread_t threadHandle; if (pthread_create(&threadHandle, NULL, entryPoint, data)) { @@ -119,19 +138,9 @@ ThreadIdentifier createThread(ThreadFunction entryPoint, void* data, const char* return 0; } - ThreadIdentifier threadID = establishIdentifierForPthreadHandle(threadHandle); - return threadID; + return establishIdentifierForPthreadHandle(threadHandle); } -#if PLATFORM(MAC) -// This function is deprecated but needs to be kept around for backward -// compatibility. Use the 3-argument version of createThread above instead. -ThreadIdentifier createThread(ThreadFunction entryPoint, void* data) -{ - return createThread(entryPoint, data, 0); -} -#endif - int waitForThreadCompletion(ThreadIdentifier threadID, void** result) { ASSERT(threadID); @@ -208,7 +217,7 @@ void Mutex::unlock() if (pthread_mutex_unlock(&m_mutex) != 0) ASSERT(false); } - + ThreadCondition::ThreadCondition() { pthread_cond_init(&m_condition, NULL); @@ -225,28 +234,22 @@ void ThreadCondition::wait(Mutex& mutex) ASSERT(false); } -bool ThreadCondition::timedWait(Mutex& mutex, double secondsToWait) +bool ThreadCondition::timedWait(Mutex& mutex, double absoluteTime) { - if (secondsToWait < 0.0) { + if (absoluteTime < currentTime()) + return false; + + if (absoluteTime > INT_MAX) { wait(mutex); return true; } - int intervalSeconds = static_cast<int>(secondsToWait); - int intervalMicroseconds = static_cast<int>((secondsToWait - intervalSeconds) * 1000000.0); + int timeSeconds = static_cast<int>(absoluteTime); + int timeNanoseconds = static_cast<int>((absoluteTime - timeSeconds) * 1E9); - // Current time comes in sec/microsec - timeval currentTime; - gettimeofday(¤tTime, NULL); - - // Target time comes in sec/nanosec timespec targetTime; - targetTime.tv_sec = currentTime.tv_sec + intervalSeconds; - targetTime.tv_nsec = (currentTime.tv_usec + intervalMicroseconds) * 1000; - if (targetTime.tv_nsec > 1000000000) { - targetTime.tv_nsec -= 1000000000; - targetTime.tv_sec++; - } + targetTime.tv_sec = timeSeconds; + targetTime.tv_nsec = timeNanoseconds; return pthread_cond_timedwait(&m_condition, &mutex.impl(), &targetTime) == 0; } diff --git a/JavaScriptCore/wtf/ThreadingQt.cpp b/JavaScriptCore/wtf/ThreadingQt.cpp index b24f241..55a479b 100644 --- a/JavaScriptCore/wtf/ThreadingQt.cpp +++ b/JavaScriptCore/wtf/ThreadingQt.cpp @@ -29,9 +29,10 @@ #include "config.h" #include "Threading.h" +#include "CurrentTime.h" #include "HashMap.h" #include "MainThread.h" -#include "MathExtras.h" +#include "RandomNumberSeed.h" #include <QCoreApplication> #include <QMutex> @@ -64,7 +65,7 @@ void ThreadPrivate::run() } -Mutex* atomicallyInitializedStaticMutex; +static Mutex* atomicallyInitializedStaticMutex; static ThreadIdentifier mainThreadIdentifier; @@ -80,8 +81,23 @@ static HashMap<ThreadIdentifier, QThread*>& threadMap() return map; } +static ThreadIdentifier identifierByQthreadHandle(QThread*& thread) +{ + MutexLocker locker(threadMapMutex()); + + HashMap<ThreadIdentifier, QThread*>::iterator i = threadMap().begin(); + for (; i != threadMap().end(); ++i) { + if (i->second == thread) + return i->first; + } + + return 0; +} + static ThreadIdentifier establishIdentifierForThread(QThread*& thread) { + ASSERT(!identifierByQthreadHandle(thread)); + MutexLocker locker(threadMapMutex()); static ThreadIdentifier identifierCount = 1; @@ -100,19 +116,6 @@ static void clearThreadForIdentifier(ThreadIdentifier id) threadMap().remove(id); } -static ThreadIdentifier identifierByQthreadHandle(QThread*& thread) -{ - MutexLocker locker(threadMapMutex()); - - HashMap<ThreadIdentifier, QThread*>::iterator i = threadMap().begin(); - for (; i != threadMap().end(); ++i) { - if (i->second == thread) - return i->first; - } - - return 0; -} - static QThread* threadForIdentifier(ThreadIdentifier id) { MutexLocker locker(threadMapMutex()); @@ -122,10 +125,10 @@ static QThread* threadForIdentifier(ThreadIdentifier id) void initializeThreading() { - if(!atomicallyInitializedStaticMutex) { + if (!atomicallyInitializedStaticMutex) { atomicallyInitializedStaticMutex = new Mutex; threadMapMutex(); - wtf_random_init(); + initializeRandomNumberGenerator(); QThread* mainThread = QCoreApplication::instance()->thread(); mainThreadIdentifier = identifierByQthreadHandle(mainThread); if (!mainThreadIdentifier) @@ -134,7 +137,18 @@ void initializeThreading() } } -ThreadIdentifier createThread(ThreadFunction entryPoint, void* data, const char*) +void lockAtomicallyInitializedStaticMutex() +{ + ASSERT(atomicallyInitializedStaticMutex); + atomicallyInitializedStaticMutex->lock(); +} + +void unlockAtomicallyInitializedStaticMutex() +{ + atomicallyInitializedStaticMutex->unlock(); +} + +ThreadIdentifier createThreadInternal(ThreadFunction entryPoint, void* data, const char*) { ThreadPrivate* thread = new ThreadPrivate(entryPoint, data); if (!thread) { @@ -157,7 +171,8 @@ int waitForThreadCompletion(ThreadIdentifier threadID, void** result) bool res = thread->wait(); clearThreadForIdentifier(threadID); - *result = static_cast<ThreadPrivate*>(thread)->getReturnValue(); + if (result) + *result = static_cast<ThreadPrivate*>(thread)->getReturnValue(); return !res; } @@ -219,15 +234,20 @@ void ThreadCondition::wait(Mutex& mutex) m_condition->wait(mutex.impl()); } -bool ThreadCondition::timedWait(Mutex& mutex, double secondsToWait) +bool ThreadCondition::timedWait(Mutex& mutex, double absoluteTime) { - if (secondsToWait < 0.0) { - wait(mutex); - return true; - } + double currentTime = WTF::currentTime(); + + // Time is in the past - return immediately. + if (absoluteTime < currentTime) + return false; + + double intervalMilliseconds = (absoluteTime - currentTime) * 1000.0; + // Qt defines wait for up to ULONG_MAX milliseconds. + if (intervalMilliseconds >= ULONG_MAX) + intervalMilliseconds = ULONG_MAX; - unsigned long millisecondsToWait = static_cast<unsigned long>(secondsToWait * 1000.0); - return m_condition->wait(mutex.impl(), millisecondsToWait); + return m_condition->wait(mutex.impl(), static_cast<unsigned long>(intervalMilliseconds)); } void ThreadCondition::signal() diff --git a/JavaScriptCore/wtf/ThreadingWin.cpp b/JavaScriptCore/wtf/ThreadingWin.cpp index 00ad149..399fb38 100644 --- a/JavaScriptCore/wtf/ThreadingWin.cpp +++ b/JavaScriptCore/wtf/ThreadingWin.cpp @@ -1,5 +1,6 @@ /* * 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 @@ -24,56 +25,76 @@ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (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. * - * ============================================================================= - * Note: The implementation of condition variables under the Windows - * plaform was based on that of the excellent BOOST C++ library. It - * has been rewritten to fit in with the WebKit architecture and to - * use its coding conventions. - * ============================================================================= + * 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 Boost license is virtually identical to the Apple variation at the - * top of this file, but is included here for completeness: + * 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 * - * Boost Software License - Version 1.0 - August 17th, 2003 + * Contact Email: rpj@callisto.canberra.edu.au * - * 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 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 * - * 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. + * 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. * - * 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. + * 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 "MainThread.h" +#if !USE(PTHREADS) && PLATFORM(WIN_OS) +#include "ThreadSpecific.h" +#endif #include <process.h> #include <windows.h> +#include <wtf/CurrentTime.h> #include <wtf/HashMap.h> #include <wtf/MathExtras.h> - -#if PLATFORM(WIN) && USE(PTHREADS) -// Currently, Apple's Windows port uses a mixture of native and pthreads functions in FastMalloc. -// To ensure that thread-specific data is properly destroyed, we need to end each thread with pthread_exit(). -#include <pthread.h> -#endif +#include <wtf/RandomNumberSeed.h> namespace WTF { @@ -111,6 +132,7 @@ static Mutex* atomicallyInitializedStaticMutex; void lockAtomicallyInitializedStaticMutex() { + ASSERT(atomicallyInitializedStaticMutex); atomicallyInitializedStaticMutex->lock(); } @@ -132,7 +154,7 @@ void initializeThreading() if (!atomicallyInitializedStaticMutex) { atomicallyInitializedStaticMutex = new Mutex; threadMapMutex(); - wtf_random_init(); + initializeRandomNumberGenerator(); initializeMainThread(); mainThreadIdentifier = currentThread(); setThreadName(mainThreadIdentifier, "Main Thread"); @@ -148,6 +170,7 @@ static HashMap<DWORD, HANDLE>& threadMap() static void storeThreadHandleByIdentifier(DWORD threadID, HANDLE threadHandle) { MutexLocker locker(threadMapMutex()); + ASSERT(!threadMap().contains(threadID)); threadMap().add(threadID, threadHandle); } @@ -178,15 +201,15 @@ static unsigned __stdcall wtfThreadEntryPoint(void* param) void* result = invocation.function(invocation.data); -#if PLATFORM(WIN) && USE(PTHREADS) - // pthreads-win32 knows how to work with threads created with Win32 or CRT functions, so it's OK to mix APIs. - pthread_exit(result); +#if !USE(PTHREADS) && PLATFORM(WIN_OS) + // Do the TLS cleanup. + ThreadSpecificThreadExit(); #endif return reinterpret_cast<unsigned>(result); } -ThreadIdentifier createThread(ThreadFunction entryPoint, void* data, const char* threadName) +ThreadIdentifier createThreadInternal(ThreadFunction entryPoint, void* data, const char* threadName) { unsigned threadIdentifier = 0; ThreadIdentifier threadID = 0; @@ -206,13 +229,6 @@ ThreadIdentifier createThread(ThreadFunction entryPoint, void* data, const char* return threadID; } -// This function is deprecated but needs to be kept around for backward -// compatibility. Use the 3-argument version of createThread above. -ThreadIdentifier createThread(ThreadFunction entryPoint, void* data) -{ - return createThread(entryPoint, data, 0); -} - int waitForThreadCompletion(ThreadIdentifier threadID, void** result) { ASSERT(threadID); @@ -221,11 +237,11 @@ int waitForThreadCompletion(ThreadIdentifier threadID, void** result) if (!threadHandle) LOG_ERROR("ThreadIdentifier %u did not correspond to an active thread when trying to quit", threadID); - DWORD joinResult = ::WaitForSingleObject(threadHandle, INFINITE); + DWORD joinResult = WaitForSingleObject(threadHandle, INFINITE); if (joinResult == WAIT_FAILED) LOG_ERROR("ThreadIdentifier %u was found to be deadlocked trying to quit", threadID); - ::CloseHandle(threadHandle); + CloseHandle(threadHandle); clearThreadHandleForIdentifier(threadID); return joinResult; @@ -237,13 +253,13 @@ void detachThread(ThreadIdentifier threadID) HANDLE threadHandle = threadHandleForIdentifier(threadID); if (threadHandle) - ::CloseHandle(threadHandle); + CloseHandle(threadHandle); clearThreadHandleForIdentifier(threadID); } ThreadIdentifier currentThread() { - return static_cast<ThreadIdentifier>(::GetCurrentThreadId()); + return static_cast<ThreadIdentifier>(GetCurrentThreadId()); } bool isMainThread() @@ -254,17 +270,17 @@ bool isMainThread() Mutex::Mutex() { m_mutex.m_recursionCount = 0; - ::InitializeCriticalSection(&m_mutex.m_internalMutex); + InitializeCriticalSection(&m_mutex.m_internalMutex); } Mutex::~Mutex() { - ::DeleteCriticalSection(&m_mutex.m_internalMutex); + DeleteCriticalSection(&m_mutex.m_internalMutex); } void Mutex::lock() { - ::EnterCriticalSection(&m_mutex.m_internalMutex); + EnterCriticalSection(&m_mutex.m_internalMutex); ++m_mutex.m_recursionCount; } @@ -276,14 +292,14 @@ bool Mutex::tryLock() // 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); + 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); + LeaveCriticalSection(&m_mutex.m_internalMutex); return false; } @@ -297,183 +313,165 @@ bool Mutex::tryLock() void Mutex::unlock() { --m_mutex.m_recursionCount; - ::LeaveCriticalSection(&m_mutex.m_internalMutex); + LeaveCriticalSection(&m_mutex.m_internalMutex); } -static const long MaxSemaphoreCount = static_cast<long>(~0UL >> 1); - -ThreadCondition::ThreadCondition() +bool PlatformCondition::timedWait(PlatformMutex& mutex, DWORD durationMilliseconds) { - m_condition.m_timedOut = 0; - m_condition.m_blocked = 0; - m_condition.m_waitingForRemoval = 0; - m_condition.m_gate = ::CreateSemaphore(0, 1, 1, 0); - m_condition.m_queue = ::CreateSemaphore(0, 0, MaxSemaphoreCount, 0); - m_condition.m_mutex = ::CreateMutex(0, 0, 0); - - if (!m_condition.m_gate || !m_condition.m_queue || !m_condition.m_mutex) { - if (m_condition.m_gate) - ::CloseHandle(m_condition.m_gate); - if (m_condition.m_queue) - ::CloseHandle(m_condition.m_queue); - if (m_condition.m_mutex) - ::CloseHandle(m_condition.m_mutex); - } -} - -ThreadCondition::~ThreadCondition() -{ - ::CloseHandle(m_condition.m_gate); - ::CloseHandle(m_condition.m_queue); - ::CloseHandle(m_condition.m_mutex); -} - -void ThreadCondition::wait(Mutex& mutex) -{ - PlatformMutex& cs = mutex.impl(); - // Enter the wait state. - DWORD res = ::WaitForSingleObject(m_condition.m_gate, INFINITE); + DWORD res = WaitForSingleObject(m_blockLock, INFINITE); ASSERT(res == WAIT_OBJECT_0); - ++m_condition.m_blocked; - res = ::ReleaseSemaphore(m_condition.m_gate, 1, 0); + ++m_waitersBlocked; + res = ReleaseSemaphore(m_blockLock, 1, 0); ASSERT(res); - ::LeaveCriticalSection(&cs.m_internalMutex); + LeaveCriticalSection(&mutex.m_internalMutex); - res = ::WaitForSingleObject(m_condition.m_queue, INFINITE); - ASSERT(res == WAIT_OBJECT_0); + // Main wait - use timeout. + bool timedOut = (WaitForSingleObject(m_blockQueue, durationMilliseconds) == WAIT_TIMEOUT); - res = ::WaitForSingleObject(m_condition.m_mutex, INFINITE); + res = WaitForSingleObject(m_unblockLock, INFINITE); ASSERT(res == WAIT_OBJECT_0); - size_t wasWaiting = m_condition.m_waitingForRemoval; - size_t wasTimedOut = m_condition.m_timedOut; - if (wasWaiting != 0) { - if (--m_condition.m_waitingForRemoval == 0) { - if (m_condition.m_blocked != 0) { - res = ::ReleaseSemaphore(m_condition.m_gate, 1, 0); // open m_gate - ASSERT(res); - wasWaiting = 0; - } - else if (m_condition.m_timedOut != 0) - m_condition.m_timedOut = 0; - } - } else if (++m_condition.m_timedOut == ((std::numeric_limits<unsigned>::max)() / 2)) { - // timeout occured, normalize the m_condition.m_timedOut count + + 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_condition.m_gate, INFINITE); + res = WaitForSingleObject(m_blockLock, INFINITE); ASSERT(res == WAIT_OBJECT_0); - m_condition.m_blocked -= m_condition.m_timedOut; - res = ::ReleaseSemaphore(m_condition.m_gate, 1, 0); + m_waitersBlocked -= m_waitersGone; + res = ReleaseSemaphore(m_blockLock, 1, 0); ASSERT(res); - m_condition.m_timedOut = 0; + m_waitersGone = 0; } - res = ::ReleaseMutex(m_condition.m_mutex); + + res = ReleaseMutex(m_unblockLock); ASSERT(res); - if (wasWaiting == 1) { - for (/**/ ; wasTimedOut; --wasTimedOut) { - // better now than spurious later - res = ::WaitForSingleObject(m_condition.m_queue, INFINITE); - ASSERT(res == WAIT_OBJECT_0); - } - res = ::ReleaseSemaphore(m_condition.m_gate, 1, 0); + if (signalsLeft == 1) { + res = ReleaseSemaphore(m_blockLock, 1, 0); // Open the gate. ASSERT(res); } - ::EnterCriticalSection (&cs.m_internalMutex); -} + EnterCriticalSection (&mutex.m_internalMutex); -bool ThreadCondition::timedWait(Mutex& mutex, double interval) -{ - // Empty for now - ASSERT(false); - return false; + return !timedOut; } -void ThreadCondition::signal() +void PlatformCondition::signal(bool unblockAll) { - unsigned signals = 0; + unsigned signalsToIssue = 0; - DWORD res = ::WaitForSingleObject(m_condition.m_mutex, INFINITE); + DWORD res = WaitForSingleObject(m_unblockLock, INFINITE); ASSERT(res == WAIT_OBJECT_0); - if (m_condition.m_waitingForRemoval != 0) { // the m_gate is already closed - if (m_condition.m_blocked == 0) { - res = ::ReleaseMutex(m_condition.m_mutex); + if (m_waitersToUnblock) { // the gate is already closed + if (!m_waitersBlocked) { // no-op + res = ReleaseMutex(m_unblockLock); ASSERT(res); return; } - ++m_condition.m_waitingForRemoval; - --m_condition.m_blocked; - - signals = 1; - } else { - res = ::WaitForSingleObject(m_condition.m_gate, INFINITE); + 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_condition.m_blocked > m_condition.m_timedOut) { - if (m_condition.m_timedOut != 0) { - m_condition.m_blocked -= m_condition.m_timedOut; - m_condition.m_timedOut = 0; - } - signals = m_condition.m_waitingForRemoval = 1; - --m_condition.m_blocked; + if (m_waitersGone != 0) { + m_waitersBlocked -= m_waitersGone; + m_waitersGone = 0; + } + if (unblockAll) { + signalsToIssue = m_waitersBlocked; + m_waitersToUnblock = m_waitersBlocked; + m_waitersBlocked = 0; } else { - res = ::ReleaseSemaphore(m_condition.m_gate, 1, 0); - ASSERT(res); + signalsToIssue = 1; + m_waitersToUnblock = 1; + --m_waitersBlocked; } + } else { // No-op. + res = ReleaseMutex(m_unblockLock); + ASSERT(res); + return; } - res =::ReleaseMutex(m_condition.m_mutex); + res = ReleaseMutex(m_unblockLock); ASSERT(res); - if (signals) { - res = ::ReleaseSemaphore(m_condition.m_queue, signals, 0); + if (signalsToIssue) { + res = ReleaseSemaphore(m_blockQueue, signalsToIssue, 0); ASSERT(res); } } -void ThreadCondition::broadcast() +static const long MaxSemaphoreCount = static_cast<long>(~0UL >> 1); + +ThreadCondition::ThreadCondition() { - unsigned signals = 0; + 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); + } +} - DWORD res = ::WaitForSingleObject(m_condition.m_mutex, INFINITE); - ASSERT(res == WAIT_OBJECT_0); +ThreadCondition::~ThreadCondition() +{ + CloseHandle(m_condition.m_blockLock); + CloseHandle(m_condition.m_blockQueue); + CloseHandle(m_condition.m_unblockLock); +} - if (m_condition.m_waitingForRemoval != 0) { // the m_gate is already closed - if (m_condition.m_blocked == 0) { - res = ::ReleaseMutex(m_condition.m_mutex); - ASSERT(res); - return; - } +void ThreadCondition::wait(Mutex& mutex) +{ + m_condition.timedWait(mutex.impl(), INFINITE); +} - m_condition.m_waitingForRemoval += (signals = m_condition.m_blocked); - m_condition.m_blocked = 0; - } else { - res = ::WaitForSingleObject(m_condition.m_gate, INFINITE); - ASSERT(res == WAIT_OBJECT_0); - if (m_condition.m_blocked > m_condition.m_timedOut) { - if (m_condition.m_timedOut != 0) { - m_condition.m_blocked -= m_condition.m_timedOut; - m_condition.m_timedOut = 0; - } - signals = m_condition.m_waitingForRemoval = m_condition.m_blocked; - m_condition.m_blocked = 0; - } else { - res = ::ReleaseSemaphore(m_condition.m_gate, 1, 0); - ASSERT(res); - } - } +bool ThreadCondition::timedWait(Mutex& mutex, double absoluteTime) +{ + double currentTime = WTF::currentTime(); - res = ::ReleaseMutex(m_condition.m_mutex); - ASSERT(res); + // Time is in the past - return immediately. + if (absoluteTime < currentTime) + return false; - if (signals) { - res = ::ReleaseSemaphore(m_condition.m_queue, signals, 0); - ASSERT(res); - } + double intervalMilliseconds = (absoluteTime - currentTime) * 1000.0; + if (intervalMilliseconds >= INT_MAX) + intervalMilliseconds = INT_MAX; + + return m_condition.timedWait(mutex.impl(), static_cast<unsigned long>(intervalMilliseconds)); +} + +void ThreadCondition::signal() +{ + m_condition.signal(false); // Unblock only 1 thread. +} + +void ThreadCondition::broadcast() +{ + m_condition.signal(true); // Unblock all threads. } } // namespace WTF diff --git a/JavaScriptCore/wtf/Vector.h b/JavaScriptCore/wtf/Vector.h index c0bc132..880b45d 100644 --- a/JavaScriptCore/wtf/Vector.h +++ b/JavaScriptCore/wtf/Vector.h @@ -37,7 +37,7 @@ namespace WTF { using std::max; // WTF_ALIGN_OF / WTF_ALIGNED - #if COMPILER(GCC) || COMPILER(MINGW) + #if COMPILER(GCC) || COMPILER(MINGW) || COMPILER(RVCT) || COMPILER(WINSCW) #define WTF_ALIGN_OF(type) __alignof__(type) #define WTF_ALIGNED(variable_type, variable, n) variable_type variable __attribute__((__aligned__(n))) #elif COMPILER(MSVC) @@ -279,8 +279,10 @@ namespace WTF { void deallocateBuffer(T* bufferToDeallocate) { - if (m_buffer == bufferToDeallocate) + if (m_buffer == bufferToDeallocate) { m_buffer = 0; + m_capacity = 0; + } fastFree(bufferToDeallocate); } @@ -346,6 +348,8 @@ namespace WTF { std::swap(m_buffer, other.m_buffer); std::swap(m_capacity, other.m_capacity); } + + void restoreInlineBufferIfNeeded() { } using Base::allocateBuffer; using Base::deallocateBuffer; @@ -393,6 +397,14 @@ namespace WTF { return; Base::deallocateBuffer(bufferToDeallocate); } + + void restoreInlineBufferIfNeeded() + { + if (m_buffer) + return; + m_buffer = inlineBuffer(); + m_capacity = inlineCapacity; + } using Base::buffer; using Base::bufferSlot; @@ -442,7 +454,7 @@ namespace WTF { ~Vector() { - clear(); + if (m_size) shrink(0); } Vector(const Vector&); @@ -492,8 +504,9 @@ namespace WTF { void resize(size_t size); void reserveCapacity(size_t newCapacity); void shrinkCapacity(size_t newCapacity); + void shrinkToFit() { shrinkCapacity(size()); } - void clear() { if (m_size) shrink(0); } + void clear() { shrinkCapacity(0); } template<typename U> void append(const U*, size_t); template<typename U> void append(const U&); @@ -725,7 +738,8 @@ namespace WTF { if (newCapacity >= capacity()) return; - resize(min(m_size, newCapacity)); + if (newCapacity < size()) + shrink(newCapacity); T* oldBuffer = begin(); if (newCapacity > 0) { @@ -736,6 +750,7 @@ namespace WTF { } m_buffer.deallocateBuffer(oldBuffer); + m_buffer.restoreInlineBufferIfNeeded(); } // Templatizing these is better than just letting the conversion happen implicitly, diff --git a/JavaScriptCore/wtf/VectorTraits.h b/JavaScriptCore/wtf/VectorTraits.h index 71aaec8..6efe36c 100644 --- a/JavaScriptCore/wtf/VectorTraits.h +++ b/JavaScriptCore/wtf/VectorTraits.h @@ -1,6 +1,5 @@ /* - * This file is part of the KDE libraries - * Copyright (C) 2006 Apple Computer, Inc. + * 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 diff --git a/JavaScriptCore/kjs/dtoa.cpp b/JavaScriptCore/wtf/dtoa.cpp index 2dc2cff..c9e8d30 100644 --- a/JavaScriptCore/kjs/dtoa.cpp +++ b/JavaScriptCore/wtf/dtoa.cpp @@ -135,7 +135,11 @@ #include "config.h" #include "dtoa.h" +#if HAVE(ERRNO_H) #include <errno.h> +#else +#define NO_ERRNO +#endif #include <float.h> #include <math.h> #include <stdint.h> @@ -152,10 +156,7 @@ #pragma warning(disable: 4554) #endif -// ANDROID : || PLATFORM(MIDDLE_ENDIAN) added in #if statement below -// for dtoa, MIDDLE_ENDIAN needs to be same as BIG_ENDIAN according to the following site -// http://lists.debian.org/debian-arm/2003/11/msg00008.html -#if PLATFORM(BIG_ENDIAN) || PLATFORM(MIDDLE_ENDIAN) +#if PLATFORM(BIG_ENDIAN) #define IEEE_MC68k #elif PLATFORM(MIDDLE_ENDIAN) #define IEEE_ARM @@ -169,7 +170,7 @@ Exactly one of IEEE_8087, IEEE_ARM or IEEE_MC68k should be defined. #endif -namespace JSC { +namespace WTF { #if ENABLE(JSC_MULTIPLE_THREADS) Mutex* s_dtoaP5Mutex; @@ -1720,7 +1721,7 @@ retfree: Bfree(delta); ret: if (se) - *se = (char*)s; + *se = const_cast<char*>(s); return sign ? -dval(rv) : dval(rv); } @@ -2435,4 +2436,4 @@ ret1: return s0; } -} // namespace JSC +} // namespace WTF diff --git a/JavaScriptCore/kjs/dtoa.h b/JavaScriptCore/wtf/dtoa.h index 690ebc8..ed858c0 100644 --- a/JavaScriptCore/kjs/dtoa.h +++ b/JavaScriptCore/wtf/dtoa.h @@ -18,14 +18,14 @@ * */ -#ifndef KJS_dtoa_h -#define KJS_dtoa_h +#ifndef WTF_dtoa_h +#define WTF_dtoa_h namespace WTF { class Mutex; } -namespace JSC { +namespace WTF { extern WTF::Mutex* s_dtoaP5Mutex; @@ -33,6 +33,6 @@ namespace JSC { char* dtoa(double d, int ndigits, int* decpt, int* sign, char** rve); void freedtoa(char* s); -} // namespace JSC +} // namespace WTF -#endif /* KJS_dtoa_h */ +#endif // WTF_dtoa_h diff --git a/JavaScriptCore/wtf/unicode/Unicode.h b/JavaScriptCore/wtf/unicode/Unicode.h index 9cd3555..e6e8f23 100644 --- a/JavaScriptCore/wtf/unicode/Unicode.h +++ b/JavaScriptCore/wtf/unicode/Unicode.h @@ -1,6 +1,6 @@ /* - * This file is part of the KDE libraries * Copyright (C) 2006 George Staikos <staikos@kde.org> + * Copyright (C) 2006, 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 @@ -19,10 +19,10 @@ * */ -#ifndef KJS_UNICODE_H -#define KJS_UNICODE_H +#ifndef WTF_UNICODE_H +#define WTF_UNICODE_H -#include <wtf/Platform.h> +#include <wtf/Assertions.h> #if USE(QT4_UNICODE) #include "qt4/UnicodeQt4.h" @@ -32,5 +32,6 @@ #error "Unknown Unicode implementation" #endif -#endif -// vim: ts=2 sw=2 et +COMPILE_ASSERT(sizeof(UChar) == 2, UCharIsTwoBytes); + +#endif // WTF_UNICODE_H diff --git a/JavaScriptCore/wtf/unicode/icu/CollatorICU.cpp b/JavaScriptCore/wtf/unicode/icu/CollatorICU.cpp index a8bcc81..79dec79 100644 --- a/JavaScriptCore/wtf/unicode/icu/CollatorICU.cpp +++ b/JavaScriptCore/wtf/unicode/icu/CollatorICU.cpp @@ -45,7 +45,7 @@ namespace WTF { static UCollator* cachedCollator; static Mutex& cachedCollatorMutex() { - AtomicallyInitializedStatic(Mutex, mutex); + AtomicallyInitializedStatic(Mutex&, mutex = *new Mutex); return mutex; } diff --git a/JavaScriptCore/wtf/unicode/icu/UnicodeIcu.h b/JavaScriptCore/wtf/unicode/icu/UnicodeIcu.h index 7cdc55c..608aea6 100644 --- a/JavaScriptCore/wtf/unicode/icu/UnicodeIcu.h +++ b/JavaScriptCore/wtf/unicode/icu/UnicodeIcu.h @@ -1,7 +1,7 @@ /* * Copyright (C) 2006 George Staikos <staikos@kde.org> * Copyright (C) 2006 Alexey Proskuryakov <ap@nypop.com> - * Copyright (C) 2007 Apple Inc. All rights reserved. + * 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 @@ -20,8 +20,8 @@ * */ -#ifndef KJS_UNICODE_ICU_H -#define KJS_UNICODE_ICU_H +#ifndef WTF_UNICODE_ICU_H +#define WTF_UNICODE_ICU_H #include <stdlib.h> #include <unicode/uchar.h> @@ -216,4 +216,4 @@ inline int umemcasecmp(const UChar* a, const UChar* b, int len) } } -#endif +#endif // WTF_UNICODE_ICU_H diff --git a/JavaScriptCore/wtf/unicode/qt4/UnicodeQt4.h b/JavaScriptCore/wtf/unicode/qt4/UnicodeQt4.h index d285a8f..d7d78ce 100644 --- a/JavaScriptCore/wtf/unicode/qt4/UnicodeQt4.h +++ b/JavaScriptCore/wtf/unicode/qt4/UnicodeQt4.h @@ -1,6 +1,7 @@ /* * 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 @@ -19,8 +20,8 @@ * */ -#ifndef KJS_UNICODE_QT4_H -#define KJS_UNICODE_QT4_H +#ifndef WTF_UNICODE_QT4_H +#define WTF_UNICODE_QT4_H #include <QChar> #include <QString> @@ -170,7 +171,7 @@ enum CharCategory { 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), + Symbol_Other = U_MASK(QChar::Symbol_Other) }; @@ -522,4 +523,4 @@ inline CharCategory category(UChar32 c) } } -#endif +#endif // WTF_UNICODE_QT4_H diff --git a/JavaScriptCore/wtf/win/MainThreadWin.cpp b/JavaScriptCore/wtf/win/MainThreadWin.cpp index 9f05d22..5f0163c 100644 --- a/JavaScriptCore/wtf/win/MainThreadWin.cpp +++ b/JavaScriptCore/wtf/win/MainThreadWin.cpp @@ -31,7 +31,9 @@ #include "Assertions.h" #include "Threading.h" +#if !PLATFORM(WIN_CE) #include <windows.h> +#endif namespace WTF { |