Ignore:
Timestamp:
Sep 2, 2011, 10:14:04 PM (14 years ago)
Author:
[email protected]
Message:

ValueProfile does not make it safe to introspect cell values
after garbage collection
https://bugs.webkit.org/show_bug.cgi?id=67354

Reviewed by Gavin Barraclough.

ValueProfile buckets are now weak references, implemented using a
light-weight weak reference mechanism that this patch also adds (the
WeakReferenceHarvester). If a cell stored in a ValueProfile bucket
is not marked, then the bucket is transformed into a Structure
pointer. If the Structure is not marked either, then it is turned
into a ClassInfo pointer.

(JSC::CodeBlock::~CodeBlock):
(JSC::CodeBlock::visitAggregate):
(JSC::CodeBlock::visitWeakReferences):

  • bytecode/CodeBlock.h:
  • bytecode/ValueProfile.h:

(JSC::ValueProfile::ValueProfile):
(JSC::ValueProfile::classInfo):
(JSC::ValueProfile::numberOfInt32s):
(JSC::ValueProfile::numberOfDoubles):
(JSC::ValueProfile::numberOfCells):
(JSC::ValueProfile::numberOfArrays):
(JSC::ValueProfile::probabilityOfArray):
(JSC::ValueProfile::WeakBucket::WeakBucket):
(JSC::ValueProfile::WeakBucket::operator!):
(JSC::ValueProfile::WeakBucket::isEmpty):
(JSC::ValueProfile::WeakBucket::isClassInfo):
(JSC::ValueProfile::WeakBucket::isStructure):
(JSC::ValueProfile::WeakBucket::asStructure):
(JSC::ValueProfile::WeakBucket::asClassInfo):
(JSC::ValueProfile::WeakBucket::getClassInfo):

  • heap/Heap.cpp:

(JSC::Heap::harvestWeakReferences):
(JSC::Heap::markRoots):

  • heap/Heap.h:
  • heap/MarkStack.cpp:

(JSC::SlotVisitor::drain):
(JSC::SlotVisitor::harvestWeakReferences):

  • heap/MarkStack.h:

(JSC::MarkStack::addWeakReferenceHarvester):
(JSC::MarkStack::MarkStack):
(JSC::MarkStack::appendUnbarrieredPointer):

  • heap/SlotVisitor.h:
  • heap/WeakReferenceHarvester.h: Added.

(JSC::WeakReferenceHarvester::WeakReferenceHarvester):
(JSC::WeakReferenceHarvester::~WeakReferenceHarvester):

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/bytecode/ValueProfile.h

    r93466 r94477  
    3030#define ValueProfile_h
    3131
     32#include "JSArray.h"
     33#include "Structure.h"
    3234#include "WriteBarrier.h"
    3335
     
    4648    {
    4749        for (unsigned i = 0; i < numberOfBuckets; ++i)
    48             buckets[i].setWithoutWriteBarrier(JSValue());
     50            buckets[i] = JSValue::encode(JSValue());
     51    }
     52   
     53    const ClassInfo* classInfo(unsigned bucket) const
     54    {
     55        if (!!buckets[bucket]) {
     56            JSValue value = JSValue::decode(buckets[bucket]);
     57            if (!value.isCell())
     58                return 0;
     59            return value.asCell()->structure()->classInfo();
     60        }
     61        return weakBuckets[bucket].getClassInfo();
    4962    }
    5063   
     
    5366        unsigned result = 0;
    5467        for (unsigned i = 0; i < numberOfBuckets; ++i) {
    55             if (!!buckets[i])
     68            if (!!buckets[i] || !!weakBuckets[i])
    5669                result++;
    5770        }
     
    7083        unsigned result = 0;
    7184        for (unsigned i = 0; i < numberOfBuckets; ++i) {
    72             if (!!buckets[i] && buckets[i].get().isInt32())
     85            if (!!buckets[i] && JSValue::decode(buckets[i]).isInt32())
    7386                result++;
    7487        }
     
    8093        unsigned result = 0;
    8194        for (unsigned i = 0; i < numberOfBuckets; ++i) {
    82             if (!!buckets[i] && buckets[i].get().isDouble())
     95            if (!!buckets[i] && JSValue::decode(buckets[i]).isDouble())
    8396                result++;
    8497        }
     
    90103        unsigned result = 0;
    91104        for (unsigned i = 0; i < numberOfBuckets; ++i) {
    92             if (!!buckets[i] && buckets[i].get().isCell())
     105            if (!!classInfo(i))
     106                result++;
     107        }
     108        return result;
     109    }
     110   
     111    unsigned numberOfArrays() const
     112    {
     113        unsigned result = 0;
     114        for (unsigned i = 0; i < numberOfBuckets; ++i) {
     115            if (classInfo(i) == &JSArray::s_info)
    93116                result++;
    94117        }
     
    116139    }
    117140   
     141    unsigned probabilityOfArray() const
     142    {
     143        return computeProbability(numberOfArrays(), numberOfSamples());
     144    }
     145   
    118146    int bytecodeOffset; // -1 for prologue
    119     WriteBarrierBase<Unknown> buckets[numberOfBuckets];
     147    EncodedJSValue buckets[numberOfBuckets];
     148   
     149    class WeakBucket {
     150    public:
     151        WeakBucket()
     152            : m_value(0)
     153        {
     154        }
     155       
     156        WeakBucket(Structure* structure)
     157            : m_value(reinterpret_cast<uintptr_t>(structure))
     158        {
     159        }
     160       
     161        WeakBucket(const ClassInfo* classInfo)
     162            : m_value(reinterpret_cast<uintptr_t>(classInfo) | 1)
     163        {
     164        }
     165       
     166        bool operator!() const
     167        {
     168            return !m_value;
     169        }
     170       
     171        bool isEmpty() const
     172        {
     173            return !m_value;
     174        }
     175       
     176        bool isClassInfo() const
     177        {
     178            return !!(m_value & 1);
     179        }
     180       
     181        bool isStructure() const
     182        {
     183            return !isEmpty() && !isClassInfo();
     184        }
     185       
     186        Structure* asStructure() const
     187        {
     188            ASSERT(isStructure());
     189            return reinterpret_cast<Structure*>(m_value);
     190        }
     191       
     192        const ClassInfo* asClassInfo() const
     193        {
     194            ASSERT(isClassInfo());
     195            return reinterpret_cast<ClassInfo*>(m_value & ~static_cast<uintptr_t>(1));
     196        }
     197       
     198        const ClassInfo* getClassInfo() const
     199        {
     200            if (isEmpty())
     201                return 0;
     202            if (isClassInfo())
     203                return asClassInfo();
     204            return asStructure()->classInfo();
     205        }
     206       
     207    private:
     208        uintptr_t m_value;
     209    };
     210   
     211    WeakBucket weakBuckets[numberOfBuckets]; // this is not covered by a write barrier because it is only set from GC
    120212};
    121213
Note: See TracChangeset for help on using the changeset viewer.