Getting the instruction stream for a code block should not require two loads
https://bugs.webkit.org/show_bug.cgi?id=79608

Reviewed by Sam Weinig.
        
Introduced the RefCountedArray class, which contains a single inline pointer
to a ref-counted non-resizeable vector backing store. This satisfies the
requirements of CodeBlock, which desires the ability to share instruction
streams with other CodeBlocks. It also reduces the number of loads required
for getting the instruction stream by one.
        
This patch also gets rid of the bytecode discarding logic, since we don't
use it anymore and it's unlikely to ever work right with DFG or LLInt. And
I didn't feel like porting dead code to use RefCountedArray.

* GNUmakefile.list.am:
* JavaScriptCore.xcodeproj/project.pbxproj:
* bytecode/CodeBlock.cpp:
(JSC::instructionOffsetForNth):
(JSC::CodeBlock::dump):
(JSC::CodeBlock::CodeBlock):
(JSC::CodeBlock::finalizeUnconditionally):
(JSC::CodeBlock::handlerForBytecodeOffset):
(JSC::CodeBlock::lineNumberForBytecodeOffset):
(JSC::CodeBlock::expressionRangeForBytecodeOffset):
(JSC::CodeBlock::shrinkToFit):
* bytecode/CodeBlock.h:
(CodeBlock):
(JSC::CodeBlock::numberOfInstructions):
(JSC::CodeBlock::instructions):
(JSC::CodeBlock::instructionCount):
(JSC::CodeBlock::valueProfileForBytecodeOffset):
(JSC):
* bytecompiler/BytecodeGenerator.cpp:
(JSC::Label::setLocation):
(JSC):
(JSC::BytecodeGenerator::generate):
(JSC::BytecodeGenerator::newLabel):
* bytecompiler/BytecodeGenerator.h:
(JSC):
(BytecodeGenerator):
(JSC::BytecodeGenerator::instructions):
* bytecompiler/Label.h:
(JSC::Label::Label):
(Label):
* dfg/DFGByteCodeCache.h:
(JSC::DFG::ByteCodeCache::~ByteCodeCache):
(JSC::DFG::ByteCodeCache::get):
* jit/JITExceptions.cpp:
(JSC::genericThrow):
* llint/LowLevelInterpreter32_64.asm:
* runtime/Executable.cpp:
(JSC::EvalExecutable::compileInternal):
(JSC::ProgramExecutable::compileInternal):
(JSC::FunctionExecutable::codeBlockWithBytecodeFor):
(JSC::FunctionExecutable::produceCodeBlockFor):
* wtf/RefCountedArray.h: Added.
(WTF):
(RefCountedArray):
(WTF::RefCountedArray::RefCountedArray):
(WTF::RefCountedArray::operator=):
(WTF::RefCountedArray::~RefCountedArray):
(WTF::RefCountedArray::size):
(WTF::RefCountedArray::data):
(WTF::RefCountedArray::begin):
(WTF::RefCountedArray::end):
(WTF::RefCountedArray::at):
(WTF::RefCountedArray::operator[]):
(Header):
(WTF::RefCountedArray::Header::size):
(WTF::RefCountedArray::Header::payload):
(WTF::RefCountedArray::Header::fromPayload):
* wtf/Platform.h:



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@108943 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog
index 49e55ba..5309949 100644
--- a/Source/JavaScriptCore/ChangeLog
+++ b/Source/JavaScriptCore/ChangeLog
@@ -1,3 +1,79 @@
+2012-02-26  Filip Pizlo  <fpizlo@apple.com>
+
+        Getting the instruction stream for a code block should not require two loads
+        https://bugs.webkit.org/show_bug.cgi?id=79608
+
+        Reviewed by Sam Weinig.
+        
+        Introduced the RefCountedArray class, which contains a single inline pointer
+        to a ref-counted non-resizeable vector backing store. This satisfies the
+        requirements of CodeBlock, which desires the ability to share instruction
+        streams with other CodeBlocks. It also reduces the number of loads required
+        for getting the instruction stream by one.
+        
+        This patch also gets rid of the bytecode discarding logic, since we don't
+        use it anymore and it's unlikely to ever work right with DFG or LLInt. And
+        I didn't feel like porting dead code to use RefCountedArray.
+
+        * GNUmakefile.list.am:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * bytecode/CodeBlock.cpp:
+        (JSC::instructionOffsetForNth):
+        (JSC::CodeBlock::dump):
+        (JSC::CodeBlock::CodeBlock):
+        (JSC::CodeBlock::finalizeUnconditionally):
+        (JSC::CodeBlock::handlerForBytecodeOffset):
+        (JSC::CodeBlock::lineNumberForBytecodeOffset):
+        (JSC::CodeBlock::expressionRangeForBytecodeOffset):
+        (JSC::CodeBlock::shrinkToFit):
+        * bytecode/CodeBlock.h:
+        (CodeBlock):
+        (JSC::CodeBlock::numberOfInstructions):
+        (JSC::CodeBlock::instructions):
+        (JSC::CodeBlock::instructionCount):
+        (JSC::CodeBlock::valueProfileForBytecodeOffset):
+        (JSC):
+        * bytecompiler/BytecodeGenerator.cpp:
+        (JSC::Label::setLocation):
+        (JSC):
+        (JSC::BytecodeGenerator::generate):
+        (JSC::BytecodeGenerator::newLabel):
+        * bytecompiler/BytecodeGenerator.h:
+        (JSC):
+        (BytecodeGenerator):
+        (JSC::BytecodeGenerator::instructions):
+        * bytecompiler/Label.h:
+        (JSC::Label::Label):
+        (Label):
+        * dfg/DFGByteCodeCache.h:
+        (JSC::DFG::ByteCodeCache::~ByteCodeCache):
+        (JSC::DFG::ByteCodeCache::get):
+        * jit/JITExceptions.cpp:
+        (JSC::genericThrow):
+        * llint/LowLevelInterpreter32_64.asm:
+        * runtime/Executable.cpp:
+        (JSC::EvalExecutable::compileInternal):
+        (JSC::ProgramExecutable::compileInternal):
+        (JSC::FunctionExecutable::codeBlockWithBytecodeFor):
+        (JSC::FunctionExecutable::produceCodeBlockFor):
+        * wtf/RefCountedArray.h: Added.
+        (WTF):
+        (RefCountedArray):
+        (WTF::RefCountedArray::RefCountedArray):
+        (WTF::RefCountedArray::operator=):
+        (WTF::RefCountedArray::~RefCountedArray):
+        (WTF::RefCountedArray::size):
+        (WTF::RefCountedArray::data):
+        (WTF::RefCountedArray::begin):
+        (WTF::RefCountedArray::end):
+        (WTF::RefCountedArray::at):
+        (WTF::RefCountedArray::operator[]):
+        (Header):
+        (WTF::RefCountedArray::Header::size):
+        (WTF::RefCountedArray::Header::payload):
+        (WTF::RefCountedArray::Header::fromPayload):
+        * wtf/Platform.h:
+
 2012-02-26  Yusuke Suzuki  <utatane.tea@gmail.com>
 
         StringLiteral and NumericLiteral are allowed as ObjectLiteral getter / setter name
diff --git a/Source/JavaScriptCore/GNUmakefile.list.am b/Source/JavaScriptCore/GNUmakefile.list.am
index 898703a..1eea784 100644
--- a/Source/JavaScriptCore/GNUmakefile.list.am
+++ b/Source/JavaScriptCore/GNUmakefile.list.am
@@ -583,6 +583,7 @@
 	Source/JavaScriptCore/wtf/ByteArray.h \
 	Source/JavaScriptCore/wtf/CheckedArithmetic.h \
 	Source/JavaScriptCore/wtf/CheckedBoolean.h \
+	Source/JavaScriptCore/wtf/RefCountedArray.h \
 	Source/JavaScriptCore/wtf/Compiler.h \
 	Source/JavaScriptCore/wtf/Complex.h \
 	Source/JavaScriptCore/wtf/CryptographicallyRandomNumber.cpp \
diff --git a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj b/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
index 2794ec9..0d643c7 100644
--- a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
+++ b/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
@@ -143,6 +143,7 @@
 		0FB5467914F5C46B002C2989 /* LazyOperandValueProfile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FB5467814F5C468002C2989 /* LazyOperandValueProfile.cpp */; };
 		0FB5467B14F5C7E1002C2989 /* MethodOfGettingAValueProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FB5467A14F5C7D4002C2989 /* MethodOfGettingAValueProfile.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		0FB5467D14F5CFD6002C2989 /* MethodOfGettingAValueProfile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FB5467C14F5CFD3002C2989 /* MethodOfGettingAValueProfile.cpp */; };
+		0FB5469014FADA7B002C2989 /* RefCountedArray.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FB5468E14FADA6F002C2989 /* RefCountedArray.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		0FBC0AE71496C7C400D4FBDD /* DFGExitProfile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FBC0AE41496C7C100D4FBDD /* DFGExitProfile.cpp */; };
 		0FBC0AE81496C7C700D4FBDD /* DFGExitProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FBC0AE51496C7C100D4FBDD /* DFGExitProfile.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		0FBD7E691447999600481315 /* CodeOrigin.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FBD7E671447998F00481315 /* CodeOrigin.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -1008,6 +1009,7 @@
 		0FB5467814F5C468002C2989 /* LazyOperandValueProfile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LazyOperandValueProfile.cpp; sourceTree = "<group>"; };
 		0FB5467A14F5C7D4002C2989 /* MethodOfGettingAValueProfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MethodOfGettingAValueProfile.h; sourceTree = "<group>"; };
 		0FB5467C14F5CFD3002C2989 /* MethodOfGettingAValueProfile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MethodOfGettingAValueProfile.cpp; sourceTree = "<group>"; };
+		0FB5468E14FADA6F002C2989 /* RefCountedArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RefCountedArray.h; sourceTree = "<group>"; };
 		0FBC0AE41496C7C100D4FBDD /* DFGExitProfile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DFGExitProfile.cpp; sourceTree = "<group>"; };
 		0FBC0AE51496C7C100D4FBDD /* DFGExitProfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DFGExitProfile.h; sourceTree = "<group>"; };
 		0FBD7E671447998F00481315 /* CodeOrigin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeOrigin.h; sourceTree = "<group>"; };
@@ -2204,6 +2206,7 @@
 				A7A1F7AB0F252B3C00E184E2 /* ByteArray.h */,
 				A7BC0C81140608B000B1BB71 /* CheckedArithmetic.h */,
 				C2D9CA1214BCC04600304B46 /* CheckedBoolean.h */,
+				0FB5468E14FADA6F002C2989 /* RefCountedArray.h */,
 				BC66BAE213F4928F00C23FAE /* Compiler.h */,
 				FDA15C1612B03028003A583A /* Complex.h */,
 				97941A7C1302A098004A3447 /* CryptographicallyRandomNumber.cpp */,
@@ -3401,6 +3404,7 @@
 				1497209114EB831500FEB1B7 /* PassWeak.h in Headers */,
 				0FB5467714F59B5C002C2989 /* LazyOperandValueProfile.h in Headers */,
 				0FB5467B14F5C7E1002C2989 /* MethodOfGettingAValueProfile.h in Headers */,
+				0FB5469014FADA7B002C2989 /* RefCountedArray.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
diff --git a/Source/JavaScriptCore/bytecode/CodeBlock.cpp b/Source/JavaScriptCore/bytecode/CodeBlock.cpp
index ab89ad9..30f1305 100644
--- a/Source/JavaScriptCore/bytecode/CodeBlock.cpp
+++ b/Source/JavaScriptCore/bytecode/CodeBlock.cpp
@@ -226,7 +226,7 @@
     }
 }
 
-static unsigned instructionOffsetForNth(ExecState* exec, const Vector<Instruction>& instructions, int nth, bool (*predicate)(OpcodeID))
+static unsigned instructionOffsetForNth(ExecState* exec, const RefCountedArray<Instruction>& instructions, int nth, bool (*predicate)(OpcodeID))
 {
     size_t i = 0;
     while (i < instructions.size()) {
@@ -347,18 +347,13 @@
 
 void CodeBlock::dump(ExecState* exec) const
 {
-    if (!m_instructions) {
-        dataLog("No instructions available.\n");
-        return;
-    }
-
     size_t instructionCount = 0;
 
     for (size_t i = 0; i < instructions().size(); i += opcodeLengths[exec->interpreter()->getOpcodeID(instructions()[i].u.opcode)])
         ++instructionCount;
 
     dataLog("%lu m_instructions; %lu bytes at %p; %d parameter(s); %d callee register(s); %d variable(s)\n\n",
-        static_cast<unsigned long>(instructionCount),
+        static_cast<unsigned long>(instructions().size()),
         static_cast<unsigned long>(instructions().size() * sizeof(Instruction)),
         this, m_numParameters, m_numCalleeRegisters, m_numVars);
 
@@ -1424,11 +1419,9 @@
     , m_numVars(other.m_numVars)
     , m_numCapturedVars(other.m_numCapturedVars)
     , m_isConstructor(other.m_isConstructor)
-    , m_shouldDiscardBytecode(false)
     , m_ownerExecutable(*other.m_globalData, other.m_ownerExecutable.get(), other.m_ownerExecutable.get())
     , m_globalData(other.m_globalData)
     , m_instructions(other.m_instructions)
-    , m_instructionCount(other.m_instructionCount)
     , m_thisRegister(other.m_thisRegister)
     , m_argumentsRegister(other.m_argumentsRegister)
     , m_activationRegister(other.m_activationRegister)
@@ -1484,12 +1477,9 @@
     , m_numCalleeRegisters(0)
     , m_numVars(0)
     , m_isConstructor(isConstructor)
-    , m_shouldDiscardBytecode(false)
     , m_numParameters(0)
     , m_ownerExecutable(globalObject->globalData(), ownerExecutable, ownerExecutable)
     , m_globalData(0)
-    , m_instructions(adoptRef(new Instructions))
-    , m_instructionCount(0)
     , m_argumentsRegister(-1)
     , m_needsFullScopeChain(ownerExecutable->needsActivation())
     , m_usesEval(ownerExecutable->usesEval())
@@ -1903,12 +1893,6 @@
         }
     }
 #endif
-
-    // Handle the bytecode discarding chore.
-    if (m_shouldDiscardBytecode) {
-        discardBytecode();
-        m_shouldDiscardBytecode = false;
-    }
 }
 
 void CodeBlock::stronglyVisitStrongReferences(SlotVisitor& visitor)
@@ -1980,7 +1964,7 @@
 
 HandlerInfo* CodeBlock::handlerForBytecodeOffset(unsigned bytecodeOffset)
 {
-    ASSERT(bytecodeOffset < m_instructionCount);
+    ASSERT(bytecodeOffset < instructions().size());
 
     if (!m_rareData)
         return 0;
@@ -1998,7 +1982,7 @@
 
 int CodeBlock::lineNumberForBytecodeOffset(unsigned bytecodeOffset)
 {
-    ASSERT(bytecodeOffset < m_instructionCount);
+    ASSERT(bytecodeOffset < instructions().size());
 
     if (!m_rareData)
         return m_ownerExecutable->source().firstLine();
@@ -2022,7 +2006,7 @@
 
 void CodeBlock::expressionRangeForBytecodeOffset(unsigned bytecodeOffset, int& divot, int& startOffset, int& endOffset)
 {
-    ASSERT(bytecodeOffset < m_instructionCount);
+    ASSERT(bytecodeOffset < instructions().size());
 
     if (!m_rareData) {
         startOffset = 0;
@@ -2102,8 +2086,6 @@
 
 void CodeBlock::shrinkToFit()
 {
-    instructions().shrinkToFit();
-
 #if ENABLE(CLASSIC_INTERPRETER)
     m_propertyAccessInstructions.shrinkToFit();
     m_globalResolveInstructions.shrinkToFit();
diff --git a/Source/JavaScriptCore/bytecode/CodeBlock.h b/Source/JavaScriptCore/bytecode/CodeBlock.h
index 195aa62..f7bb651 100644
--- a/Source/JavaScriptCore/bytecode/CodeBlock.h
+++ b/Source/JavaScriptCore/bytecode/CodeBlock.h
@@ -61,6 +61,7 @@
 #include "UString.h"
 #include "UnconditionalFinalizer.h"
 #include "ValueProfile.h"
+#include <wtf/RefCountedArray.h>
 #include <wtf/FastAllocBase.h>
 #include <wtf/PassOwnPtr.h>
 #include <wtf/RefPtr.h>
@@ -127,8 +128,6 @@
         }
 #endif
         
-        bool canProduceCopyWithBytecode() { return hasInstructions(); }
-
         void visitAggregate(SlotVisitor&);
 
         static void dumpStatistics();
@@ -341,20 +340,13 @@
         void setIsNumericCompareFunction(bool isNumericCompareFunction) { m_isNumericCompareFunction = isNumericCompareFunction; }
         bool isNumericCompareFunction() { return m_isNumericCompareFunction; }
 
-        bool hasInstructions() const { return !!m_instructions; }
-        unsigned numberOfInstructions() const { return !m_instructions ? 0 : m_instructions->m_instructions.size(); }
-        Vector<Instruction>& instructions() { return m_instructions->m_instructions; }
-        const Vector<Instruction>& instructions() const { return m_instructions->m_instructions; }
-        void discardBytecode() { m_instructions.clear(); }
-        void discardBytecodeLater()
-        {
-            m_shouldDiscardBytecode = true;
-        }
+        unsigned numberOfInstructions() const { return m_instructions.size(); }
+        RefCountedArray<Instruction>& instructions() { return m_instructions; }
+        const RefCountedArray<Instruction>& instructions() const { return m_instructions; }
         
         bool usesOpcode(OpcodeID);
 
-        unsigned instructionCount() { return m_instructionCount; }
-        void setInstructionCount(unsigned instructionCount) { m_instructionCount = instructionCount; }
+        unsigned instructionCount() { return m_instructions.size(); }
 
 #if ENABLE(JIT)
         void setJITCode(const JITCode& code, MacroAssemblerCodePtr codeWithArityCheck)
@@ -541,11 +533,10 @@
         {
             ValueProfile* result = WTF::genericBinarySearch<ValueProfile, int, getValueProfileBytecodeOffset>(m_valueProfiles, m_valueProfiles.size(), bytecodeOffset);
             ASSERT(result->m_bytecodeOffset != -1);
-            ASSERT(!hasInstructions()
-                   || instructions()[bytecodeOffset + opcodeLength(
-                           m_globalData->interpreter->getOpcodeID(
-                               instructions()[
-                                   bytecodeOffset].u.opcode)) - 1].u.profile == result);
+            ASSERT(instructions()[bytecodeOffset + opcodeLength(
+                       m_globalData->interpreter->getOpcodeID(
+                           instructions()[
+                               bytecodeOffset].u.opcode)) - 1].u.profile == result);
             return result;
         }
         PredictedType valueProfilePredictionForBytecodeOffset(int bytecodeOffset)
@@ -1047,9 +1038,6 @@
         int m_numCapturedVars;
         bool m_isConstructor;
 
-        // This is public because otherwise we would have many friends.
-        bool m_shouldDiscardBytecode;
-
     protected:
 #if ENABLE(JIT)
         virtual void jitCompileImpl(JSGlobalData&) = 0;
@@ -1115,11 +1103,7 @@
         WriteBarrier<ScriptExecutable> m_ownerExecutable;
         JSGlobalData* m_globalData;
 
-        struct Instructions : public RefCounted<Instructions> {
-            Vector<Instruction> m_instructions;
-        };
-        RefPtr<Instructions> m_instructions;
-        unsigned m_instructionCount;
+        RefCountedArray<Instruction> m_instructions;
 
         int m_thisRegister;
         int m_argumentsRegister;
@@ -1379,27 +1363,6 @@
 #endif
     };
 
-    // Use this if you want to copy a code block and you're paranoid about a GC
-    // happening.
-    class BytecodeDestructionBlocker {
-    public:
-        BytecodeDestructionBlocker(CodeBlock* codeBlock)
-            : m_codeBlock(codeBlock)
-            , m_oldValueOfShouldDiscardBytecode(codeBlock->m_shouldDiscardBytecode)
-        {
-            codeBlock->m_shouldDiscardBytecode = false;
-        }
-        
-        ~BytecodeDestructionBlocker()
-        {
-            m_codeBlock->m_shouldDiscardBytecode = m_oldValueOfShouldDiscardBytecode;
-        }
-        
-    private:
-        CodeBlock* m_codeBlock;
-        bool m_oldValueOfShouldDiscardBytecode;
-    };
-
     inline CodeBlock* baselineCodeBlockForOriginAndBaselineCodeBlock(const CodeOrigin& codeOrigin, CodeBlock* baselineCodeBlock)
     {
         if (codeOrigin.inlineCallFrame) {
diff --git a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
index 6fa0ce9..4a6f465 100644
--- a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
+++ b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
@@ -119,6 +119,15 @@
     expected by the callee.
 */
 
+void Label::setLocation(unsigned location)
+{
+    m_location = location;
+    
+    unsigned size = m_unresolvedJumps.size();
+    for (unsigned i = 0; i < size; ++i)
+        m_generator->m_instructions[m_unresolvedJumps[i].second].u.operand = m_location - m_unresolvedJumps[i].first;
+}
+
 #ifndef NDEBUG
 void ResolveResult::checkValidity()
 {
@@ -171,8 +180,8 @@
     m_codeBlock->setThisRegister(m_thisRegister.index());
 
     m_scopeNode->emitBytecode(*this);
-
-    m_codeBlock->setInstructionCount(m_codeBlock->instructions().size());
+    
+    m_codeBlock->instructions() = RefCountedArray<Instruction>(m_instructions);
 
     if (s_dumpsGeneratedCode)
         m_codeBlock->dump(m_scopeChain->globalObject->globalExec());
@@ -607,7 +616,7 @@
         m_labels.removeLast();
 
     // Allocate new label ID.
-    m_labels.append(m_codeBlock);
+    m_labels.append(this);
     return &m_labels.last();
 }
 
diff --git a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
index d61b42b..c44812c 100644
--- a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
+++ b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
@@ -48,6 +48,7 @@
 namespace JSC {
 
     class Identifier;
+    class Label;
     class ScopeChainNode;
 
     class CallArguments {
@@ -532,6 +533,8 @@
         ScopeChainNode* scopeChain() const { return m_scopeChain.get(); }
 
     private:
+        friend class Label;
+        
         void emitOpcode(OpcodeID);
         ValueProfile* emitProfiledOpcode(OpcodeID);
         void retrieveLastBinaryOp(int& dstIndex, int& src1Index, int& src2Index);
@@ -611,7 +614,7 @@
 
         RegisterID* emitInitLazyRegister(RegisterID*);
 
-        Vector<Instruction>& instructions() { return m_codeBlock->instructions(); }
+        Vector<Instruction>& instructions() { return m_instructions; }
         SymbolTable& symbolTable() { return *m_symbolTable; }
 
         bool shouldOptimizeLocals()
@@ -644,6 +647,8 @@
         void createArgumentsIfNecessary();
         void createActivationIfNecessary();
         RegisterID* createLazyRegisterIfNecessary(RegisterID*);
+        
+        Vector<Instruction> m_instructions;
 
         bool m_shouldEmitDebugHooks;
         bool m_shouldEmitProfileHooks;
diff --git a/Source/JavaScriptCore/bytecompiler/Label.h b/Source/JavaScriptCore/bytecompiler/Label.h
index 8cab1db..21fa463 100644
--- a/Source/JavaScriptCore/bytecompiler/Label.h
+++ b/Source/JavaScriptCore/bytecompiler/Label.h
@@ -39,21 +39,14 @@
 
     class Label {
     public:
-        explicit Label(CodeBlock* codeBlock)
+        explicit Label(BytecodeGenerator* generator)
             : m_refCount(0)
             , m_location(invalidLocation)
-            , m_codeBlock(codeBlock)
+            , m_generator(generator)
         {
         }
 
-        void setLocation(unsigned location)
-        {
-            m_location = location;
-
-            unsigned size = m_unresolvedJumps.size();
-            for (unsigned i = 0; i < size; ++i)
-                m_codeBlock->instructions()[m_unresolvedJumps[i].second].u.operand = m_location - m_unresolvedJumps[i].first;
-        }
+        void setLocation(unsigned);
 
         int bind(int opcode, int offset) const
         {
@@ -81,7 +74,7 @@
 
         int m_refCount;
         unsigned m_location;
-        CodeBlock* m_codeBlock;
+        BytecodeGenerator* m_generator;
         mutable JumpVector m_unresolvedJumps;
     };
 
diff --git a/Source/JavaScriptCore/dfg/DFGByteCodeCache.h b/Source/JavaScriptCore/dfg/DFGByteCodeCache.h
index fd3b514..f6a745c 100644
--- a/Source/JavaScriptCore/dfg/DFGByteCodeCache.h
+++ b/Source/JavaScriptCore/dfg/DFGByteCodeCache.h
@@ -138,7 +138,6 @@
                 delete iter->second.codeBlock;
                 continue;
             }
-            iter->second.codeBlock->m_shouldDiscardBytecode = iter->second.oldValueOfShouldDiscardBytecode;
         }
     }
     
@@ -155,7 +154,6 @@
         value.codeBlock = key.executable()->codeBlockWithBytecodeFor(key.kind());
         if (value.codeBlock) {
             value.owned = false;
-            value.oldValueOfShouldDiscardBytecode = value.codeBlock->m_shouldDiscardBytecode;
         } else {
             // Nope, so try to parse one.
             JSObject* exception;
@@ -171,13 +169,6 @@
             value.codeBlock = 0;
         }
         
-        // If we're about to return a code block, make sure that we're not going
-        // to be discarding its bytecode if a GC were to happen during DFG
-        // compilation. That's unlikely, but it's good to thoroughly enjoy this
-        // kind of paranoia.
-        if (!!value.codeBlock)
-            value.codeBlock->m_shouldDiscardBytecode = false;
-        
         m_map.add(key, value);
         
         return value.codeBlock;
diff --git a/Source/JavaScriptCore/jit/JITExceptions.cpp b/Source/JavaScriptCore/jit/JITExceptions.cpp
index 2edd340..ab11807 100644
--- a/Source/JavaScriptCore/jit/JITExceptions.cpp
+++ b/Source/JavaScriptCore/jit/JITExceptions.cpp
@@ -48,8 +48,7 @@
     Instruction* catchPCForInterpreter = 0;
     if (handler) {
         catchRoutine = handler->nativeCode.executableAddress();
-        if (callFrame->codeBlock()->hasInstructions())
-            catchPCForInterpreter = &callFrame->codeBlock()->instructions()[handler->target];
+        catchPCForInterpreter = &callFrame->codeBlock()->instructions()[handler->target];
     } else
         catchRoutine = FunctionPtr(ctiOpThrowNotCaught).value();
     
diff --git a/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm b/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm
index ba49fe3..2c3aa7d 100644
--- a/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm
+++ b/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm
@@ -443,8 +443,7 @@
     codeBlockSetter(t1)
     
     # Set up the PC.
-    loadp CodeBlock::m_instructions[t1], t0
-    loadp CodeBlock::Instructions::m_instructions + VectorBufferOffset[t0], PC
+    loadp CodeBlock::m_instructions[t1], PC
 end
 
 # Expects that CodeBlock is in t1, which is what prologue() leaves behind.
@@ -503,8 +502,7 @@
 .continue:
     # Reload CodeBlock and PC, since the slow_path clobbered it.
     loadp CodeBlock[cfr], t1
-    loadp CodeBlock::m_instructions[t1], t0
-    loadp CodeBlock::Instructions::m_instructions + VectorBufferOffset[t0], PC
+    loadp CodeBlock::m_instructions[t1], PC
     jmp doneLabel
 end
 
diff --git a/Source/JavaScriptCore/runtime/Executable.cpp b/Source/JavaScriptCore/runtime/Executable.cpp
index 25ddf76..a85089a 100644
--- a/Source/JavaScriptCore/runtime/Executable.cpp
+++ b/Source/JavaScriptCore/runtime/Executable.cpp
@@ -210,8 +210,7 @@
     JSGlobalData* globalData = &exec->globalData();
     JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject();
     
-    if (!!m_evalCodeBlock && m_evalCodeBlock->canProduceCopyWithBytecode()) {
-        BytecodeDestructionBlocker blocker(m_evalCodeBlock.get());
+    if (!!m_evalCodeBlock) {
         OwnPtr<EvalCodeBlock> newCodeBlock = adoptPtr(new EvalCodeBlock(CodeBlock::CopyParsedBlock, *m_evalCodeBlock));
         newCodeBlock->setAlternative(static_pointer_cast<CodeBlock>(m_evalCodeBlock.release()));
         m_evalCodeBlock = newCodeBlock.release();
@@ -346,8 +345,7 @@
     JSGlobalData* globalData = &exec->globalData();
     JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject();
     
-    if (!!m_programCodeBlock && m_programCodeBlock->canProduceCopyWithBytecode()) {
-        BytecodeDestructionBlocker blocker(m_programCodeBlock.get());
+    if (!!m_programCodeBlock) {
         OwnPtr<ProgramCodeBlock> newCodeBlock = adoptPtr(new ProgramCodeBlock(CodeBlock::CopyParsedBlock, *m_programCodeBlock));
         newCodeBlock->setAlternative(static_pointer_cast<CodeBlock>(m_programCodeBlock.release()));
         m_programCodeBlock = newCodeBlock.release();
@@ -494,18 +492,13 @@
 
 FunctionCodeBlock* FunctionExecutable::codeBlockWithBytecodeFor(CodeSpecializationKind kind)
 {
-    FunctionCodeBlock* codeBlock = baselineCodeBlockFor(kind);
-    if (codeBlock->canProduceCopyWithBytecode())
-        return codeBlock;
-    return 0;
+    return baselineCodeBlockFor(kind);
 }
 
 PassOwnPtr<FunctionCodeBlock> FunctionExecutable::produceCodeBlockFor(ScopeChainNode* scopeChainNode, CompilationKind compilationKind, CodeSpecializationKind specializationKind, JSObject*& exception)
 {
-    if (!!codeBlockFor(specializationKind) && codeBlockFor(specializationKind)->canProduceCopyWithBytecode()) {
-        BytecodeDestructionBlocker blocker(codeBlockFor(specializationKind).get());
+    if (!!codeBlockFor(specializationKind))
         return adoptPtr(new FunctionCodeBlock(CodeBlock::CopyParsedBlock, *codeBlockFor(specializationKind)));
-    }
     
     exception = 0;
     JSGlobalData* globalData = scopeChainNode->globalData;
diff --git a/Source/JavaScriptCore/wtf/Platform.h b/Source/JavaScriptCore/wtf/Platform.h
index 76b11fe88..794db09 100644
--- a/Source/JavaScriptCore/wtf/Platform.h
+++ b/Source/JavaScriptCore/wtf/Platform.h
@@ -920,7 +920,7 @@
 #define ENABLE_JIT 0
 #endif
 
-/* The JIT is enabled by default on all x86, x64-64, ARM & MIPS platforms. */
+/* The JIT is enabled by default on all x86, x86-64, ARM & MIPS platforms. */
 #if !defined(ENABLE_JIT) \
     && (CPU(X86) || CPU(X86_64) || CPU(ARM) || CPU(MIPS)) \
     && (OS(DARWIN) || !COMPILER(GCC) || GCC_VERSION_AT_LEAST(4, 1, 0)) \
diff --git a/Source/JavaScriptCore/wtf/RefCountedArray.h b/Source/JavaScriptCore/wtf/RefCountedArray.h
new file mode 100644
index 0000000..a5ae862
--- /dev/null
+++ b/Source/JavaScriptCore/wtf/RefCountedArray.h
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2011 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef RefCountedArray_h
+#define RefCountedArray_h
+
+#include <wtf/FastMalloc.h>
+#include <wtf/StdLibExtras.h>
+#include <wtf/Vector.h>
+
+// This implements a reference counted array for POD** values, which is optimized for:
+// - An empty array only uses one word.
+// - A copy of the array only uses one word (i.e. assignment means aliasing).
+// - The vector can't grow beyond 2^32-1 elements.
+// - In all other regards this has similar space usage to a Vector.
+//
+// ** This could be modified to support non-POD values quite easily. It just
+//    hasn't been, so far, because there has been no need. Moreover, even now,
+//    it's used for things that aren't quite POD according to the official
+//    defintion, such as JSC::Instruction.
+
+namespace WTF {
+
+template<typename T>
+class RefCountedArray {
+public:
+    RefCountedArray()
+        : m_data(0)
+    {
+    }
+    
+    RefCountedArray(const RefCountedArray& other)
+        : m_data(other.m_data)
+    {
+        if (m_data)
+            Header::fromPayload(m_data)->refCount++;
+    }
+    
+    explicit RefCountedArray(const Vector<T>& other)
+    {
+        if (other.isEmpty()) {
+            m_data = 0;
+            return;
+        }
+        
+        m_data = (static_cast<Header*>(fastMalloc(Header::size() + sizeof(T) * other.size())))->payload();
+        Header::fromPayload(m_data)->refCount = 1;
+        Header::fromPayload(m_data)->length = other.size();
+        ASSERT(Header::fromPayload(m_data)->length == other.size());
+        memcpy(m_data, other.begin(), sizeof(T) * other.size());
+    }
+    
+    RefCountedArray& operator=(const RefCountedArray& other)
+    {
+        T* oldData = m_data;
+        m_data = other.m_data;
+        if (m_data)
+            Header::fromPayload(m_data)->refCount++;
+        
+        if (!oldData)
+            return *this;
+        if (--Header::fromPayload(oldData)->refCount)
+            return *this;
+        fastFree(Header::fromPayload(oldData));
+        return *this;
+    }
+    
+    ~RefCountedArray()
+    {
+        if (!m_data)
+            return;
+        if (--Header::fromPayload(m_data)->refCount)
+            return;
+        fastFree(Header::fromPayload(m_data));
+    }
+    
+    size_t size() const
+    {
+        if (!m_data)
+            return 0;
+        return Header::fromPayload(m_data)->length;
+    }
+    
+    T* data() { return m_data; }
+    T* begin() { return m_data; }
+    T* end()
+    {
+        if (!m_data)
+            return 0;
+        return m_data + Header::fromPayload(m_data)->length;
+    }
+    
+    const T* data() const { return m_data; }
+    const T* begin() const { return m_data; }
+    const T* end() const { return const_cast<RefCountedArray*>(this)->end(); }
+    
+    T& at(size_t i)
+    {
+        ASSERT(i < size());
+        return begin()[i];
+    }
+    
+    const T& at(size_t i) const
+    {
+        ASSERT(i < size());
+        return begin()[i];
+    }
+    
+    T& operator[](size_t i) { return at(i); }
+    const T& operator[](size_t i) const { return at(i); }
+    
+private:
+    struct Header {
+        unsigned refCount;
+        unsigned length;
+        
+        static size_t size()
+        {
+            return (sizeof(Header) + 7) & ~7;
+        }
+        
+        T* payload()
+        {
+            char* result = reinterpret_cast<char*>(this) + size();
+            ASSERT(!(bitwise_cast<uintptr_t>(result) & 7));
+            return reinterpret_cast<T*>(result);
+        }
+        
+        static Header* fromPayload(T* payload)
+        {
+            return reinterpret_cast<Header*>(reinterpret_cast<char*>(payload) - size());
+        }
+    };
+    
+    T* m_data;
+};
+
+} // namespace WTF
+
+using WTF::RefCountedArray;
+
+#endif // RefCountedArray_h
+