Multiple CodeBlock should be able to share the same instruction
stream without copying
https://bugs.webkit.org/show_bug.cgi?id=71978

Reviewed by Oliver Hunt.
        
This refactors CodeBlock::m_instructions to be a Vector boxed in a
ref-counted object, but otherwise does not take advantage of this.
        
This is performance neutral.

* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::printStructure):
(JSC::CodeBlock::printStructures):
(JSC::CodeBlock::dump):
(JSC::CodeBlock::CodeBlock):
(JSC::CodeBlock::visitAggregate):
(JSC::CodeBlock::shrinkToFit):
* bytecode/CodeBlock.h:
(JSC::CodeBlock::hasInstructions):
(JSC::CodeBlock::numberOfInstructions):
(JSC::CodeBlock::instructions):
* jit/JIT.cpp:
(JSC::JIT::JIT):



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@99810 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog
index d797d71..ad6d8c6 100644
--- a/Source/JavaScriptCore/ChangeLog
+++ b/Source/JavaScriptCore/ChangeLog
@@ -1,3 +1,30 @@
+2011-11-09  Filip Pizlo  <fpizlo@apple.com>
+
+        Multiple CodeBlock should be able to share the same instruction
+        stream without copying
+        https://bugs.webkit.org/show_bug.cgi?id=71978
+
+        Reviewed by Oliver Hunt.
+        
+        This refactors CodeBlock::m_instructions to be a Vector boxed in a
+        ref-counted object, but otherwise does not take advantage of this.
+        
+        This is performance neutral.
+
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::printStructure):
+        (JSC::CodeBlock::printStructures):
+        (JSC::CodeBlock::dump):
+        (JSC::CodeBlock::CodeBlock):
+        (JSC::CodeBlock::visitAggregate):
+        (JSC::CodeBlock::shrinkToFit):
+        * bytecode/CodeBlock.h:
+        (JSC::CodeBlock::hasInstructions):
+        (JSC::CodeBlock::numberOfInstructions):
+        (JSC::CodeBlock::instructions):
+        * jit/JIT.cpp:
+        (JSC::JIT::JIT):
+
 2011-11-09  Gavin Barraclough  <barraclough@apple.com>
 
         Renovate ARMv7 assembler/macro-assembler
diff --git a/Source/JavaScriptCore/bytecode/CodeBlock.cpp b/Source/JavaScriptCore/bytecode/CodeBlock.cpp
index d560eac..82a664c 100644
--- a/Source/JavaScriptCore/bytecode/CodeBlock.cpp
+++ b/Source/JavaScriptCore/bytecode/CodeBlock.cpp
@@ -284,14 +284,14 @@
 
 void CodeBlock::printStructure(const char* name, const Instruction* vPC, int operand) const
 {
-    unsigned instructionOffset = vPC - m_instructions.begin();
+    unsigned instructionOffset = vPC - instructions().begin();
     printf("  [%4d] %s: %s\n", instructionOffset, name, pointerToSourceString(vPC[operand].u.structure).utf8().data());
 }
 
 void CodeBlock::printStructures(const Instruction* vPC) const
 {
     Interpreter* interpreter = m_globalData->interpreter;
-    unsigned instructionOffset = vPC - m_instructions.begin();
+    unsigned instructionOffset = vPC - instructions().begin();
 
     if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id)) {
         printStructure("get_by_id", vPC, 4);
@@ -336,23 +336,23 @@
 
 void CodeBlock::dump(ExecState* exec) const
 {
-    if (m_instructions.isEmpty()) {
+    if (!m_instructions) {
         printf("No instructions available.\n");
         return;
     }
 
     size_t instructionCount = 0;
 
-    for (size_t i = 0; i < m_instructions.size(); i += opcodeLengths[exec->interpreter()->getOpcodeID(m_instructions[i].u.opcode)])
+    for (size_t i = 0; i < instructions().size(); i += opcodeLengths[exec->interpreter()->getOpcodeID(instructions()[i].u.opcode)])
         ++instructionCount;
 
     printf("%lu m_instructions; %lu bytes at %p; %d parameter(s); %d callee register(s)\n\n",
         static_cast<unsigned long>(instructionCount),
-        static_cast<unsigned long>(m_instructions.size() * sizeof(Instruction)),
+        static_cast<unsigned long>(instructions().size() * sizeof(Instruction)),
         this, m_numParameters, m_numCalleeRegisters);
 
-    Vector<Instruction>::const_iterator begin = m_instructions.begin();
-    Vector<Instruction>::const_iterator end = m_instructions.end();
+    Vector<Instruction>::const_iterator begin = instructions().begin();
+    Vector<Instruction>::const_iterator end = instructions().end();
     for (Vector<Instruction>::const_iterator it = begin; it != end; ++it)
         dump(exec, begin, it);
 
@@ -390,14 +390,14 @@
     if (!m_globalResolveInfos.isEmpty()) {
         size_t i = 0;
         do {
-             printGlobalResolveInfo(m_globalResolveInfos[i], instructionOffsetForNth(exec, m_instructions, i + 1, isGlobalResolve));
+             printGlobalResolveInfo(m_globalResolveInfos[i], instructionOffsetForNth(exec, instructions(), i + 1, isGlobalResolve));
              ++i;
         } while (i < m_globalResolveInfos.size());
     }
     if (!m_structureStubInfos.isEmpty()) {
         size_t i = 0;
         do {
-            printStructureStubInfo(m_structureStubInfos[i], instructionOffsetForNth(exec, m_instructions, i + 1, isPropertyAccess));
+            printStructureStubInfo(m_structureStubInfos[i], instructionOffsetForNth(exec, instructions(), i + 1, isPropertyAccess));
              ++i;
         } while (i < m_structureStubInfos.size());
     }
@@ -409,14 +409,14 @@
     if (!m_globalResolveInstructions.isEmpty()) {
         size_t i = 0;
         do {
-             printStructures(&m_instructions[m_globalResolveInstructions[i]]);
+             printStructures(&instructions()[m_globalResolveInstructions[i]]);
              ++i;
         } while (i < m_globalResolveInstructions.size());
     }
     if (!m_propertyAccessInstructions.isEmpty()) {
         size_t i = 0;
         do {
-            printStructures(&m_instructions[m_propertyAccessInstructions[i]]);
+            printStructures(&instructions()[m_propertyAccessInstructions[i]]);
              ++i;
         } while (i < m_propertyAccessInstructions.size());
     }
@@ -1416,9 +1416,8 @@
     , m_isConstructor(isConstructor)
     , m_ownerExecutable(globalObject->globalData(), ownerExecutable, ownerExecutable)
     , m_globalData(0)
-#ifndef NDEBUG
+    , m_instructions(adoptRef(new Instructions))
     , m_instructionCount(0)
-#endif
     , m_argumentsRegister(-1)
     , m_needsFullScopeChain(ownerExecutable->needsActivation())
     , m_usesEval(ownerExecutable->usesEval())
@@ -1554,9 +1553,9 @@
 #endif
 #if ENABLE(INTERPRETER)
     for (size_t size = m_propertyAccessInstructions.size(), i = 0; i < size; ++i)
-        visitStructures(visitor, &m_instructions[m_propertyAccessInstructions[i]]);
+        visitStructures(visitor, &instructions()[m_propertyAccessInstructions[i]]);
     for (size_t size = m_globalResolveInstructions.size(), i = 0; i < size; ++i)
-        visitStructures(visitor, &m_instructions[m_globalResolveInstructions[i]]);
+        visitStructures(visitor, &instructions()[m_globalResolveInstructions[i]]);
 #endif
 #if ENABLE(JIT)
     for (size_t size = m_globalResolveInfos.size(), i = 0; i < size; ++i) {
@@ -1722,7 +1721,7 @@
 
 void CodeBlock::shrinkToFit()
 {
-    m_instructions.shrinkToFit();
+    instructions().shrinkToFit();
 
 #if ENABLE(INTERPRETER)
     m_propertyAccessInstructions.shrinkToFit();
diff --git a/Source/JavaScriptCore/bytecode/CodeBlock.h b/Source/JavaScriptCore/bytecode/CodeBlock.h
index ada8d3f..893452b 100644
--- a/Source/JavaScriptCore/bytecode/CodeBlock.h
+++ b/Source/JavaScriptCore/bytecode/CodeBlock.h
@@ -438,7 +438,10 @@
         void setIsNumericCompareFunction(bool isNumericCompareFunction) { m_isNumericCompareFunction = isNumericCompareFunction; }
         bool isNumericCompareFunction() { return m_isNumericCompareFunction; }
 
-        Vector<Instruction>& instructions() { return m_instructions; }
+        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(); }
 
 #ifndef NDEBUG
@@ -1015,7 +1018,10 @@
         WriteBarrier<ScriptExecutable> m_ownerExecutable;
         JSGlobalData* m_globalData;
 
-        Vector<Instruction> m_instructions;
+        struct Instructions : public RefCounted<Instructions> {
+            Vector<Instruction> m_instructions;
+        };
+        RefPtr<Instructions> m_instructions;
         unsigned m_instructionCount;
 
         int m_thisRegister;
diff --git a/Source/JavaScriptCore/jit/JIT.cpp b/Source/JavaScriptCore/jit/JIT.cpp
index 200def4..e93eaf5 100644
--- a/Source/JavaScriptCore/jit/JIT.cpp
+++ b/Source/JavaScriptCore/jit/JIT.cpp
@@ -73,7 +73,7 @@
     : m_interpreter(globalData->interpreter)
     , m_globalData(globalData)
     , m_codeBlock(codeBlock)
-    , m_labels(codeBlock ? codeBlock->instructions().size() : 0)
+    , m_labels(codeBlock ? codeBlock->numberOfInstructions() : 0)
     , m_bytecodeOffset((unsigned)-1)
 #if USE(JSVALUE32_64)
     , m_jumpTargetIndex(0)