Changeset 52956 in webkit for trunk/JavaScriptCore/runtime


Ignore:
Timestamp:
Jan 7, 2010, 4:15:05 PM (15 years ago)
Author:
[email protected]
Message:

Reviewed by Geoffrey Garen.

https://bugs.webkit.org/show_bug.cgi?id=33057
REGRESSION(r49365): typeof(xhr.responseText) != "string" in Windows

<rdar://problem/7296920> REGRESSION: WebKit fails to start PeaceKeeper benchmark

Test: fast/js/webcore-string-comparison.html

In r49365, some code was moved from JSString.cpp to JSString.h, and as a result, WebCore
got a way to directly instantiate JSStrings over DLL borders. Since vftable for JSString was
not exported, objects created from WebCore got a different vptr, and JavaScriptCore
optimizations that relied on vptr of all JSString objects being equal failed.

  • config.h: Added a JS_EXPORTCLASS macro for exporting classes. It's currently the same as JS_EXPORTDATA, but it clearly needed a new name.
  • runtime/InitializeThreading.cpp: (JSC::initializeThreadingOnce):
  • runtime/JSGlobalData.cpp: (JSC::JSGlobalData::storeVPtrs): (JSC::JSGlobalData::JSGlobalData): (JSC::JSGlobalData::createNonDefault): (JSC::JSGlobalData::create): (JSC::JSGlobalData::sharedInstance):
  • runtime/JSGlobalData.h: Store vptrs just once, no need to repeatedly pick and copy them. This makes it possible to assert vptr correctness in object destructors (which don't have access to JSGlobalData, and even Heap::heap(this) will fail for fake objects created from storeVPtrs()).
  • runtime/JSArray.cpp: (JSC::JSArray::~JSArray): Assert that vptr is what we expect it to be. It's important to assert in destructor, because MSVC changes the vptr after constructor is invoked.
  • runtime/JSByteArray.cpp: (JSC::JSByteArray::~JSByteArray): Ditto.
  • runtime/JSByteArray.h: Ditto.
  • runtime/JSFunction.h: Ditto.
  • runtime/JSFunction.cpp: (JSC::JSFunction::~JSFunction): Ditto.
  • runtime/JSCell.h: (JSC::JSCell::setVPtr): Added a method to substitute vptr for another one.
  • runtime/JSString.h: Export JSString class together with its vftable, and tell other libraries tp import it. This is needed on platforms that have a separate JavaScriptCore dynamic library - and on Mac, we already did the export via JavaScriptCore.exp. (JSC::JSString::~JSString): Assert tha vptr is what we expect it to be. (JSC::fixupVPtr): Store a previously saved primary vftable pointer (do nothing if building JavaScriptCore itself). (JSC::jsSingleCharacterString): Call fixupVPtr in case this is call across DLL boundary. (JSC::jsSingleCharacterSubstring): Ditto. (JSC::jsNontrivialString): Ditto. (JSC::jsString): Ditto. (JSC::jsSubstring): Ditto. (JSC::jsOwnedString): Ditto.
  • JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: Export the new static JSGlobalData members that are used in WebCore via inline functions.
Location:
trunk/JavaScriptCore/runtime
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/runtime/InitializeThreading.cpp

    r52791 r52956  
    5050    WTF::initializeThreading();
    5151    initializeUString();
     52    JSGlobalData::storeVPtrs();
    5253#if ENABLE(JSC_MULTIPLE_THREADS)
    5354    s_dtoaP5Mutex = new Mutex;
  • trunk/JavaScriptCore/runtime/JSArray.cpp

    r52082 r52956  
    186186JSArray::~JSArray()
    187187{
     188    ASSERT(vptr() == JSGlobalData::jsArrayVPtr);
    188189    checkConsistency(DestructorConsistencyCheck);
    189190
  • trunk/JavaScriptCore/runtime/JSByteArray.cpp

    r49721 r52956  
    4343    putDirect(exec->globalData().propertyNames->length, jsNumber(exec, m_storage->length()), ReadOnly | DontDelete);
    4444}
    45    
     45
     46#if !ASSERT_DISABLED
     47JSByteArray::~JSByteArray()
     48{
     49    ASSERT(vptr() == JSGlobalData::jsByteArrayVPtr);
     50}
     51#endif
     52
     53
    4654PassRefPtr<Structure> JSByteArray::createStructure(JSValue prototype)
    4755{
  • trunk/JavaScriptCore/runtime/JSByteArray.h

    r49721 r52956  
    3434
    3535    class JSByteArray : public JSObject {
    36         friend struct VPtrSet;
     36        friend class JSGlobalData;
    3737    public:
    3838        bool canAccessIndex(unsigned i) { return i < m_storage->length(); }
     
    9292        WTF::ByteArray* storage() const { return m_storage.get(); }
    9393
     94#if !ASSERT_DISABLED
     95        virtual ~JSByteArray();
     96#endif
     97
    9498    protected:
    9599        static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesGetPropertyNames | JSObject::StructureFlags;
  • trunk/JavaScriptCore/runtime/JSCell.h

    r52178 r52956  
    4444        friend class JSAPIValueWrapper;
    4545        friend class JSZombie;
    46         friend struct VPtrSet;
     46        friend class JSGlobalData;
    4747
    4848    private:
     
    112112        virtual JSValue getJSNumber();
    113113        void* vptr() { return *reinterpret_cast<void**>(this); }
     114        void setVPtr(void* vptr) { *reinterpret_cast<void**>(this) = vptr; }
    114115
    115116    private:
  • trunk/JavaScriptCore/runtime/JSFunction.cpp

    r48836 r52956  
    8282JSFunction::~JSFunction()
    8383{
     84    ASSERT(vptr() == JSGlobalData::jsFunctionVPtr);
     85
    8486    // JIT code for other functions may have had calls linked directly to the code for this function; these links
    8587    // are based on a check for the this pointer value for this JSFunction - which will no longer be valid once
  • trunk/JavaScriptCore/runtime/JSFunction.h

    r50232 r52956  
    3737    class JSFunction : public InternalFunction {
    3838        friend class JIT;
    39         friend struct VPtrSet;
     39        friend class JSGlobalData;
    4040
    4141        typedef InternalFunction Base;
  • trunk/JavaScriptCore/runtime/JSGlobalData.cpp

    r52856 r52956  
    7272extern JSC_CONST_HASHTABLE HashTable stringTable;
    7373
    74 struct VPtrSet {
    75     VPtrSet();
    76 
    77     void* jsArrayVPtr;
    78     void* jsByteArrayVPtr;
    79     void* jsStringVPtr;
    80     void* jsFunctionVPtr;
    81 };
    82 
    83 VPtrSet::VPtrSet()
     74void* JSGlobalData::jsArrayVPtr;
     75void* JSGlobalData::jsByteArrayVPtr;
     76void* JSGlobalData::jsStringVPtr;
     77void* JSGlobalData::jsFunctionVPtr;
     78
     79void JSGlobalData::storeVPtrs()
    8480{
    8581    CollectorCell cell;
     
    8884    COMPILE_ASSERT(sizeof(JSArray) <= sizeof(CollectorCell), sizeof_JSArray_must_be_less_than_CollectorCell);
    8985    JSCell* jsArray = new (storage) JSArray(JSArray::createStructure(jsNull()));
    90     jsArrayVPtr = jsArray->vptr();
     86    JSGlobalData::jsArrayVPtr = jsArray->vptr();
    9187    jsArray->~JSCell();
    9288
    9389    COMPILE_ASSERT(sizeof(JSByteArray) <= sizeof(CollectorCell), sizeof_JSByteArray_must_be_less_than_CollectorCell);
    9490    JSCell* jsByteArray = new (storage) JSByteArray(JSByteArray::VPtrStealingHack);
    95     jsByteArrayVPtr = jsByteArray->vptr();
     91    JSGlobalData::jsByteArrayVPtr = jsByteArray->vptr();
    9692    jsByteArray->~JSCell();
    9793
    9894    COMPILE_ASSERT(sizeof(JSString) <= sizeof(CollectorCell), sizeof_JSString_must_be_less_than_CollectorCell);
    9995    JSCell* jsString = new (storage) JSString(JSString::VPtrStealingHack);
    100     jsStringVPtr = jsString->vptr();
     96    JSGlobalData::jsStringVPtr = jsString->vptr();
    10197    jsString->~JSCell();
    10298
    10399    COMPILE_ASSERT(sizeof(JSFunction) <= sizeof(CollectorCell), sizeof_JSFunction_must_be_less_than_CollectorCell);
    104100    JSCell* jsFunction = new (storage) JSFunction(JSFunction::createStructure(jsNull()));
    105     jsFunctionVPtr = jsFunction->vptr();
     101    JSGlobalData::jsFunctionVPtr = jsFunction->vptr();
    106102    jsFunction->~JSCell();
    107103}
    108104
    109 JSGlobalData::JSGlobalData(bool isShared, const VPtrSet& vptrSet)
     105JSGlobalData::JSGlobalData(bool isShared)
    110106    : isSharedInstance(isShared)
    111107    , clientData(0)
     
    131127    , numberStructure(JSNumberCell::createStructure(jsNull()))
    132128#endif
    133     , jsArrayVPtr(vptrSet.jsArrayVPtr)
    134     , jsByteArrayVPtr(vptrSet.jsByteArrayVPtr)
    135     , jsStringVPtr(vptrSet.jsStringVPtr)
    136     , jsFunctionVPtr(vptrSet.jsFunctionVPtr)
    137129    , identifierTable(createIdentifierTable())
    138130    , propertyNames(new CommonIdentifiers(this))
     
    150142    , functionCodeBlockBeingReparsed(0)
    151143    , firstStringifierToMark(0)
    152     , markStack(vptrSet.jsArrayVPtr)
     144    , markStack(jsArrayVPtr)
    153145    , cachedUTCOffset(NaN)
    154146    , weakRandom(static_cast<int>(currentTime()))
     
    205197PassRefPtr<JSGlobalData> JSGlobalData::createNonDefault()
    206198{
    207     return adoptRef(new JSGlobalData(false, VPtrSet()));
     199    return adoptRef(new JSGlobalData(false));
    208200}
    209201
    210202PassRefPtr<JSGlobalData> JSGlobalData::create()
    211203{
    212     JSGlobalData* globalData = new JSGlobalData(false, VPtrSet());
     204    JSGlobalData* globalData = new JSGlobalData(false);
    213205    setDefaultIdentifierTable(globalData->identifierTable);
    214206    setCurrentIdentifierTable(globalData->identifierTable);
     
    233225    JSGlobalData*& instance = sharedInstanceInternal();
    234226    if (!instance) {
    235         instance = new JSGlobalData(true, VPtrSet());
     227        instance = new JSGlobalData(true);
    236228#if ENABLE(JSC_MULTIPLE_THREADS)
    237229        instance->makeUsableFromMultipleThreads();
  • trunk/JavaScriptCore/runtime/JSGlobalData.h

    r52856 r52956  
    6363    struct HashTable;
    6464    struct Instruction;   
    65     struct VPtrSet;
    6665
    6766    struct DSTOffsetCache {
     
    131130#endif
    132131
    133         void* jsArrayVPtr;
    134         void* jsByteArrayVPtr;
    135         void* jsStringVPtr;
    136         void* jsFunctionVPtr;
     132        static void storeVPtrs();
     133        static JS_EXPORTDATA void* jsArrayVPtr;
     134        static JS_EXPORTDATA void* jsByteArrayVPtr;
     135        static JS_EXPORTDATA void* jsStringVPtr;
     136        static JS_EXPORTDATA void* jsFunctionVPtr;
    137137
    138138        IdentifierTable* identifierTable;
     
    195195        void dumpSampleData(ExecState* exec);
    196196    private:
    197         JSGlobalData(bool isShared, const VPtrSet&);
     197        JSGlobalData(bool isShared);
    198198        static JSGlobalData*& sharedInstanceInternal();
    199199        void createNativeThunk();
  • trunk/JavaScriptCore/runtime/JSString.h

    r52346 r52956  
    6060    JSString* jsOwnedString(ExecState*, const UString&);
    6161
    62     class JSString : public JSCell {
     62    class JS_EXPORTCLASS JSString : public JSCell {
    6363    public:
    6464        friend class JIT;
    65         friend struct VPtrSet;
     65        friend class JSGlobalData;
    6666
    6767        // A Rope is a string composed of a set of substrings.
     
    248248        ~JSString()
    249249        {
     250            ASSERT(vptr() == JSGlobalData::jsStringVPtr);
    250251            for (unsigned i = 0; i < m_ropeLength; ++i)
    251252                m_fibers[i].deref();
     
    351352    JSString* asString(JSValue);
    352353
     354    // When an object is created from a different DLL, MSVC changes vptr to a "local" one right after invoking a constructor,
     355    // see <http://groups.google.com/group/microsoft.public.vc.language/msg/55cdcefeaf770212>.
     356    // This breaks isJSString(), and we don't need that hack anyway, so we change vptr back to primary one.
     357    // The below function must be called by any inline function that invokes a JSString constructor.
     358#if COMPILER(MSVC) && !defined(BUILDING_JavaScriptCore)
     359    inline JSString* fixupVPtr(JSGlobalData* globalData, JSString* string) { string->setVPtr(globalData->jsStringVPtr); return string; }
     360#else
     361    inline JSString* fixupVPtr(JSGlobalData*, JSString* string) { return string; }
     362#endif
     363
    353364    inline JSString* asString(JSValue value)
    354365    {
     
    366377        if (c <= 0xFF)
    367378            return globalData->smallStrings.singleCharacterString(globalData, c);
    368         return new (globalData) JSString(globalData, UString(&c, 1));
     379        return fixupVPtr(globalData, new (globalData) JSString(globalData, UString(&c, 1)));
    369380    }
    370381
     
    375386        if (c <= 0xFF)
    376387            return globalData->smallStrings.singleCharacterString(globalData, c);
    377         return new (globalData) JSString(globalData, UString(UString::Rep::create(s.rep(), offset, 1)));
     388        return fixupVPtr(globalData, new (globalData) JSString(globalData, UString(UString::Rep::create(s.rep(), offset, 1))));
    378389    }
    379390
     
    383394        ASSERT(s[0]);
    384395        ASSERT(s[1]);
    385         return new (globalData) JSString(globalData, s);
     396        return fixupVPtr(globalData, new (globalData) JSString(globalData, s));
    386397    }
    387398
     
    389400    {
    390401        ASSERT(s.size() > 1);
    391         return new (globalData) JSString(globalData, s);
     402        return fixupVPtr(globalData, new (globalData) JSString(globalData, s));
    392403    }
    393404
     
    408419                return globalData->smallStrings.singleCharacterString(globalData, c);
    409420        }
    410         return new (globalData) JSString(globalData, s);
     421        return fixupVPtr(globalData, new (globalData) JSString(globalData, s));
    411422    }
    412423
     
    423434                return globalData->smallStrings.singleCharacterString(globalData, c);
    424435        }
    425         return new (globalData) JSString(globalData, UString(UString::Rep::create(s.rep(), offset, length)), JSString::HasOtherOwner);
     436        return fixupVPtr(globalData, new (globalData) JSString(globalData, UString(UString::Rep::create(s.rep(), offset, length)), JSString::HasOtherOwner));
    426437    }
    427438
     
    436447                return globalData->smallStrings.singleCharacterString(globalData, c);
    437448        }
    438         return new (globalData) JSString(globalData, s, JSString::HasOtherOwner);
     449        return fixupVPtr(globalData, new (globalData) JSString(globalData, s, JSString::HasOtherOwner));
    439450    }
    440451
Note: See TracChangeset for help on using the changeset viewer.