[JSC] Embed RegExp into constant buffer in UnlinkedCodeBlock and CodeBlock
authorutatane.tea@gmail.com <utatane.tea@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 9 Jul 2018 21:29:41 +0000 (21:29 +0000)
committerutatane.tea@gmail.com <utatane.tea@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 9 Jul 2018 21:29:41 +0000 (21:29 +0000)
https://bugs.webkit.org/show_bug.cgi?id=187477

Reviewed by Mark Lam.

Before this patch, RegExp* is specially held in m_regexp buffer which resides in CodeBlock's RareData.
However, it is not necessary since JSCells can be reside in a constant buffer.
This patch embeds RegExp* to a constant buffer in UnlinkedCodeBlock and CodeBlock. And remove RegExp
vector from RareData.

We also move the code of dumping RegExp from BytecodeDumper to RegExp::dumpToStream.

* bytecode/BytecodeDumper.cpp:
(JSC::BytecodeDumper<Block>::dumpBytecode):
(JSC::BytecodeDumper<Block>::dumpBlock):
(JSC::regexpToSourceString): Deleted.
(JSC::regexpName): Deleted.
(JSC::BytecodeDumper<Block>::dumpRegExps): Deleted.
* bytecode/BytecodeDumper.h:
* bytecode/CodeBlock.h:
(JSC::CodeBlock::regexp const): Deleted.
(JSC::CodeBlock::numberOfRegExps const): Deleted.
* bytecode/UnlinkedCodeBlock.cpp:
(JSC::UnlinkedCodeBlock::visitChildren):
(JSC::UnlinkedCodeBlock::shrinkToFit):
* bytecode/UnlinkedCodeBlock.h:
(JSC::UnlinkedCodeBlock::addRegExp): Deleted.
(JSC::UnlinkedCodeBlock::numberOfRegExps const): Deleted.
(JSC::UnlinkedCodeBlock::regexp const): Deleted.
* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::emitNewRegExp):
(JSC::BytecodeGenerator::addRegExp): Deleted.
* bytecompiler/BytecodeGenerator.h:
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::parseBlock):
* jit/JITOpcodes.cpp:
(JSC::JIT::emit_op_new_regexp):
* llint/LLIntSlowPaths.cpp:
(JSC::LLInt::LLINT_SLOW_PATH_DECL):
* runtime/JSCJSValue.cpp:
(JSC::JSValue::dumpInContextAssumingStructure const):
* runtime/RegExp.cpp:
(JSC::regexpToSourceString):
(JSC::RegExp::dumpToStream):
* runtime/RegExp.h:

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

14 files changed:
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/bytecode/BytecodeDumper.cpp
Source/JavaScriptCore/bytecode/BytecodeDumper.h
Source/JavaScriptCore/bytecode/CodeBlock.h
Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp
Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h
Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
Source/JavaScriptCore/jit/JITOpcodes.cpp
Source/JavaScriptCore/llint/LLIntSlowPaths.cpp
Source/JavaScriptCore/runtime/JSCJSValue.cpp
Source/JavaScriptCore/runtime/RegExp.cpp
Source/JavaScriptCore/runtime/RegExp.h

index f372c37..54b73a9 100644 (file)
@@ -1,3 +1,51 @@
+2018-07-09  Yusuke Suzuki  <utatane.tea@gmail.com>
+
+        [JSC] Embed RegExp into constant buffer in UnlinkedCodeBlock and CodeBlock
+        https://bugs.webkit.org/show_bug.cgi?id=187477
+
+        Reviewed by Mark Lam.
+
+        Before this patch, RegExp* is specially held in m_regexp buffer which resides in CodeBlock's RareData.
+        However, it is not necessary since JSCells can be reside in a constant buffer.
+        This patch embeds RegExp* to a constant buffer in UnlinkedCodeBlock and CodeBlock. And remove RegExp
+        vector from RareData.
+
+        We also move the code of dumping RegExp from BytecodeDumper to RegExp::dumpToStream.
+
+        * bytecode/BytecodeDumper.cpp:
+        (JSC::BytecodeDumper<Block>::dumpBytecode):
+        (JSC::BytecodeDumper<Block>::dumpBlock):
+        (JSC::regexpToSourceString): Deleted.
+        (JSC::regexpName): Deleted.
+        (JSC::BytecodeDumper<Block>::dumpRegExps): Deleted.
+        * bytecode/BytecodeDumper.h:
+        * bytecode/CodeBlock.h:
+        (JSC::CodeBlock::regexp const): Deleted.
+        (JSC::CodeBlock::numberOfRegExps const): Deleted.
+        * bytecode/UnlinkedCodeBlock.cpp:
+        (JSC::UnlinkedCodeBlock::visitChildren):
+        (JSC::UnlinkedCodeBlock::shrinkToFit):
+        * bytecode/UnlinkedCodeBlock.h:
+        (JSC::UnlinkedCodeBlock::addRegExp): Deleted.
+        (JSC::UnlinkedCodeBlock::numberOfRegExps const): Deleted.
+        (JSC::UnlinkedCodeBlock::regexp const): Deleted.
+        * bytecompiler/BytecodeGenerator.cpp:
+        (JSC::BytecodeGenerator::emitNewRegExp):
+        (JSC::BytecodeGenerator::addRegExp): Deleted.
+        * bytecompiler/BytecodeGenerator.h:
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::parseBlock):
+        * jit/JITOpcodes.cpp:
+        (JSC::JIT::emit_op_new_regexp):
+        * llint/LLIntSlowPaths.cpp:
+        (JSC::LLInt::LLINT_SLOW_PATH_DECL):
+        * runtime/JSCJSValue.cpp:
+        (JSC::JSValue::dumpInContextAssumingStructure const):
+        * runtime/RegExp.cpp:
+        (JSC::regexpToSourceString):
+        (JSC::RegExp::dumpToStream):
+        * runtime/RegExp.h:
+
 2018-07-09  Brian Burg  <bburg@apple.com>
 
         REGRESSION: Web Inspector no longer pauses in internal injected scripts like WDFindNodes.js
index af3a2c1..eba04d9 100644 (file)
@@ -250,31 +250,6 @@ const Identifier& BytecodeDumper<Block>::identifier(int index) const
     return block()->identifier(index);
 }
 
-static CString regexpToSourceString(RegExp* regExp)
-{
-    char postfix[7] = { '/', 0, 0, 0, 0, 0, 0 };
-    int index = 1;
-    if (regExp->global())
-        postfix[index++] = 'g';
-    if (regExp->ignoreCase())
-        postfix[index++] = 'i';
-    if (regExp->multiline())
-        postfix[index] = 'm';
-    if (regExp->dotAll())
-        postfix[index++] = 's';
-    if (regExp->unicode())
-        postfix[index++] = 'u';
-    if (regExp->sticky())
-        postfix[index++] = 'y';
-
-    return toCString("/", regExp->pattern().impl(), postfix);
-}
-
-static CString regexpName(int re, RegExp* regexp)
-{
-    return toCString(regexpToSourceString(regexp), "(@re", re, ")");
-}
-
 template<class Instruction>
 static void printLocationAndOp(PrintStream& out, int location, const Instruction*&, const char* op)
 {
@@ -827,11 +802,7 @@ void BytecodeDumper<Block>::dumpBytecode(PrintStream& out, const typename Block:
         int r0 = (++it)->u.operand;
         int re0 = (++it)->u.operand;
         printLocationAndOp(out, location, it, "new_regexp");
-        out.printf("%s, ", registerName(r0).data());
-        if (r0 >=0 && r0 < (int)block()->numberOfRegExps())
-            out.printf("%s", regexpName(re0, block()->regexp(re0)).data());
-        else
-            out.printf("bad_regexp(%d)", re0);
+        out.printf("%s, %s", registerName(r0).data(), registerName(re0).data());
         break;
     }
     case op_mov: {
@@ -1823,19 +1794,6 @@ void BytecodeDumper<Block>::dumpConstants(PrintStream& out)
 }
 
 template<class Block>
-void BytecodeDumper<Block>::dumpRegExps(PrintStream& out)
-{
-    if (size_t count = block()->numberOfRegExps()) {
-        out.printf("\nm_regexps:\n");
-        size_t i = 0;
-        do {
-            out.printf("  re%u = %s\n", static_cast<unsigned>(i), regexpToSourceString(block()->regexp(i)).data());
-            ++i;
-        } while (i < count);
-    }
-}
-
-template<class Block>
 void BytecodeDumper<Block>::dumpExceptionHandlers(PrintStream& out)
 {
     if (unsigned count = block()->numberOfExceptionHandlers()) {
@@ -1914,7 +1872,6 @@ void BytecodeDumper<Block>::dumpBlock(Block* block, const typename Block::Unpack
 
     dumper.dumpIdentifiers(out);
     dumper.dumpConstants(out);
-    dumper.dumpRegExps(out);
     dumper.dumpExceptionHandlers(out);
     dumper.dumpSwitchJumpTables(out);
     dumper.dumpStringSwitchJumpTables(out);
index 5e8943e..deb4788 100644 (file)
@@ -59,7 +59,6 @@ private:
 
     void dumpIdentifiers(PrintStream& out);
     void dumpConstants(PrintStream& out);
-    void dumpRegExps(PrintStream& out);
     void dumpExceptionHandlers(PrintStream& out);
     void dumpSwitchJumpTables(PrintStream& out);
     void dumpStringSwitchJumpTables(PrintStream& out);
index 553b3bb..851b58b 100644 (file)
@@ -560,9 +560,6 @@ public:
     int numberOfFunctionDecls() { return m_functionDecls.size(); }
     FunctionExecutable* functionExpr(int index) { return m_functionExprs[index].get(); }
     
-    RegExp* regexp(int index) const { return m_unlinkedCode->regexp(index); }
-    unsigned numberOfRegExps() const { return m_unlinkedCode->numberOfRegExps(); }
-
     const Vector<BitVector>& bitVectors() const { return m_unlinkedCode->bitVectors(); }
     const BitVector& bitVector(size_t i) { return m_unlinkedCode->bitVector(i); }
 
index b735ae9..f5b1bf7 100644 (file)
@@ -92,10 +92,6 @@ void UnlinkedCodeBlock::visitChildren(JSCell* cell, SlotVisitor& visitor)
     visitor.appendValues(thisObject->m_constantRegisters.data(), thisObject->m_constantRegisters.size());
     if (thisObject->m_unlinkedInstructions)
         visitor.reportExtraMemoryVisited(thisObject->m_unlinkedInstructions->sizeInBytes());
-    if (thisObject->m_rareData) {
-        for (size_t i = 0, end = thisObject->m_rareData->m_regexps.size(); i != end; i++)
-            visitor.append(thisObject->m_rareData->m_regexps[i]);
-    }
 }
 
 size_t UnlinkedCodeBlock::estimatedSize(JSCell* cell)
@@ -396,7 +392,6 @@ void UnlinkedCodeBlock::shrinkToFit()
 
     if (m_rareData) {
         m_rareData->m_exceptionHandlers.shrinkToFit();
-        m_rareData->m_regexps.shrinkToFit();
         m_rareData->m_switchJumpTables.shrinkToFit();
         m_rareData->m_stringSwitchJumpTables.shrinkToFit();
         m_rareData->m_expressionInfoFatPositions.shrinkToFit();
index ceb4673..d76f8c9 100644 (file)
@@ -158,23 +158,6 @@ public:
     void addParameter() { m_numParameters++; }
     unsigned numParameters() const { return m_numParameters; }
 
-    unsigned addRegExp(RegExp* r)
-    {
-        createRareDataIfNecessary();
-        VM& vm = *this->vm();
-        auto locker = lockDuringMarking(vm.heap, cellLock());
-        unsigned size = m_rareData->m_regexps.size();
-        m_rareData->m_regexps.append(WriteBarrier<RegExp>(vm, this, r));
-        return size;
-    }
-    unsigned numberOfRegExps() const
-    {
-        if (!m_rareData)
-            return 0;
-        return m_rareData->m_regexps.size();
-    }
-    RegExp* regexp(int index) const { ASSERT(m_rareData); return m_rareData->m_regexps[index].get(); }
-
     // Constant Pools
 
     size_t numberOfIdentifiers() const { return m_identifiers.size(); }
@@ -506,9 +489,6 @@ public:
     public:
         Vector<UnlinkedHandlerInfo> m_exceptionHandlers;
 
-        // Rare Constants
-        Vector<WriteBarrier<RegExp>> m_regexps;
-
         // Jump Tables
         Vector<UnlinkedSimpleJumpTable> m_switchJumpTables;
         Vector<UnlinkedStringJumpTable> m_stringSwitchJumpTables;
index 55f5ea1..556780b 100644 (file)
@@ -1651,11 +1651,6 @@ RegisterID* BytecodeGenerator::moveLinkTimeConstant(RegisterID* dst, LinkTimeCon
     return dst;
 }
 
-unsigned BytecodeGenerator::addRegExp(RegExp* r)
-{
-    return m_codeBlock->addRegExp(r);
-}
-
 RegisterID* BytecodeGenerator::moveEmptyValue(RegisterID* dst)
 {
     RefPtr<RegisterID> emptyValue = addConstantEmptyValue();
@@ -3286,7 +3281,7 @@ RegisterID* BytecodeGenerator::emitNewRegExp(RegisterID* dst, RegExp* regExp)
 {
     emitOpcode(op_new_regexp);
     instructions().append(dst->index());
-    instructions().append(addRegExp(regExp));
+    instructions().append(addConstantValue(regExp)->index());
     return dst;
 }
 
index f57a47c..35957d8 100644 (file)
@@ -1074,7 +1074,6 @@ namespace JSC {
         unsigned addConstant(const Identifier&);
         RegisterID* addConstantValue(JSValue, SourceCodeRepresentation = SourceCodeRepresentation::Other);
         RegisterID* addConstantEmptyValue();
-        unsigned addRegExp(RegExp*);
 
         UnlinkedFunctionExecutable* makeFunction(FunctionMetadataNode* metadata)
         {
index 6984d75..d89f2af 100644 (file)
@@ -4602,9 +4602,10 @@ void ByteCodeParser::parseBlock(unsigned limit)
         }
             
         case op_new_regexp: {
-            RegExp* regexp = m_inlineStackTop->m_codeBlock->regexp(currentInstruction[2].u.operand);
-            FrozenValue* frozen = m_graph.freezeStrong(regexp);
-            set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(NewRegexp, OpInfo(frozen), jsConstant(jsNumber(0))));
+            VirtualRegister regExpRegister(currentInstruction[2].u.operand);
+            ASSERT(regExpRegister.isConstant());
+            FrozenValue* frozenRegExp = m_graph.freezeStrong(m_inlineStackTop->m_codeBlock->getConstant(regExpRegister.offset()));
+            set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(NewRegexp, OpInfo(frozenRegExp), jsConstant(jsNumber(0))));
             NEXT_OPCODE(op_new_regexp);
         }
 
index 25eccd1..6c39fce 100644 (file)
@@ -990,7 +990,8 @@ void JIT::emitSlow_op_check_traps(Instruction*, Vector<SlowCaseEntry>::iterator&
 void JIT::emit_op_new_regexp(Instruction* currentInstruction)
 {
     int dst = currentInstruction[1].u.operand;
-    callOperation(operationNewRegexp, m_codeBlock->regexp(currentInstruction[2].u.operand));
+    int regexp = currentInstruction[2].u.operand;
+    callOperation(operationNewRegexp, jsCast<RegExp*>(m_codeBlock->getConstant(regexp)));
     emitStoreCell(dst, returnValueGPR);
 }
 
index bf776ab..6abe8fd 100644 (file)
@@ -550,7 +550,7 @@ LLINT_SLOW_PATH_DECL(slow_path_new_array_with_size)
 LLINT_SLOW_PATH_DECL(slow_path_new_regexp)
 {
     LLINT_BEGIN();
-    RegExp* regExp = exec->codeBlock()->regexp(pc[2].u.operand);
+    RegExp* regExp = jsCast<RegExp*>(LLINT_OP_C(2).jsValue());
     ASSERT(regExp->isValid());
     LLINT_RETURN(RegExpObject::create(vm, exec->lexicalGlobalObject()->regExpStructure(), regExp));
 }
index 1a6748a..9681962 100644 (file)
@@ -272,7 +272,9 @@ void JSValue::dumpInContextAssumingStructure(
             } else
                 out.print(" (unresolved)");
             out.print(": ", impl);
-        } else if (structure->classInfo()->isSubClassOf(Symbol::info()))
+        } else if (structure->classInfo()->isSubClassOf(RegExp::info()))
+            out.print("RegExp: ", *jsCast<RegExp*>(asCell()));
+        else if (structure->classInfo()->isSubClassOf(Symbol::info()))
             out.print("Symbol: ", RawPointer(asCell()));
         else if (structure->classInfo()->isSubClassOf(Structure::info()))
             out.print("Structure: ", inContext(*jsCast<Structure*>(asCell()), context));
index 63a2b51..41e005e 100644 (file)
@@ -505,4 +505,29 @@ void RegExp::matchCompareWithInterpreter(const String& s, int startOffset, int*
     }
 #endif
 
+static CString regexpToSourceString(const RegExp* regExp)
+{
+    char postfix[7] = { '/', 0, 0, 0, 0, 0, 0 };
+    int index = 1;
+    if (regExp->global())
+        postfix[index++] = 'g';
+    if (regExp->ignoreCase())
+        postfix[index++] = 'i';
+    if (regExp->multiline())
+        postfix[index] = 'm';
+    if (regExp->dotAll())
+        postfix[index++] = 's';
+    if (regExp->unicode())
+        postfix[index++] = 'u';
+    if (regExp->sticky())
+        postfix[index++] = 'y';
+
+    return toCString("/", regExp->pattern().impl(), postfix);
+}
+
+void RegExp::dumpToStream(const JSCell* cell, PrintStream& out)
+{
+    out.print(regexpToSourceString(jsCast<const RegExp*>(cell)));
+}
+
 } // namespace JSC
index 60d7ff2..05ce5c0 100644 (file)
@@ -49,6 +49,7 @@ public:
     static const bool needsDestruction = true;
     static void destroy(JSCell*);
     static size_t estimatedSize(JSCell*);
+    JS_EXPORT_PRIVATE static void dumpToStream(const JSCell*, PrintStream&);
 
     bool global() const { return m_flags & FlagGlobal; }
     bool ignoreCase() const { return m_flags & FlagIgnoreCase; }