2011-03-07 Oliver Hunt <oliver@apple.com>
authoroliver@apple.com <oliver@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 8 Mar 2011 23:17:32 +0000 (23:17 +0000)
committeroliver@apple.com <oliver@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 8 Mar 2011 23:17:32 +0000 (23:17 +0000)
        Reviewed by Gavin Barraclough.

        Make CodeBlock GC write barrier safe
        https://bugs.webkit.org/show_bug.cgi?id=55910

        In order to make CodeBlock WriteBarrier safe it was necessary
        to make it have a single GC owner, and for that reason I have
        made ExecutableBase a GC allocated object.  This required
        updating their creation routines as well as all sites that hold
        a reference to them.  GC objects that held Executable's have been
        converted to WriteBarriers, and all other sites now use Global<>.

        As an added benefit this gets rid of JSGlobalData's list of
        GlobalCodeBlocks.

        Perf testing shows a 0.5% progression on v8, vs. a 0.3% regression
        on SunSpider.  Given none of the tests that show regressions
        demonstrate a regression on their own, and sampling shows up nothing.
        I suspect we're just getting one or two additional gc passes at
        the end of the run.

        * bytecode/CodeBlock.cpp:
        (JSC::CodeBlock::dump):
        (JSC::CodeBlock::CodeBlock):
        (JSC::EvalCodeCache::markAggregate):
        (JSC::CodeBlock::markAggregate):
        * bytecode/CodeBlock.h:
        (JSC::CodeBlock::ownerExecutable):
        (JSC::CodeBlock::addConstant):
        (JSC::CodeBlock::constantRegister):
        (JSC::CodeBlock::getConstant):
        (JSC::CodeBlock::addFunctionDecl):
        (JSC::CodeBlock::addFunctionExpr):
        (JSC::GlobalCodeBlock::GlobalCodeBlock):
        (JSC::ExecState::r):
        * bytecode/EvalCodeCache.h:
        (JSC::EvalCodeCache::get):
        * bytecode/SamplingTool.h:
        (JSC::ScriptSampleRecord::ScriptSampleRecord):
        * bytecompiler/BytecodeGenerator.cpp:
        (JSC::BytecodeGenerator::addConstantValue):
        (JSC::BytecodeGenerator::emitEqualityOp):
        * bytecompiler/BytecodeGenerator.h:
        (JSC::BytecodeGenerator::makeFunction):
        * debugger/Debugger.cpp:
        (JSC::evaluateInGlobalCallFrame):
        * debugger/DebuggerCallFrame.cpp:
        (JSC::DebuggerCallFrame::evaluate):
        * interpreter/Interpreter.cpp:
        (JSC::Interpreter::callEval):
        * jit/JITInlineMethods.h:
        (JSC::JIT::emitLoadDouble):
        (JSC::JIT::emitLoadInt32ToDouble):
        * jit/JITStubs.cpp:
        (JSC::JITThunks::JITThunks):
        (JSC::JITThunks::hostFunctionStub):
        (JSC::JITThunks::clearHostFunctionStubs):
        * jit/JITStubs.h:
        * runtime/Completion.cpp:
        (JSC::checkSyntax):
        (JSC::evaluate):
        * runtime/Executable.cpp:
        (JSC::EvalExecutable::EvalExecutable):
        (JSC::ProgramExecutable::ProgramExecutable):
        (JSC::FunctionExecutable::FunctionExecutable):
        (JSC::FunctionExecutable::~FunctionExecutable):
        (JSC::EvalExecutable::markChildren):
        (JSC::ProgramExecutable::markChildren):
        (JSC::FunctionExecutable::markChildren):
        (JSC::FunctionExecutable::fromGlobalCode):
        * runtime/Executable.h:
        (JSC::ExecutableBase::ExecutableBase):
        (JSC::ExecutableBase::createStructure):
        (JSC::NativeExecutable::create):
        (JSC::NativeExecutable::NativeExecutable):
        (JSC::VPtrHackExecutable::VPtrHackExecutable):
        (JSC::ScriptExecutable::ScriptExecutable):
        (JSC::EvalExecutable::create):
        (JSC::EvalExecutable::createStructure):
        (JSC::ProgramExecutable::create):
        (JSC::ProgramExecutable::createStructure):
        (JSC::FunctionExecutable::create):
        (JSC::FunctionExecutable::createStructure):
        * runtime/FunctionConstructor.cpp:
        (JSC::constructFunction):
        * runtime/Heap.cpp:
        (JSC::Heap::destroy):
        (JSC::Heap::markRoots):
        * runtime/Heap.h:
        * runtime/JSActivation.cpp:
        (JSC::JSActivation::JSActivation):
        (JSC::JSActivation::markChildren):
        * runtime/JSActivation.h:
        (JSC::JSActivation::JSActivationData::JSActivationData):
        * runtime/JSCell.h:
        * runtime/JSFunction.cpp:
        (JSC::JSFunction::JSFunction):
        (JSC::JSFunction::~JSFunction):
        (JSC::JSFunction::markChildren):
        * runtime/JSFunction.h:
        * runtime/JSGlobalData.cpp:
        (JSC::JSGlobalData::storeVPtrs):
        (JSC::JSGlobalData::JSGlobalData):
        (JSC::JSGlobalData::getHostFunction):
        * runtime/JSGlobalData.h:
        * runtime/JSGlobalObjectFunctions.cpp:
        (JSC::globalFuncEval):
        * runtime/JSObject.cpp:
        * runtime/JSStaticScopeObject.cpp:
        (JSC::JSStaticScopeObject::markChildren):
        * runtime/JSStaticScopeObject.h:
        (JSC::JSStaticScopeObject::JSStaticScopeObjectData::JSStaticScopeObjectData):
        (JSC::JSStaticScopeObject::JSStaticScopeObject):
        * runtime/JSZombie.cpp:
        (JSC::JSZombie::leakedZombieStructure):
        * runtime/JSZombie.h:
        (JSC::JSZombie::createStructure):
        * runtime/MarkedSpace.h:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@80598 268f45cc-cd09-0410-ab3c-d52691b4dbfc

30 files changed:
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/bytecode/CodeBlock.cpp
Source/JavaScriptCore/bytecode/CodeBlock.h
Source/JavaScriptCore/bytecode/EvalCodeCache.h
Source/JavaScriptCore/bytecode/SamplingTool.h
Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
Source/JavaScriptCore/debugger/Debugger.cpp
Source/JavaScriptCore/debugger/DebuggerCallFrame.cpp
Source/JavaScriptCore/interpreter/Interpreter.cpp
Source/JavaScriptCore/jit/JITInlineMethods.h
Source/JavaScriptCore/jit/JITStubs.cpp
Source/JavaScriptCore/jit/JITStubs.h
Source/JavaScriptCore/runtime/Completion.cpp
Source/JavaScriptCore/runtime/Executable.cpp
Source/JavaScriptCore/runtime/Executable.h
Source/JavaScriptCore/runtime/FunctionConstructor.cpp
Source/JavaScriptCore/runtime/Heap.cpp
Source/JavaScriptCore/runtime/Heap.h
Source/JavaScriptCore/runtime/JSActivation.cpp
Source/JavaScriptCore/runtime/JSActivation.h
Source/JavaScriptCore/runtime/JSCell.h
Source/JavaScriptCore/runtime/JSFunction.cpp
Source/JavaScriptCore/runtime/JSFunction.h
Source/JavaScriptCore/runtime/JSGlobalData.cpp
Source/JavaScriptCore/runtime/JSGlobalData.h
Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp
Source/JavaScriptCore/runtime/JSStaticScopeObject.cpp
Source/JavaScriptCore/runtime/JSStaticScopeObject.h
Source/JavaScriptCore/runtime/MarkedSpace.h

index c175726..c539a7b 100644 (file)
@@ -1,3 +1,124 @@
+2011-03-07  Oliver Hunt  <oliver@apple.com>
+
+        Reviewed by Gavin Barraclough.
+
+        Make CodeBlock GC write barrier safe
+        https://bugs.webkit.org/show_bug.cgi?id=55910
+
+        In order to make CodeBlock WriteBarrier safe it was necessary
+        to make it have a single GC owner, and for that reason I have
+        made ExecutableBase a GC allocated object.  This required
+        updating their creation routines as well as all sites that hold
+        a reference to them.  GC objects that held Executable's have been
+        converted to WriteBarriers, and all other sites now use Global<>.
+
+        As an added benefit this gets rid of JSGlobalData's list of
+        GlobalCodeBlocks.
+
+        Perf testing shows a 0.5% progression on v8, vs. a 0.3% regression
+        on SunSpider.  Given none of the tests that show regressions
+        demonstrate a regression on their own, and sampling shows up nothing.
+        I suspect we're just getting one or two additional gc passes at
+        the end of the run.
+
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::dump):
+        (JSC::CodeBlock::CodeBlock):
+        (JSC::EvalCodeCache::markAggregate):
+        (JSC::CodeBlock::markAggregate):
+        * bytecode/CodeBlock.h:
+        (JSC::CodeBlock::ownerExecutable):
+        (JSC::CodeBlock::addConstant):
+        (JSC::CodeBlock::constantRegister):
+        (JSC::CodeBlock::getConstant):
+        (JSC::CodeBlock::addFunctionDecl):
+        (JSC::CodeBlock::addFunctionExpr):
+        (JSC::GlobalCodeBlock::GlobalCodeBlock):
+        (JSC::ExecState::r):
+        * bytecode/EvalCodeCache.h:
+        (JSC::EvalCodeCache::get):
+        * bytecode/SamplingTool.h:
+        (JSC::ScriptSampleRecord::ScriptSampleRecord):
+        * bytecompiler/BytecodeGenerator.cpp:
+        (JSC::BytecodeGenerator::addConstantValue):
+        (JSC::BytecodeGenerator::emitEqualityOp):
+        * bytecompiler/BytecodeGenerator.h:
+        (JSC::BytecodeGenerator::makeFunction):
+        * debugger/Debugger.cpp:
+        (JSC::evaluateInGlobalCallFrame):
+        * debugger/DebuggerCallFrame.cpp:
+        (JSC::DebuggerCallFrame::evaluate):
+        * interpreter/Interpreter.cpp:
+        (JSC::Interpreter::callEval):
+        * jit/JITInlineMethods.h:
+        (JSC::JIT::emitLoadDouble):
+        (JSC::JIT::emitLoadInt32ToDouble):
+        * jit/JITStubs.cpp:
+        (JSC::JITThunks::JITThunks):
+        (JSC::JITThunks::hostFunctionStub):
+        (JSC::JITThunks::clearHostFunctionStubs):
+        * jit/JITStubs.h:
+        * runtime/Completion.cpp:
+        (JSC::checkSyntax):
+        (JSC::evaluate):
+        * runtime/Executable.cpp:
+        (JSC::EvalExecutable::EvalExecutable):
+        (JSC::ProgramExecutable::ProgramExecutable):
+        (JSC::FunctionExecutable::FunctionExecutable):
+        (JSC::FunctionExecutable::~FunctionExecutable):
+        (JSC::EvalExecutable::markChildren):
+        (JSC::ProgramExecutable::markChildren):
+        (JSC::FunctionExecutable::markChildren):
+        (JSC::FunctionExecutable::fromGlobalCode):
+        * runtime/Executable.h:
+        (JSC::ExecutableBase::ExecutableBase):
+        (JSC::ExecutableBase::createStructure):
+        (JSC::NativeExecutable::create):
+        (JSC::NativeExecutable::NativeExecutable):
+        (JSC::VPtrHackExecutable::VPtrHackExecutable):
+        (JSC::ScriptExecutable::ScriptExecutable):
+        (JSC::EvalExecutable::create):
+        (JSC::EvalExecutable::createStructure):
+        (JSC::ProgramExecutable::create):
+        (JSC::ProgramExecutable::createStructure):
+        (JSC::FunctionExecutable::create):
+        (JSC::FunctionExecutable::createStructure):
+        * runtime/FunctionConstructor.cpp:
+        (JSC::constructFunction):
+        * runtime/Heap.cpp:
+        (JSC::Heap::destroy):
+        (JSC::Heap::markRoots):
+        * runtime/Heap.h:
+        * runtime/JSActivation.cpp:
+        (JSC::JSActivation::JSActivation):
+        (JSC::JSActivation::markChildren):
+        * runtime/JSActivation.h:
+        (JSC::JSActivation::JSActivationData::JSActivationData):
+        * runtime/JSCell.h:
+        * runtime/JSFunction.cpp:
+        (JSC::JSFunction::JSFunction):
+        (JSC::JSFunction::~JSFunction):
+        (JSC::JSFunction::markChildren):
+        * runtime/JSFunction.h:
+        * runtime/JSGlobalData.cpp:
+        (JSC::JSGlobalData::storeVPtrs):
+        (JSC::JSGlobalData::JSGlobalData):
+        (JSC::JSGlobalData::getHostFunction):
+        * runtime/JSGlobalData.h:
+        * runtime/JSGlobalObjectFunctions.cpp:
+        (JSC::globalFuncEval):
+        * runtime/JSObject.cpp:
+        * runtime/JSStaticScopeObject.cpp:
+        (JSC::JSStaticScopeObject::markChildren):
+        * runtime/JSStaticScopeObject.h:
+        (JSC::JSStaticScopeObject::JSStaticScopeObjectData::JSStaticScopeObjectData):
+        (JSC::JSStaticScopeObject::JSStaticScopeObject):
+        * runtime/JSZombie.cpp:
+        (JSC::JSZombie::leakedZombieStructure):
+        * runtime/JSZombie.h:
+        (JSC::JSZombie::createStructure):
+        * runtime/MarkedSpace.h:
+
 2011-03-07  Andy Estes  <aestes@apple.com>
 
         Reviewed by Dan Bernstein.
index 2d235df..bac3880 100644 (file)
@@ -364,7 +364,7 @@ void CodeBlock::dump(ExecState* exec) const
         unsigned registerIndex = m_numVars;
         size_t i = 0;
         do {
-            printf("   k%u = %s\n", registerIndex, valueToSourceString(exec, m_constantRegisters[i].jsValue()).utf8().data());
+            printf("   k%u = %s\n", registerIndex, valueToSourceString(exec, m_constantRegisters[i].get()).utf8().data());
             ++i;
             ++registerIndex;
         } while (i < m_constantRegisters.size());
@@ -1360,13 +1360,13 @@ void CodeBlock::dumpStatistics()
 }
 
 CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, CodeType codeType, JSGlobalObject *globalObject, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset, SymbolTable* symTab, bool isConstructor)
-    : m_globalObject(globalObject)
+    : m_globalObject(globalObject->globalData(), ownerExecutable, globalObject)
     , m_heap(&m_globalObject->globalData().heap)
     , m_numCalleeRegisters(0)
     , m_numVars(0)
     , m_numParameters(0)
     , m_isConstructor(isConstructor)
-    , m_ownerExecutable(ownerExecutable)
+    , m_ownerExecutable(globalObject->globalData(), ownerExecutable, ownerExecutable)
     , m_globalData(0)
 #ifndef NDEBUG
     , m_instructionCount(0)
@@ -1527,14 +1527,24 @@ void CodeBlock::refStructures(Instruction* vPC) const
     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 EvalCodeCache::markAggregate(MarkStack& markStack)
+{
+    EvalCacheMap::iterator end = m_cacheMap.end();
+    for (EvalCacheMap::iterator ptr = m_cacheMap.begin(); ptr != end; ++ptr)
+        markStack.append(&ptr->second);
+}
+
 void CodeBlock::markAggregate(MarkStack& markStack)
 {
-    for (size_t i = 0; i < m_constantRegisters.size(); ++i)
-        markStack.deprecatedAppend(&m_constantRegisters[i]);
+    markStack.append(&m_globalObject);
+    markStack.append(&m_ownerExecutable);
+    if (m_rareData)
+        m_rareData->m_evalCodeCache.markAggregate(markStack);
+    markStack.appendValues(m_constantRegisters.data(), m_constantRegisters.size());
     for (size_t i = 0; i < m_functionExprs.size(); ++i)
-        m_functionExprs[i]->markAggregate(markStack);
+        markStack.append(&m_functionExprs[i]);
     for (size_t i = 0; i < m_functionDecls.size(); ++i)
-        m_functionDecls[i]->markAggregate(markStack);
+        markStack.append(&m_functionDecls[i]);
 }
 
 HandlerInfo* CodeBlock::handlerForBytecodeOffset(unsigned bytecodeOffset)
index bef4561..61a2881 100644 (file)
@@ -248,7 +248,7 @@ namespace JSC {
     protected:
         CodeBlock(ScriptExecutable* ownerExecutable, CodeType, JSGlobalObject*, PassRefPtr<SourceProvider>, unsigned sourceOffset, SymbolTable* symbolTable, bool isConstructor);
 
-        DeprecatedPtr<JSGlobalObject> m_globalObject;
+        WriteBarrier<JSGlobalObject> m_globalObject;
         Heap* m_heap;
 
     public:
@@ -359,7 +359,7 @@ namespace JSC {
         ExecutablePool* executablePool() { return getJITCode().getExecutablePool(); }
 #endif
 
-        ScriptExecutable* ownerExecutable() const { return m_ownerExecutable; }
+        ScriptExecutable* ownerExecutable() const { return m_ownerExecutable.get(); }
 
         void setGlobalData(JSGlobalData* globalData) { m_globalData = globalData; }
 
@@ -472,15 +472,31 @@ namespace JSC {
         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 - FirstConstantRegisterIndex]; }
+        void addConstant(JSValue v)
+        {
+            m_constantRegisters.append(WriteBarrier<Unknown>());
+            m_constantRegisters.last().set(m_globalObject->globalData(), m_ownerExecutable.get(), v);
+        }
+        WriteBarrier<Unknown>& constantRegister(int index) { return m_constantRegisters[index - FirstConstantRegisterIndex]; }
         ALWAYS_INLINE bool isConstantRegisterIndex(int index) const { return index >= FirstConstantRegisterIndex; }
-        ALWAYS_INLINE JSValue getConstant(int index) const { return m_constantRegisters[index - FirstConstantRegisterIndex].jsValue(); }
+        ALWAYS_INLINE JSValue getConstant(int index) const { return m_constantRegisters[index - FirstConstantRegisterIndex].get(); }
 
-        unsigned addFunctionDecl(NonNullPassRefPtr<FunctionExecutable> n) { unsigned size = m_functionDecls.size(); m_functionDecls.append(n); return size; }
+        unsigned addFunctionDecl(FunctionExecutable* n)
+        {
+            unsigned size = m_functionDecls.size();
+            m_functionDecls.append(WriteBarrier<FunctionExecutable>());
+            m_functionDecls.last().set(m_globalObject->globalData(), m_ownerExecutable.get(), n);
+            return size;
+        }
         FunctionExecutable* functionDecl(int index) { return m_functionDecls[index].get(); }
         int numberOfFunctionDecls() { return m_functionDecls.size(); }
-        unsigned addFunctionExpr(NonNullPassRefPtr<FunctionExecutable> n) { unsigned size = m_functionExprs.size(); m_functionExprs.append(n); return size; }
+        unsigned addFunctionExpr(FunctionExecutable* n)
+        {
+            unsigned size = m_functionExprs.size();
+            m_functionExprs.append(WriteBarrier<FunctionExecutable>());
+            m_functionExprs.last().set(m_globalObject->globalData(), m_ownerExecutable.get(), n);
+            return size;
+        }
         FunctionExecutable* functionExpr(int index) { return m_functionExprs[index].get(); }
 
         unsigned addRegExp(RegExp* r) { createRareDataIfNecessary(); unsigned size = m_rareData->m_regexps.size(); m_rareData->m_regexps.append(r); return size; }
@@ -536,7 +552,7 @@ namespace JSC {
                 m_rareData = adoptPtr(new RareData);
         }
 
-        ScriptExecutable* m_ownerExecutable;
+        WriteBarrier<ScriptExecutable> m_ownerExecutable;
         JSGlobalData* m_globalData;
 
         Vector<Instruction> m_instructions;
@@ -574,9 +590,10 @@ namespace JSC {
 
         // Constant Pool
         Vector<Identifier> m_identifiers;
-        Vector<Register> m_constantRegisters;
-        Vector<RefPtr<FunctionExecutable> > m_functionDecls;
-        Vector<RefPtr<FunctionExecutable> > m_functionExprs;
+        COMPILE_ASSERT(sizeof(Register) == sizeof(WriteBarrier<Unknown>), Register_must_be_same_size_as_WriteBarrier_Unknown);
+        Vector<WriteBarrier<Unknown> > m_constantRegisters;
+        Vector<WriteBarrier<FunctionExecutable> > m_functionDecls;
+        Vector<WriteBarrier<FunctionExecutable> > m_functionExprs;
 
         SymbolTable* m_symbolTable;
 
@@ -617,12 +634,6 @@ namespace JSC {
         GlobalCodeBlock(ScriptExecutable* ownerExecutable, CodeType codeType, JSGlobalObject* globalObject, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset)
             : CodeBlock(ownerExecutable, codeType, globalObject, sourceProvider, sourceOffset, &m_unsharedSymbolTable, false)
         {
-            m_heap->codeBlocks().add(this);
-        }
-
-        ~GlobalCodeBlock()
-        {
-            m_heap->codeBlocks().remove(this);
         }
 
     private:
@@ -680,7 +691,7 @@ namespace JSC {
     {
         CodeBlock* codeBlock = this->codeBlock();
         if (codeBlock->isConstantRegisterIndex(index))
-            return codeBlock->constantRegister(index);
+            return *reinterpret_cast<Register*>(&codeBlock->constantRegister(index));
         return this[index];
     }
 
index edd575f..3e450b1 100644 (file)
 
 namespace JSC {
 
+    class MarkStack;
+
     class EvalCodeCache {
     public:
-        PassRefPtr<EvalExecutable> get(ExecState* exec, bool inStrictContext, const UString& evalSource, ScopeChainNode* scopeChain, JSValue& exceptionValue)
+        EvalExecutable* get(ExecState* exec, ScriptExecutable* owner, bool inStrictContext, const UString& evalSource, ScopeChainNode* scopeChain, JSValue& exceptionValue)
         {
-            RefPtr<EvalExecutable> evalExecutable;
+            EvalExecutable* evalExecutable = 0;
 
             if (!inStrictContext && evalSource.length() < maxCacheableSourceLength && (*scopeChain->begin())->isVariableObject())
-                evalExecutable = m_cacheMap.get(evalSource.impl());
+                evalExecutable = m_cacheMap.get(evalSource.impl()).get();
 
             if (!evalExecutable) {
                 evalExecutable = EvalExecutable::create(exec, makeSource(evalSource), inStrictContext);
@@ -57,19 +59,21 @@ namespace JSC {
                     return 0;
 
                 if (!inStrictContext && evalSource.length() < maxCacheableSourceLength && (*scopeChain->begin())->isVariableObject() && m_cacheMap.size() < maxCacheEntries)
-                    m_cacheMap.set(evalSource.impl(), evalExecutable);
+                    m_cacheMap.set(evalSource.impl(), WriteBarrier<EvalExecutable>(exec->globalData(), owner, evalExecutable));
             }
 
-            return evalExecutable.release();
+            return evalExecutable;
         }
 
         bool isEmpty() const { return m_cacheMap.isEmpty(); }
 
+        void markAggregate(MarkStack&);
+
     private:
         static const unsigned maxCacheableSourceLength = 256;
         static const int maxCacheEntries = 64;
 
-        typedef HashMap<RefPtr<StringImpl>, RefPtr<EvalExecutable> > EvalCacheMap;
+        typedef HashMap<RefPtr<StringImpl>, WriteBarrier<EvalExecutable> > EvalCacheMap;
         EvalCacheMap m_cacheMap;
     };
 
index 9ca54da..7c0fe3a 100644 (file)
@@ -95,8 +95,8 @@ namespace JSC {
     struct Instruction;
 
     struct ScriptSampleRecord {
-        ScriptSampleRecord(ScriptExecutable* executable)
-            : m_executable(executable)
+        ScriptSampleRecord(JSGlobalData& globalData, ScriptExecutable* executable)
+            : m_executable(globalData, executable)
             , m_codeBlock(0)
             , m_sampleCount(0)
             , m_opcodeSampleCount(0)
@@ -113,7 +113,7 @@ namespace JSC {
         
         void sample(CodeBlock*, Instruction*);
 
-        RefPtr<ScriptExecutable> m_executable;
+        Global<ScriptExecutable> m_executable;
         CodeBlock* m_codeBlock;
         int m_sampleCount;
         int m_opcodeSampleCount;
index 08f4bd4..4fd216f 100644 (file)
@@ -943,7 +943,7 @@ RegisterID* BytecodeGenerator::addConstantValue(JSValue v)
     if (result.second) {
         m_constantPoolRegisters.append(FirstConstantRegisterIndex + m_nextConstantOffset);
         ++m_nextConstantOffset;
-        m_codeBlock->addConstantRegister(JSValue(v));
+        m_codeBlock->addConstant(JSValue(v));
     } else
         index = result.first->second;
 
@@ -1026,8 +1026,8 @@ RegisterID* BytecodeGenerator::emitEqualityOp(OpcodeID opcodeID, RegisterID* dst
         if (src1->index() == dstIndex
             && src1->isTemporary()
             && m_codeBlock->isConstantRegisterIndex(src2->index())
-            && m_codeBlock->constantRegister(src2->index()).jsValue().isString()) {
-            const UString& value = asString(m_codeBlock->constantRegister(src2->index()).jsValue())->tryGetValue();
+            && m_codeBlock->constantRegister(src2->index()).get().isString()) {
+            const UString& value = asString(m_codeBlock->constantRegister(src2->index()).get())->tryGetValue();
             if (value == "undefined") {
                 rewindUnaryOp();
                 emitOpcode(op_is_undefined);
index b3851c7..5e55470 100644 (file)
@@ -483,12 +483,12 @@ namespace JSC {
         RegisterID* addConstantValue(JSValue);
         unsigned addRegExp(RegExp*);
 
-        PassRefPtr<FunctionExecutable> makeFunction(ExecState* exec, FunctionBodyNode* body)
+        FunctionExecutable* makeFunction(ExecState* exec, FunctionBodyNode* body)
         {
             return FunctionExecutable::create(exec, body->ident(), body->source(), body->usesArguments(), body->parameters(), body->isStrictMode(), body->lineNo(), body->lastLine());
         }
 
-        PassRefPtr<FunctionExecutable> makeFunction(JSGlobalData* globalData, FunctionBodyNode* body)
+        FunctionExecutable* makeFunction(JSGlobalData* globalData, FunctionBodyNode* body)
         {
             return FunctionExecutable::create(globalData, body->ident(), body->source(), body->usesArguments(), body->parameters(), body->isStrictMode(), body->lineNo(), body->lastLine());
         }
index b999446..d1c90b0 100644 (file)
@@ -118,14 +118,19 @@ void Debugger::recompileAllJSFunctions(JSGlobalData* globalData)
 JSValue evaluateInGlobalCallFrame(const UString& script, JSValue& exception, JSGlobalObject* globalObject)
 {
     CallFrame* globalCallFrame = globalObject->globalExec();
+    JSGlobalData& globalData = globalObject->globalData();
 
-    RefPtr<EvalExecutable> eval = EvalExecutable::create(globalCallFrame, makeSource(script), false);
+    EvalExecutable* eval = EvalExecutable::create(globalCallFrame, makeSource(script), false);
+    if (!eval) {
+        exception = globalData.exception.get();
+        globalData.exception = JSValue();
+        return exception;
+    }
     JSObject* error = eval->compile(globalCallFrame, globalCallFrame->scopeChain());
     if (error)
         return error;
 
-    JSGlobalData& globalData = globalObject->globalData();
-    JSValue result = globalData.interpreter->execute(eval.get(), globalCallFrame, globalObject, globalCallFrame->scopeChain());
+    JSValue result = globalData.interpreter->execute(eval, globalCallFrame, globalObject, globalCallFrame->scopeChain());
     if (globalData.exception) {
         exception = globalData.exception.get();
         globalData.exception = JSValue();
index d778bd5..4d90ed8 100644 (file)
@@ -87,14 +87,19 @@ JSValue DebuggerCallFrame::evaluate(const UString& script, JSValue& exception) c
 {
     if (!m_callFrame->codeBlock())
         return JSValue();
+    
+    JSGlobalData& globalData = m_callFrame->globalData();
+    EvalExecutable* eval = EvalExecutable::create(m_callFrame, makeSource(script), m_callFrame->codeBlock()->isStrictMode());
+    if (globalData.exception) {
+        exception = globalData.exception.get();
+        globalData.exception = JSValue();
+    }
 
-    RefPtr<EvalExecutable> eval = EvalExecutable::create(m_callFrame, makeSource(script), m_callFrame->codeBlock()->isStrictMode());
     JSObject* error = eval->compile(m_callFrame, m_callFrame->scopeChain());
     if (error)
         return error;
 
-    JSGlobalData& globalData = m_callFrame->globalData();
-    JSValue result = globalData.interpreter->execute(eval.get(), m_callFrame, thisObject(), m_callFrame->scopeChain());
+    JSValue result = globalData.interpreter->execute(eval, m_callFrame, thisObject(), m_callFrame->scopeChain());
     if (globalData.exception) {
         exception = globalData.exception.get();
         globalData.exception = JSValue();
index b9a9c40..a0d95b1 100644 (file)
@@ -409,13 +409,13 @@ NEVER_INLINE JSValue Interpreter::callEval(CallFrame* callFrame, RegisterFile* r
 
     ScopeChainNode* scopeChain = callFrame->scopeChain();
     JSValue exceptionValue;
-    RefPtr<EvalExecutable> eval = codeBlock->evalCodeCache().get(callFrame, codeBlock->isStrictMode(), programSource, scopeChain, exceptionValue);
+    EvalExecutable* eval = codeBlock->evalCodeCache().get(callFrame, codeBlock->ownerExecutable(), codeBlock->isStrictMode(), programSource, scopeChain, exceptionValue);
 
     ASSERT(!eval == exceptionValue);
     if (UNLIKELY(!eval))
         return throwError(callFrame, exceptionValue);
 
-    return callFrame->globalData().interpreter->execute(eval.get(), callFrame, callFrame->uncheckedR(codeBlock->thisRegister()).jsValue().toThisObject(callFrame), callFrame->registers() - registerFile->start() + registerOffset, scopeChain);
+    return callFrame->globalData().interpreter->execute(eval, callFrame, callFrame->uncheckedR(codeBlock->thisRegister()).jsValue().toThisObject(callFrame), callFrame->registers() - registerFile->start() + registerOffset, scopeChain);
 }
 
 Interpreter::Interpreter(JSGlobalData& globalData)
index 39ca4a5..20cfe4c 100644 (file)
@@ -396,7 +396,7 @@ inline void JIT::emitLoad2(unsigned index1, RegisterID tag1, RegisterID payload1
 inline void JIT::emitLoadDouble(unsigned index, FPRegisterID value)
 {
     if (m_codeBlock->isConstantRegisterIndex(index)) {
-        Register& inConstantPool = m_codeBlock->constantRegister(index);
+        WriteBarrier<Unknown>& inConstantPool = m_codeBlock->constantRegister(index);
         loadDouble(&inConstantPool, value);
     } else
         loadDouble(addressFor(index), value);
@@ -405,7 +405,7 @@ inline void JIT::emitLoadDouble(unsigned index, FPRegisterID value)
 inline void JIT::emitLoadInt32ToDouble(unsigned index, FPRegisterID value)
 {
     if (m_codeBlock->isConstantRegisterIndex(index)) {
-        Register& inConstantPool = m_codeBlock->constantRegister(index);
+        WriteBarrier<Unknown>& inConstantPool = m_codeBlock->constantRegister(index);
         char* bytePointer = reinterpret_cast<char*>(&inConstantPool);
         convertInt32ToDouble(AbsoluteAddress(bytePointer + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), value);
     } else
@@ -701,7 +701,7 @@ ALWAYS_INLINE void JIT::emitJumpSlowCaseIfNotJSCell(RegisterID reg, int vReg)
 inline void JIT::emitLoadDouble(unsigned index, FPRegisterID value)
 {
     if (m_codeBlock->isConstantRegisterIndex(index)) {
-        Register& inConstantPool = m_codeBlock->constantRegister(index);
+        WriteBarrier<Unknown>& inConstantPool = m_codeBlock->constantRegister(index);
         loadDouble(&inConstantPool, value);
     } else
         loadDouble(addressFor(index), value);
@@ -710,7 +710,7 @@ inline void JIT::emitLoadDouble(unsigned index, FPRegisterID value)
 inline void JIT::emitLoadInt32ToDouble(unsigned index, FPRegisterID value)
 {
     if (m_codeBlock->isConstantRegisterIndex(index)) {
-        Register& inConstantPool = m_codeBlock->constantRegister(index);
+        WriteBarrier<Unknown>& inConstantPool = m_codeBlock->constantRegister(index);
         convertInt32ToDouble(AbsoluteAddress(&inConstantPool), value);
     } else
         convertInt32ToDouble(addressFor(index), value);
index 95bf52c..ba18f0b 100644 (file)
@@ -40,6 +40,7 @@
 #include "Debugger.h"
 #include "ExceptionHelpers.h"
 #include "GetterSetter.h"
+#include "Global.h"
 #include "JIT.h"
 #include "JSActivation.h"
 #include "JSArray.h"
@@ -679,6 +680,7 @@ __asm void ctiOpThrowNotCaught()
 #endif
 
 JITThunks::JITThunks(JSGlobalData* globalData)
+    : m_hostFunctionStubMap(new HostFunctionStubMap)
 {
     if (!globalData->executableAllocator.isValid())
         return;
@@ -3483,22 +3485,27 @@ MacroAssemblerCodePtr JITThunks::ctiStub(JSGlobalData* globalData, ThunkGenerato
     return entry.first->second;
 }
 
-PassRefPtr<NativeExecutable> JITThunks::hostFunctionStub(JSGlobalData* globalData, NativeFunction function)
+NativeExecutable* JITThunks::hostFunctionStub(JSGlobalData* globalData, NativeFunction function)
 {
-    std::pair<HostFunctionStubMap::iterator, bool> entry = m_hostFunctionStubMap.add(function, 0);
+    std::pair<HostFunctionStubMap::iterator, bool> entry = m_hostFunctionStubMap->add(function, Global<NativeExecutable>(Global<NativeExecutable>::EmptyValue));
     if (entry.second)
-        entry.first->second = NativeExecutable::create(JIT::compileCTINativeCall(globalData, m_executablePool, function), function, ctiNativeConstruct(), callHostFunctionAsConstructor);
-    return entry.first->second;
+        entry.first->second.set(*globalData, NativeExecutable::create(*globalData, JIT::compileCTINativeCall(globalData, m_executablePool, function), function, ctiNativeConstruct(), callHostFunctionAsConstructor));
+    return entry.first->second.get();
 }
 
-PassRefPtr<NativeExecutable> JITThunks::hostFunctionStub(JSGlobalData* globalData, NativeFunction function, ThunkGenerator generator)
+NativeExecutable* JITThunks::hostFunctionStub(JSGlobalData* globalData, NativeFunction function, ThunkGenerator generator)
 {
-    std::pair<HostFunctionStubMap::iterator, bool> entry = m_hostFunctionStubMap.add(function, 0);
+    std::pair<HostFunctionStubMap::iterator, bool> entry = m_hostFunctionStubMap->add(function, Global<NativeExecutable>(Global<NativeExecutable>::EmptyValue));
     if (entry.second) {
         MacroAssemblerCodePtr code = globalData->canUseJIT() ? generator(globalData, m_executablePool.get()) : MacroAssemblerCodePtr();
-        entry.first->second = NativeExecutable::create(code, function, ctiNativeConstruct(), callHostFunctionAsConstructor);
+        entry.first->second.set(*globalData, NativeExecutable::create(*globalData, code, function, ctiNativeConstruct(), callHostFunctionAsConstructor));
     }
-    return entry.first->second;
+    return entry.first->second.get();
+}
+
+void JITThunks::clearHostFunctionStubs()
+{
+    m_hostFunctionStubMap.clear();
 }
 
 } // namespace JSC
index 65f6a55..af6e13f 100644 (file)
@@ -254,6 +254,8 @@ namespace JSC {
     extern "C" void ctiOpThrowNotCaught();
     extern "C" EncodedJSValue ctiTrampoline(void* code, RegisterFile*, CallFrame*, void* /*unused1*/, Profiler**, JSGlobalData*);
 
+    template <typename T> class Global;
+
     class JITThunks {
     public:
         JITThunks(JSGlobalData*);
@@ -273,13 +275,16 @@ namespace JSC {
 
         MacroAssemblerCodePtr ctiStub(JSGlobalData* globalData, ThunkGenerator generator);
 
-        PassRefPtr<NativeExecutable> hostFunctionStub(JSGlobalData* globalData, NativeFunction func);
-        PassRefPtr<NativeExecutable> hostFunctionStub(JSGlobalData* globalData, NativeFunction func, ThunkGenerator generator);
+        NativeExecutable* hostFunctionStub(JSGlobalData*, NativeFunction);
+        NativeExecutable* hostFunctionStub(JSGlobalData*, NativeFunction, ThunkGenerator);
+
+        void clearHostFunctionStubs();
+
     private:
         typedef HashMap<ThunkGenerator, MacroAssemblerCodePtr> CTIStubMap;
         CTIStubMap m_ctiStubMap;
-        typedef HashMap<NativeFunction, RefPtr<NativeExecutable> > HostFunctionStubMap;
-        HostFunctionStubMap m_hostFunctionStubMap;
+        typedef HashMap<NativeFunction, Global<NativeExecutable> > HostFunctionStubMap;
+        OwnPtr<HostFunctionStubMap> m_hostFunctionStubMap;
         RefPtr<ExecutablePool> m_executablePool;
 
         TrampolineStructure m_trampolineStructure;
index 83d8bd8..b8dcb21 100644 (file)
@@ -39,7 +39,7 @@ Completion checkSyntax(ExecState* exec, const SourceCode& source)
     JSLock lock(exec);
     ASSERT(exec->globalData().identifierTable == wtfThreadData().currentIdentifierTable());
 
-    RefPtr<ProgramExecutable> program = ProgramExecutable::create(exec, source);
+    ProgramExecutable* program = ProgramExecutable::create(exec, source);
     JSObject* error = program->checkSyntax(exec);
     if (error)
         return Completion(Throw, error);
@@ -52,14 +52,19 @@ Completion evaluate(ExecState* exec, ScopeChainNode* scopeChain, const SourceCod
     JSLock lock(exec);
     ASSERT(exec->globalData().identifierTable == wtfThreadData().currentIdentifierTable());
 
-    RefPtr<ProgramExecutable> program = ProgramExecutable::create(exec, source);
+    ProgramExecutable* program = ProgramExecutable::create(exec, source);
+    if (!program) {
+        JSValue exception = exec->globalData().exception.get();
+        exec->globalData().exception = JSValue();
+        return Completion(Throw, exception);
+    }
     JSObject* error = program->compile(exec, scopeChain);
     if (error)
         return Completion(Throw, error);
 
     JSObject* thisObj = (!thisValue || thisValue.isUndefinedOrNull()) ? exec->dynamicGlobalObject() : thisValue.toObject(exec);
 
-    JSValue result = exec->interpreter()->execute(program.get(), exec, scopeChain, thisObj);
+    JSValue result = exec->interpreter()->execute(program, exec, scopeChain, thisObj);
 
     if (exec->hadException()) {
         JSValue exception = exec->exception();
index 607a2c2..b392f26 100644 (file)
@@ -44,7 +44,7 @@ VPtrHackExecutable::~VPtrHackExecutable()
 }
 
 EvalExecutable::EvalExecutable(ExecState* exec, const SourceCode& source, bool inStrictContext)
-    : ScriptExecutable(exec, source, inStrictContext)
+    : ScriptExecutable(exec->globalData().evalExecutableStructure, exec, source, inStrictContext)
 {
 }
 
@@ -53,7 +53,7 @@ EvalExecutable::~EvalExecutable()
 }
 
 ProgramExecutable::ProgramExecutable(ExecState* exec, const SourceCode& source)
-    : ScriptExecutable(exec, source, false)
+    : ScriptExecutable(exec->globalData().programExecutableStructure, exec, source, false)
 {
 }
 
@@ -62,7 +62,7 @@ ProgramExecutable::~ProgramExecutable()
 }
 
 FunctionExecutable::FunctionExecutable(JSGlobalData* globalData, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool inStrictContext, int firstLine, int lastLine)
-    : ScriptExecutable(globalData, source, inStrictContext)
+    : ScriptExecutable(globalData->functionExecutableStructure, globalData, source, inStrictContext)
     , m_numCapturedVariables(0)
     , m_forceUsesArguments(forceUsesArguments)
     , m_parameters(parameters)
@@ -74,7 +74,7 @@ FunctionExecutable::FunctionExecutable(JSGlobalData* globalData, const Identifie
 }
 
 FunctionExecutable::FunctionExecutable(ExecState* exec, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool inStrictContext, int firstLine, int lastLine)
-    : ScriptExecutable(exec, source, inStrictContext)
+    : ScriptExecutable(exec->globalData().functionExecutableStructure, exec, source, inStrictContext)
     , m_numCapturedVariables(0)
     , m_forceUsesArguments(forceUsesArguments)
     , m_parameters(parameters)
@@ -87,6 +87,12 @@ FunctionExecutable::FunctionExecutable(ExecState* exec, const Identifier& name,
 
 FunctionExecutable::~FunctionExecutable()
 {
+#if ENABLE(JIT_OPTIMIZE_CALL)
+    if (isGeneratedForCall())
+        generatedBytecodeForCall().unlinkCallers();
+    if (isGeneratedForConstruct())
+        generatedBytecodeForConstruct().unlinkCallers();
+#endif
 }
 
 JSObject* EvalExecutable::compileInternal(ExecState* exec, ScopeChainNode* scopeChainNode)
@@ -127,6 +133,13 @@ JSObject* EvalExecutable::compileInternal(ExecState* exec, ScopeChainNode* scope
     return 0;
 }
 
+void EvalExecutable::markChildren(MarkStack& markStack)
+{
+    ScriptExecutable::markChildren(markStack);
+    if (m_evalCodeBlock)
+        m_evalCodeBlock->markAggregate(markStack);
+}
+
 JSObject* ProgramExecutable::checkSyntax(ExecState* exec)
 {
     JSObject* exception = 0;
@@ -178,6 +191,13 @@ JSObject* ProgramExecutable::compileInternal(ExecState* exec, ScopeChainNode* sc
    return 0;
 }
 
+void ProgramExecutable::markChildren(MarkStack& markStack)
+{
+    ScriptExecutable::markChildren(markStack);
+    if (m_programCodeBlock)
+        m_programCodeBlock->markAggregate(markStack);
+}
+
 JSObject* FunctionExecutable::compileForCallInternal(ExecState* exec, ScopeChainNode* scopeChainNode)
 {
     JSObject* exception = 0;
@@ -268,8 +288,9 @@ JSObject* FunctionExecutable::compileForConstructInternal(ExecState* exec, Scope
     return 0;
 }
 
-void FunctionExecutable::markAggregate(MarkStack& markStack)
+void FunctionExecutable::markChildren(MarkStack& markStack)
 {
+    ScriptExecutable::markChildren(markStack);
     if (m_codeBlockForCall)
         m_codeBlockForCall->markAggregate(markStack);
     if (m_codeBlockForConstruct)
@@ -288,7 +309,7 @@ void FunctionExecutable::discardCode()
 #endif
 }
 
-PassRefPtr<FunctionExecutable> FunctionExecutable::fromGlobalCode(const Identifier& functionName, ExecState* exec, Debugger* debugger, const SourceCode& source, JSObject** exception)
+FunctionExecutable* FunctionExecutable::fromGlobalCode(const Identifier& functionName, ExecState* exec, Debugger* debugger, const SourceCode& source, JSObject** exception)
 {
     JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject();
     RefPtr<ProgramNode> program = exec->globalData().parser->parse<ProgramNode>(lexicalGlobalObject, debugger, exec, source, 0, JSParseNormal, exception);
index b2565a0..9ca9fcb 100644 (file)
@@ -44,7 +44,7 @@ namespace JSC {
 
     struct ExceptionInfo;
 
-    class ExecutableBase : public RefCounted<ExecutableBase> {
+    class ExecutableBase : public JSCell {
         friend class JIT;
 
     protected:
@@ -52,21 +52,23 @@ namespace JSC {
         static const int NUM_PARAMETERS_NOT_COMPILED = -1;
     
     public:
-        ExecutableBase(int numParameters)
-            : m_numParametersForCall(numParameters)
+        ExecutableBase(PassRefPtr<Structure> structure, int numParameters)
+            : JSCell(structure.releaseRef())
+            , m_numParametersForCall(numParameters)
             , m_numParametersForConstruct(numParameters)
         {
         }
 
-        virtual ~ExecutableBase() {}
-
         bool isHostFunction() const
         {
             ASSERT((m_numParametersForCall == NUM_PARAMETERS_IS_HOST) == (m_numParametersForConstruct == NUM_PARAMETERS_IS_HOST));
             return m_numParametersForCall == NUM_PARAMETERS_IS_HOST;
         }
 
+        static PassRefPtr<Structure> createStructure(JSValue proto) { return Structure::create(proto, TypeInfo(CompoundType, StructureFlags), AnonymousSlotCount, 0); }
+
     protected:
+        static const unsigned StructureFlags = 0;
         int m_numParametersForCall;
         int m_numParametersForConstruct;
 
@@ -96,16 +98,16 @@ namespace JSC {
         friend class JIT;
     public:
 #if ENABLE(JIT)
-        static PassRefPtr<NativeExecutable> create(MacroAssemblerCodePtr callThunk, NativeFunction function, MacroAssemblerCodePtr constructThunk, NativeFunction constructor)
+        static NativeExecutable* create(JSGlobalData& globalData, MacroAssemblerCodePtr callThunk, NativeFunction function, MacroAssemblerCodePtr constructThunk, NativeFunction constructor)
         {
             if (!callThunk)
-                return adoptRef(new NativeExecutable(JITCode(), function, JITCode(), constructor));
-            return adoptRef(new NativeExecutable(JITCode::HostFunction(callThunk), function, JITCode::HostFunction(constructThunk), constructor));
+                return new (&globalData) NativeExecutable(globalData, JITCode(), function, JITCode(), constructor);
+            return new (&globalData) NativeExecutable(globalData, JITCode::HostFunction(callThunk), function, JITCode::HostFunction(constructThunk), constructor);
         }
 #else
-        static PassRefPtr<NativeExecutable> create(NativeFunction function, NativeFunction constructor)
+        static NativeExecutable* create(JSGlobalData& globalData, NativeFunction function, NativeFunction constructor)
         {
-            return adoptRef(new NativeExecutable(function, constructor));
+            return new (&globalData) NativeExecutable(globalData, function, constructor);
         }
 #endif
 
@@ -115,8 +117,8 @@ namespace JSC {
 
     private:
 #if ENABLE(JIT)
-        NativeExecutable(JITCode callThunk, NativeFunction function, JITCode constructThunk, NativeFunction constructor)
-            : ExecutableBase(NUM_PARAMETERS_IS_HOST)
+        NativeExecutable(JSGlobalData& globalData, JITCode callThunk, NativeFunction function, JITCode constructThunk, NativeFunction constructor)
+            : ExecutableBase(globalData.executableStructure, NUM_PARAMETERS_IS_HOST)
             , m_function(function)
             , m_constructor(constructor)
         {
@@ -126,8 +128,8 @@ namespace JSC {
             m_jitCodeForConstructWithArityCheck = constructThunk.addressForCall();
         }
 #else
-        NativeExecutable(NativeFunction function, NativeFunction constructor)
-            : ExecutableBase(NUM_PARAMETERS_IS_HOST)
+        NativeExecutable(JSGlobalData& globalData, NativeFunction function, NativeFunction constructor)
+            : ExecutableBase(globalData.executableStructure, NUM_PARAMETERS_IS_HOST)
             , m_function(function)
             , m_constructor(constructor)
         {
@@ -142,8 +144,8 @@ namespace JSC {
 
     class VPtrHackExecutable : public ExecutableBase {
     public:
-        VPtrHackExecutable()
-            : ExecutableBase(NUM_PARAMETERS_IS_HOST)
+        VPtrHackExecutable(PassRefPtr<Structure> structure)
+            : ExecutableBase(structure, NUM_PARAMETERS_IS_HOST)
         {
         }
 
@@ -152,8 +154,8 @@ namespace JSC {
 
     class ScriptExecutable : public ExecutableBase {
     public:
-        ScriptExecutable(JSGlobalData* globalData, const SourceCode& source, bool isInStrictContext)
-            : ExecutableBase(NUM_PARAMETERS_NOT_COMPILED)
+        ScriptExecutable(PassRefPtr<Structure> structure, JSGlobalData* globalData, const SourceCode& source, bool isInStrictContext)
+            : ExecutableBase(structure, NUM_PARAMETERS_NOT_COMPILED)
             , m_source(source)
             , m_features(isInStrictContext ? StrictModeFeature : 0)
         {
@@ -166,8 +168,8 @@ namespace JSC {
 #endif
         }
 
-        ScriptExecutable(ExecState* exec, const SourceCode& source, bool isInStrictContext)
-            : ExecutableBase(NUM_PARAMETERS_NOT_COMPILED)
+        ScriptExecutable(PassRefPtr<Structure> structure, ExecState* exec, const SourceCode& source, bool isInStrictContext)
+            : ExecutableBase(structure, NUM_PARAMETERS_NOT_COMPILED)
             , m_source(source)
             , m_features(isInStrictContext ? StrictModeFeature : 0)
         {
@@ -227,7 +229,7 @@ namespace JSC {
             return *m_evalCodeBlock;
         }
 
-        static PassRefPtr<EvalExecutable> create(ExecState* exec, const SourceCode& source, bool isInStrictContext) { return adoptRef(new EvalExecutable(exec, source, isInStrictContext)); }
+        static EvalExecutable* create(ExecState* exec, const SourceCode& source, bool isInStrictContext) { return new (exec) EvalExecutable(exec, source, isInStrictContext); }
 
 #if ENABLE(JIT)
         JITCode& generatedJITCode()
@@ -235,20 +237,23 @@ namespace JSC {
             return generatedJITCodeForCall();
         }
 #endif
+        static PassRefPtr<Structure> createStructure(JSValue proto) { return Structure::create(proto, TypeInfo(CompoundType, StructureFlags), AnonymousSlotCount, 0); }
 
     private:
+        static const unsigned StructureFlags = OverridesMarkChildren | ScriptExecutable::StructureFlags;
         EvalExecutable(ExecState*, const SourceCode&, bool);
 
         JSObject* compileInternal(ExecState*, ScopeChainNode*);
+        virtual void markChildren(MarkStack&);
 
         OwnPtr<EvalCodeBlock> m_evalCodeBlock;
     };
 
     class ProgramExecutable : public ScriptExecutable {
     public:
-        static PassRefPtr<ProgramExecutable> create(ExecState* exec, const SourceCode& source)
+        static ProgramExecutable* create(ExecState* exec, const SourceCode& source)
         {
-            return adoptRef(new ProgramExecutable(exec, source));
+            return new (exec) ProgramExecutable(exec, source);
         }
 
         ~ProgramExecutable();
@@ -276,11 +281,15 @@ namespace JSC {
             return generatedJITCodeForCall();
         }
 #endif
+        
+        static PassRefPtr<Structure> createStructure(JSValue proto) { return Structure::create(proto, TypeInfo(CompoundType, StructureFlags), AnonymousSlotCount, 0); }
 
     private:
+        static const unsigned StructureFlags = OverridesMarkChildren | ScriptExecutable::StructureFlags;
         ProgramExecutable(ExecState*, const SourceCode&);
 
         JSObject* compileInternal(ExecState*, ScopeChainNode*);
+        virtual void markChildren(MarkStack&);
 
         OwnPtr<ProgramCodeBlock> m_programCodeBlock;
     };
@@ -288,14 +297,14 @@ namespace JSC {
     class FunctionExecutable : public ScriptExecutable {
         friend class JIT;
     public:
-        static PassRefPtr<FunctionExecutable> create(ExecState* exec, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool isInStrictContext, int firstLine, int lastLine)
+        static FunctionExecutable* create(ExecState* exec, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool isInStrictContext, int firstLine, int lastLine)
         {
-            return adoptRef(new FunctionExecutable(exec, name, source, forceUsesArguments, parameters, isInStrictContext, firstLine, lastLine));
+            return new (exec) FunctionExecutable(exec, name, source, forceUsesArguments, parameters, isInStrictContext, firstLine, lastLine);
         }
 
-        static PassRefPtr<FunctionExecutable> create(JSGlobalData* globalData, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool isInStrictContext, int firstLine, int lastLine)
+        static FunctionExecutable* create(JSGlobalData* globalData, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool isInStrictContext, int firstLine, int lastLine)
         {
-            return adoptRef(new FunctionExecutable(globalData, name, source, forceUsesArguments, parameters, isInStrictContext, firstLine, lastLine));
+            return new (globalData) FunctionExecutable(globalData, name, source, forceUsesArguments, parameters, isInStrictContext, firstLine, lastLine);
         }
 
         ~FunctionExecutable();
@@ -363,8 +372,9 @@ namespace JSC {
         SharedSymbolTable* symbolTable() const { return m_symbolTable; }
 
         void discardCode();
-        void markAggregate(MarkStack&);
-        static PassRefPtr<FunctionExecutable> fromGlobalCode(const Identifier&, ExecState*, Debugger*, const SourceCode&, JSObject** exception);
+        void markChildren(MarkStack&);
+        static FunctionExecutable* fromGlobalCode(const Identifier&, ExecState*, Debugger*, const SourceCode&, JSObject** exception);
+        static PassRefPtr<Structure> createStructure(JSValue proto) { return Structure::create(proto, TypeInfo(CompoundType, StructureFlags), AnonymousSlotCount, 0); }
 
     private:
         FunctionExecutable(JSGlobalData*, const Identifier& name, const SourceCode&, bool forceUsesArguments, FunctionParameters*, bool, int firstLine, int lastLine);
@@ -372,7 +382,8 @@ namespace JSC {
 
         JSObject* compileForCallInternal(ExecState*, ScopeChainNode*);
         JSObject* compileForConstructInternal(ExecState*, ScopeChainNode*);
-
+        
+        static const unsigned StructureFlags = OverridesMarkChildren | ScriptExecutable::StructureFlags;
         unsigned m_numCapturedVariables : 31;
         bool m_forceUsesArguments : 1;
 
index e642594..573bd5b 100644 (file)
@@ -100,7 +100,7 @@ JSObject* constructFunction(ExecState* exec, const ArgList& args, const Identifi
     JSGlobalData& globalData = globalObject->globalData();
     SourceCode source = makeSource(program, sourceURL, lineNumber);
     JSObject* exception = 0;
-    RefPtr<FunctionExecutable> function = FunctionExecutable::fromGlobalCode(functionName, exec, exec->dynamicGlobalObject()->debugger(), source, &exception);
+    FunctionExecutable* function = FunctionExecutable::fromGlobalCode(functionName, exec, exec->dynamicGlobalObject()->debugger(), source, &exception);
     if (!function) {
         ASSERT(exception);
         return throwError(exec, exception);
index c52bcfe..1781582 100644 (file)
@@ -75,6 +75,10 @@ void Heap::destroy()
     // (and thus the global data) before other objects that may use the global data.
     RefPtr<JSGlobalData> protect(m_globalData);
 
+#if ENABLE(JIT)
+    m_globalData->jitStubs->clearHostFunctionStubs();
+#endif
+
     delete m_markListSet;
     m_markListSet = 0;
     m_markedSpace.clearMarks();
@@ -221,11 +225,6 @@ void Heap::markRoots()
     // Mark temporary vector for Array sorting
     markTempSortVectors(markStack);
     markStack.drain();
-    
-    HashSet<GlobalCodeBlock*>::const_iterator end = m_codeBlocks.end();
-    for (HashSet<GlobalCodeBlock*>::const_iterator it = m_codeBlocks.begin(); it != end; ++it)
-        (*it)->markAggregate(markStack);
-    markStack.drain();
 
     // Mark misc. other roots.
     if (m_markListSet && m_markListSet->size())
index eb8af70..40808fd 100644 (file)
@@ -92,9 +92,7 @@ namespace JSC {
 
         void pushTempSortVector(Vector<ValueStringPair>*);
         void popTempSortVector(Vector<ValueStringPair>*);
-        
-        HashSet<GlobalCodeBlock*>& codeBlocks() { return m_codeBlocks; }
-
+    
         HashSet<MarkedArgumentBuffer*>& markListSet() { if (!m_markListSet) m_markListSet = new HashSet<MarkedArgumentBuffer*>; return *m_markListSet; }
         
         template <typename Functor> void forEach(Functor&);
@@ -124,7 +122,6 @@ namespace JSC {
 
         ProtectCountSet m_protectedValues;
         Vector<Vector<ValueStringPair>* > m_tempSortingVectors;
-        HashSet<GlobalCodeBlock*> m_codeBlocks;
 
         HashSet<MarkedArgumentBuffer*>* m_markListSet;
 
index eb9c7c1..9910c09 100644 (file)
@@ -39,8 +39,8 @@ ASSERT_CLASS_FITS_IN_CELL(JSActivation);
 
 const ClassInfo JSActivation::s_info = { "JSActivation", &Base::s_info, 0, 0 };
 
-JSActivation::JSActivation(CallFrame* callFrame, NonNullPassRefPtr<FunctionExecutable> functionExecutable)
-    : Base(callFrame->globalData().activationStructure, new JSActivationData(functionExecutable, callFrame->registers()))
+JSActivation::JSActivation(CallFrame* callFrame, FunctionExecutable* functionExecutable)
+    : Base(callFrame->globalData().activationStructure, new JSActivationData(callFrame->globalData(), this, functionExecutable, callFrame->registers()))
 {
     ASSERT(inherits(&s_info));
 }
@@ -53,6 +53,7 @@ JSActivation::~JSActivation()
 void JSActivation::markChildren(MarkStack& markStack)
 {
     Base::markChildren(markStack);
+    markStack.append(&d()->functionExecutable);
 
     // No need to mark our registers if they're still in the RegisterFile.
     WriteBarrier<Unknown>* registerArray = d()->registerArray.get();
index 6e04041..27004a9 100644 (file)
@@ -42,7 +42,7 @@ namespace JSC {
     class JSActivation : public JSVariableObject {
         typedef JSVariableObject Base;
     public:
-        JSActivation(CallFrame*, NonNullPassRefPtr<FunctionExecutable>);
+        JSActivation(CallFrame*, FunctionExecutable*);
         virtual ~JSActivation();
 
         virtual void markChildren(MarkStack&);
@@ -73,9 +73,9 @@ namespace JSC {
 
     private:
         struct JSActivationData : public JSVariableObjectData {
-            JSActivationData(NonNullPassRefPtr<FunctionExecutable> _functionExecutable, Register* registers)
+            JSActivationData(JSGlobalData& globalData, JSActivation* activation, FunctionExecutable* _functionExecutable, Register* registers)
                 : JSVariableObjectData(_functionExecutable->symbolTable(), registers)
-                , functionExecutable(_functionExecutable)
+                , functionExecutable(globalData, activation, _functionExecutable)
             {
                 // We have to manually ref and deref the symbol table as JSVariableObjectData
                 // doesn't know about SharedSymbolTable
@@ -86,7 +86,7 @@ namespace JSC {
                 static_cast<SharedSymbolTable*>(symbolTable)->deref();
             }
 
-            RefPtr<FunctionExecutable> functionExecutable;
+            WriteBarrier<FunctionExecutable> functionExecutable;
         };
 
         bool symbolTableGet(const Identifier&, PropertySlot&);
index 7313d52..54ee018 100644 (file)
@@ -53,6 +53,7 @@ namespace JSC {
         WTF_MAKE_NONCOPYABLE(JSCell);
 #endif
 
+        friend class ExecutableBase;
         friend class GetterSetter;
         friend class Heap;
         friend class JIT;
index 2ade441..8e7747b 100644 (file)
@@ -56,16 +56,16 @@ bool JSFunction::isHostFunctionNonInline() const
     return isHostFunction();
 }
 
-JSFunction::JSFunction(NonNullPassRefPtr<Structure> structure)
+JSFunction::JSFunction(NonNullPassRefPtr<Structure> structure, VPtrHackExecutable* executable)
     : Base(structure)
-    , m_executable(adoptRef(new VPtrHackExecutable()))
 {
     ASSERT(inherits(&s_info));
+    m_executable.setWithoutWriteBarrier(executable);
 }
 
-JSFunction::JSFunction(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, int length, const Identifier& name, PassRefPtr<NativeExecutable> thunk)
+JSFunction::JSFunction(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, int length, const Identifier& name, NativeExecutable* thunk)
     : Base(globalObject, structure)
-    , m_executable(thunk)
+    , m_executable(exec->globalData(), this, thunk)
     , m_scopeChain(exec->globalData(), this, globalObject->globalScopeChain())
 {
     ASSERT(inherits(&s_info));
@@ -75,7 +75,7 @@ JSFunction::JSFunction(ExecState* exec, JSGlobalObject* globalObject, NonNullPas
 
 JSFunction::JSFunction(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, int length, const Identifier& name, NativeFunction func)
     : Base(globalObject, structure)
-    , m_executable(exec->globalData().getHostFunction(func))
+    , m_executable(exec->globalData(), this, exec->globalData().getHostFunction(func))
     , m_scopeChain(exec->globalData(), this, globalObject->globalScopeChain())
 {
     ASSERT(inherits(&s_info));
@@ -83,9 +83,9 @@ JSFunction::JSFunction(ExecState* exec, JSGlobalObject* globalObject, NonNullPas
     putDirect(exec->globalData(), exec->propertyNames().length, jsNumber(length), DontDelete | ReadOnly | DontEnum);
 }
 
-JSFunction::JSFunction(ExecState* exec, NonNullPassRefPtr<FunctionExecutable> executable, ScopeChainNode* scopeChainNode)
+JSFunction::JSFunction(ExecState* exec, FunctionExecutable* executable, ScopeChainNode* scopeChainNode)
     : Base(scopeChainNode->globalObject.get(), scopeChainNode->globalObject->functionStructure())
-    , m_executable(executable)
+    , m_executable(exec->globalData(), this, executable)
     , m_scopeChain(exec->globalData(), this, scopeChainNode)
 {
     ASSERT(inherits(&s_info));
@@ -96,19 +96,6 @@ JSFunction::JSFunction(ExecState* exec, NonNullPassRefPtr<FunctionExecutable> ex
 JSFunction::~JSFunction()
 {
     ASSERT(vptr() == JSGlobalData::jsFunctionVPtr);
-
-    // 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 (!isHostFunction()) {
-#if ENABLE(JIT_OPTIMIZE_CALL)
-        ASSERT(m_executable);
-        if (jsExecutable()->isGeneratedForCall())
-            jsExecutable()->generatedBytecodeForCall().unlinkCallers();
-        if (jsExecutable()->isGeneratedForConstruct())
-            jsExecutable()->generatedBytecodeForConstruct().unlinkCallers();
-#endif
-    }
 }
 
 static const char* StrictModeCallerAccessError = "Cannot access caller property of a strict mode function";
@@ -148,8 +135,8 @@ const UString JSFunction::calculatedDisplayName(ExecState* exec)
 void JSFunction::markChildren(MarkStack& markStack)
 {
     Base::markChildren(markStack);
+    markStack.append(&m_executable);
     if (!isHostFunction()) {
-        jsExecutable()->markAggregate(markStack);
         markStack.append(&m_scopeChain);
     }
 }
index 089f42e..6bc3e83 100644 (file)
@@ -34,6 +34,7 @@ namespace JSC {
     class JSActivation;
     class JSGlobalObject;
     class NativeExecutable;
+    class VPtrHackExecutable;
 
     EncodedJSValue JSC_HOST_CALL callHostFunctionAsConstructor(ExecState*);
 
@@ -45,8 +46,8 @@ namespace JSC {
 
     public:
         JSFunction(ExecState*, JSGlobalObject*, NonNullPassRefPtr<Structure>, int length, const Identifier&, NativeFunction);
-        JSFunction(ExecState*, JSGlobalObject*, NonNullPassRefPtr<Structure>, int length, const Identifier&, PassRefPtr<NativeExecutable>);
-        JSFunction(ExecState*, NonNullPassRefPtr<FunctionExecutable>, ScopeChainNode*);
+        JSFunction(ExecState*, JSGlobalObject*, NonNullPassRefPtr<Structure>, int length, const Identifier&, NativeExecutable*);
+        JSFunction(ExecState*, FunctionExecutable*, ScopeChainNode*);
         virtual ~JSFunction();
 
         const UString& name(ExecState*);
@@ -86,7 +87,7 @@ namespace JSC {
         const static unsigned StructureFlags = OverridesGetOwnPropertySlot | ImplementsHasInstance | OverridesMarkChildren | OverridesGetPropertyNames | JSObject::StructureFlags;
 
     private:
-        JSFunction(NonNullPassRefPtr<Structure>);
+        JSFunction(NonNullPassRefPtr<Structure>, VPtrHackExecutable*);
 
         bool isHostFunctionNonInline() const;
 
@@ -102,7 +103,7 @@ namespace JSC {
         static JSValue callerGetter(ExecState*, JSValue, const Identifier&);
         static JSValue lengthGetter(ExecState*, JSValue, const Identifier&);
 
-        RefPtr<ExecutableBase> m_executable;
+        WriteBarrier<ExecutableBase> m_executable;
         WriteBarrier<ScopeChainNode> m_scopeChain;
     };
 
index e25040c..af444d5 100644 (file)
@@ -107,7 +107,9 @@ void JSGlobalData::storeVPtrs()
     jsString->~JSCell();
 
     COMPILE_ASSERT(sizeof(JSFunction) <= sizeof(storage), sizeof_JSFunction_must_be_less_than_storage);
-    JSCell* jsFunction = new (storage) JSFunction(JSFunction::createStructure(jsNull()));
+    char executableStorage[sizeof(VPtrHackExecutable)];
+    VPtrHackExecutable* executable = new (executableStorage) VPtrHackExecutable(VPtrHackExecutable::createStructure(jsNull()));
+    JSCell* jsFunction = new (storage) JSFunction(JSFunction::createStructure(jsNull()), executable);
     JSGlobalData::jsFunctionVPtr = jsFunction->vptr();
     jsFunction->~JSCell();
 }
@@ -135,6 +137,10 @@ JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType thread
     , getterSetterStructure(GetterSetter::createStructure(jsNull()))
     , apiWrapperStructure(JSAPIValueWrapper::createStructure(jsNull()))
     , scopeChainNodeStructure(ScopeChainNode::createStructure(jsNull()))
+    , executableStructure(ExecutableBase::createStructure(jsNull()))
+    , evalExecutableStructure(EvalExecutable::createStructure(jsNull()))
+    , programExecutableStructure(ProgramExecutable::createStructure(jsNull()))
+    , functionExecutableStructure(FunctionExecutable::createStructure(jsNull()))
     , dummyMarkableCellStructure(JSCell::createDummyStructure())
     , identifierTable(globalDataType == Default ? wtfThreadData().currentIdentifierTable() : createIdentifierTable())
     , propertyNames(new CommonIdentifiers(this))
@@ -282,18 +288,18 @@ JSGlobalData*& JSGlobalData::sharedInstanceInternal()
 }
 
 #if ENABLE(JIT)
-PassRefPtr<NativeExecutable> JSGlobalData::getHostFunction(NativeFunction function)
+NativeExecutable* JSGlobalData::getHostFunction(NativeFunction function)
 {
     return jitStubs->hostFunctionStub(this, function);
 }
-PassRefPtr<NativeExecutable> JSGlobalData::getHostFunction(NativeFunction function, ThunkGenerator generator)
+NativeExecutable* JSGlobalData::getHostFunction(NativeFunction function, ThunkGenerator generator)
 {
     return jitStubs->hostFunctionStub(this, function, generator);
 }
 #else
-PassRefPtr<NativeExecutable> JSGlobalData::getHostFunction(NativeFunction function)
+NativeExecutable* JSGlobalData::getHostFunction(NativeFunction function)
 {
-    return NativeExecutable::create(function, callHostFunctionAsConstructor);
+    return NativeExecutable::create(*this, function, callHostFunctionAsConstructor);
 }
 #endif
 
index ee3e067..553233d 100644 (file)
@@ -155,6 +155,10 @@ namespace JSC {
         RefPtr<Structure> getterSetterStructure;
         RefPtr<Structure> apiWrapperStructure;
         RefPtr<Structure> scopeChainNodeStructure;
+        RefPtr<Structure> executableStructure;
+        RefPtr<Structure> evalExecutableStructure;
+        RefPtr<Structure> programExecutableStructure;
+        RefPtr<Structure> functionExecutableStructure;
         RefPtr<Structure> dummyMarkableCellStructure;
 
         static void storeVPtrs();
@@ -199,9 +203,9 @@ namespace JSC {
         {
             return jitStubs->ctiStub(this, generator);
         }
-        PassRefPtr<NativeExecutable> getHostFunction(NativeFunction, ThunkGenerator);
+        NativeExecutable* getHostFunction(NativeFunction, ThunkGenerator);
 #endif
-        PassRefPtr<NativeExecutable> getHostFunction(NativeFunction);
+        NativeExecutable* getHostFunction(NativeFunction);
 
         TimeoutChecker timeoutChecker;
         Terminator terminator;
index de1300a..f0da773 100644 (file)
@@ -449,12 +449,12 @@ EncodedJSValue JSC_HOST_CALL globalFuncEval(ExecState* exec)
     if (JSValue parsedObject = preparser.tryLiteralParse())
         return JSValue::encode(parsedObject);
 
-    RefPtr<EvalExecutable> eval = EvalExecutable::create(exec, makeSource(s), false);
+    EvalExecutable* eval = EvalExecutable::create(exec, makeSource(s), false);
     JSObject* error = eval->compile(exec, static_cast<JSGlobalObject*>(unwrappedObject)->globalScopeChain());
     if (error)
         return throwVMError(exec, error);
 
-    return JSValue::encode(exec->interpreter()->execute(eval.get(), exec, thisObject, static_cast<JSGlobalObject*>(unwrappedObject)->globalScopeChain()));
+    return JSValue::encode(exec->interpreter()->execute(eval, exec, thisObject, static_cast<JSGlobalObject*>(unwrappedObject)->globalScopeChain()));
 }
 
 EncodedJSValue JSC_HOST_CALL globalFuncParseInt(ExecState* exec)
index 727ac28..0cabaef 100644 (file)
@@ -34,7 +34,7 @@ ASSERT_CLASS_FITS_IN_CELL(JSStaticScopeObject);
 void JSStaticScopeObject::markChildren(MarkStack& markStack)
 {
     JSVariableObject::markChildren(markStack);
-    markStack.deprecatedAppend(&d()->registerStore);
+    markStack.append(&d()->registerStore);
 }
 
 JSObject* JSStaticScopeObject::toThisObject(ExecState* exec) const
index b3c0695..c6ac75a 100644 (file)
@@ -35,18 +35,18 @@ namespace JSC{
         using JSVariableObject::JSVariableObjectData;
         struct JSStaticScopeObjectData : public JSVariableObjectData {
             JSStaticScopeObjectData()
-                : JSVariableObjectData(&symbolTable, &registerStore + 1)
+                : JSVariableObjectData(&symbolTable, reinterpret_cast<Register*>(&registerStore + 1))
             {
             }
             SymbolTable symbolTable;
-            Register registerStore;
+            WriteBarrier<Unknown> registerStore;
         };
         
     public:
         JSStaticScopeObject(ExecState* exec, const Identifier& ident, JSValue value, unsigned attributes)
             : JSVariableObject(exec->globalData().staticScopeStructure, new JSStaticScopeObjectData())
         {
-            d()->registerStore = value;
+            d()->registerStore.set(exec->globalData(), this, value);
             symbolTable().add(ident.impl(), SymbolTableEntry(-1, attributes));
         }
         virtual ~JSStaticScopeObject();
index 2e88887..1090fe2 100644 (file)
@@ -33,7 +33,7 @@
 #include <wtf/Vector.h>
 
 #define ASSERT_CLASS_FITS_IN_CELL(class) COMPILE_ASSERT(sizeof(class) <= MarkedSpace::maxCellSize, class_fits_in_cell)
-#define ASSERT_CLASS_FILLS_CELL(class) COMPILE_ASSERT(sizeof(class) == MarkedSpace::maxCellSize, class_fills_cell)
+#define ASSERT_CLASS_FILLS_CELL(class) COMPILE_ASSERT((sizeof(class) <= MarkedSpace::maxCellSize) && !(sizeof(class) & (sizeof(class) - 1)), class_fills_cell)
 
 namespace JSC {
 
@@ -48,7 +48,7 @@ namespace JSC {
         WTF_MAKE_NONCOPYABLE(MarkedSpace);
     public:
         // Currently public for use in assertions.
-        static const size_t maxCellSize = 64;
+        static const size_t maxCellSize = 256;
 
         static Heap* heap(JSCell*);