Changeset 36081 in webkit for trunk/JavaScriptCore/VM/Machine.cpp


Ignore:
Timestamp:
Sep 4, 2008, 12:21:43 AM (17 years ago)
Author:
[email protected]
Message:

JavaScriptCore:

2008-09-03 Geoffrey Garen <[email protected]>

Reviewed by Cameron Zwarich.


Fixed <rdar://problem/6193925> REGRESSION: Crash occurs at
KJS::Machine::privateExecute() when attempting to load my Mobile Gallery
(http://www.me.com/gallery/#home)


also


https://bugs.webkit.org/show_bug.cgi?id=20633 Crash in privateExecute
@ cs.byu.edu


The underlying problem was that we would cache prototype properties
even if the prototype was a dictionary.


The fix is to transition a prototype back from dictionary to normal
status when an opcode caches access to it. (This is better than just
refusing to cache, since a heavily accessed prototype is almost
certainly not a true dictionary.)

  • VM/Machine.cpp: (KJS::Machine::tryCacheGetByID):
  • kjs/JSObject.h:

LayoutTests:

2008-09-04 Geoffrey Garen <[email protected]>

Reviewed by Cameron Zwarich.


Test for <rdar://problem/6193925> REGRESSION: Crash occurs at
KJS::Machine::privateExecute() when attempting to load my Mobile Gallery
(http://www.me.com/gallery/#home)


also


https://bugs.webkit.org/show_bug.cgi?id=20633 Crash in privateExecute
@ cs.byu.edu

  • fast/js/pic/dictionary-prototype-expected.txt: Added.
  • fast/js/pic/dictionary-prototype.html: Added.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/VM/Machine.cpp

    r36058 r36081  
    11961196    }
    11971197
    1198     JSCell* baseCell = static_cast<JSCell*>(baseValue);
    1199     StructureID* structureID = baseCell->structureID();
     1198    StructureID* structureID = static_cast<JSCell*>(baseValue)->structureID();
    12001199
    12011200    // FIXME: Remove this !structureID check once all JSCells have StructureIDs.
     
    12261225    // Cache hit: Specialize instruction and ref StructureIDs.
    12271226
    1228     JSValue* slotBase = slot.slotBase();
    1229     if (slotBase == baseCell) {
     1227    if (slot.slotBase() == baseValue) {
    12301228        vPC[0] = getOpcode(op_get_by_id_self);
    12311229        vPC[5] = slot.cachedOffset();
     
    12351233    }
    12361234
    1237     if (slotBase == structureID->prototype()) {
    1238         ASSERT(!JSImmediate::isImmediate(slotBase));
     1235    if (slot.slotBase() == structureID->prototype()) {
     1236        ASSERT(slot.slotBase()->isObject());
     1237
     1238        JSObject* slotBaseObject = static_cast<JSObject*>(slot.slotBase());
     1239
     1240        // Heavy access to a prototype is a good indication that it's not being
     1241        // used as a dictionary.
     1242        if (slotBaseObject->structureID()->isDictionary()) {
     1243            RefPtr<StructureID> transition = StructureID::fromDictionaryTransition(slotBaseObject->structureID());
     1244            slotBaseObject->setStructureID(transition.release());
     1245            static_cast<JSObject*>(baseValue)->structureID()->setCachedPrototypeChain(0);
     1246        }
    12391247
    12401248        vPC[0] = getOpcode(op_get_by_id_proto);
    1241         vPC[5] = static_cast<JSCell*>(slotBase)->structureID();
     1249        vPC[5] = slotBaseObject->structureID();
    12421250        vPC[6] = slot.cachedOffset();
    12431251
     
    12471255
    12481256    size_t count = 0;
    1249     while (baseCell != slotBase) {
    1250         baseCell = static_cast<JSCell*>(baseCell->structureID()->prototype());
    1251         // If we didn't find slotBase in baseCell's prototype chain, then baseCell
     1257    JSObject* o = static_cast<JSObject*>(baseValue);
     1258    while (slot.slotBase() != o) {
     1259        JSValue* v = o->structureID()->prototype();
     1260
     1261        // If we didn't find slotBase in baseValue's prototype chain, then baseValue
    12521262        // must be a proxy for another object.
    1253         if (baseCell->isNull()) {
     1263        if (v->isNull()) {
    12541264            vPC[0] = getOpcode(op_get_by_id_generic);
    12551265            return;
    12561266        }
     1267
     1268        o = static_cast<JSObject*>(v);
     1269
     1270        // Heavy access to a prototype is a good indication that it's not being
     1271        // used as a dictionary.
     1272        if (o->structureID()->isDictionary()) {
     1273            RefPtr<StructureID> transition = StructureID::fromDictionaryTransition(o->structureID());
     1274            o->setStructureID(transition.release());
     1275            static_cast<JSObject*>(baseValue)->structureID()->setCachedPrototypeChain(0);
     1276        }
     1277
    12571278        ++count;
    12581279    }
Note: See TracChangeset for help on using the changeset viewer.