Don't allocate value profiles when the JIT is disabled
authorsbarati@apple.com <sbarati@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 11 May 2018 07:57:21 +0000 (07:57 +0000)
committersbarati@apple.com <sbarati@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 11 May 2018 07:57:21 +0000 (07:57 +0000)
https://bugs.webkit.org/show_bug.cgi?id=185525

Reviewed by Michael Saboff.

Source/JavaScriptCore:

There are many JSC API clients that run with the JIT disabled. We were
still allocating a ton of value profiles in this use case even though
these clients get no benefit from doing value profiling. This patch makes
it so that we don't allocate value profiles or argument value profiles
when we're not using the JIT. We now just make all value profiles in
the instruction stream point to a global value profile that the VM owns.
And we make the argument value profile array have zero length and teach
the LLInt how to handle that. Heap clears the global value profile on each GC.

In an app that I'm testing this against, this saves ~1MB of memory.

* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::finishCreation):
(JSC::CodeBlock::setNumParameters):
* bytecode/CodeBlock.h:
(JSC::CodeBlock::numberOfArgumentValueProfiles):
(JSC::CodeBlock::valueProfileForArgument):
* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::emitProfiledOpcode):
* heap/Heap.cpp:
(JSC::Heap::runEndPhase):
* llint/LowLevelInterpreter.asm:
* runtime/VM.cpp:
(JSC::VM::VM):
* runtime/VM.h:

Source/WTF:

* wtf/RefCountedArray.h:
(WTF::RefCountedArray::RefCountedArray):

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

Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/bytecode/CodeBlock.cpp
Source/JavaScriptCore/bytecode/CodeBlock.h
Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
Source/JavaScriptCore/heap/Heap.cpp
Source/JavaScriptCore/llint/LowLevelInterpreter.asm
Source/JavaScriptCore/runtime/VM.cpp
Source/JavaScriptCore/runtime/VM.h
Source/WTF/ChangeLog
Source/WTF/wtf/RefCountedArray.h

index c43468b..62ef911 100644 (file)
@@ -1,3 +1,36 @@
+2018-05-11  Saam Barati  <sbarati@apple.com>
+
+        Don't allocate value profiles when the JIT is disabled
+        https://bugs.webkit.org/show_bug.cgi?id=185525
+
+        Reviewed by Michael Saboff.
+
+        There are many JSC API clients that run with the JIT disabled. We were
+        still allocating a ton of value profiles in this use case even though
+        these clients get no benefit from doing value profiling. This patch makes
+        it so that we don't allocate value profiles or argument value profiles
+        when we're not using the JIT. We now just make all value profiles in
+        the instruction stream point to a global value profile that the VM owns.
+        And we make the argument value profile array have zero length and teach
+        the LLInt how to handle that. Heap clears the global value profile on each GC.
+
+        In an app that I'm testing this against, this saves ~1MB of memory.
+
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::finishCreation):
+        (JSC::CodeBlock::setNumParameters):
+        * bytecode/CodeBlock.h:
+        (JSC::CodeBlock::numberOfArgumentValueProfiles):
+        (JSC::CodeBlock::valueProfileForArgument):
+        * bytecompiler/BytecodeGenerator.cpp:
+        (JSC::BytecodeGenerator::emitProfiledOpcode):
+        * heap/Heap.cpp:
+        (JSC::Heap::runEndPhase):
+        * llint/LowLevelInterpreter.asm:
+        * runtime/VM.cpp:
+        (JSC::VM::VM):
+        * runtime/VM.h:
+
 2018-05-10  Carlos Garcia Campos  <cgarcia@igalia.com>
 
         [JSC][GLIB] Add introspectable alternatives to functions using vargars
index 745037a..d111de0 100644 (file)
@@ -506,6 +506,8 @@ bool CodeBlock::finishCreation(VM& vm, ScriptExecutable* ownerExecutable, Unlink
         m_arrayAllocationProfiles = RefCountedArray<ArrayAllocationProfile>(size);
     if (size_t size = unlinkedCodeBlock->numberOfValueProfiles())
         m_valueProfiles = RefCountedArray<ValueProfile>(size);
+    if (!vm.canUseJIT())
+        RELEASE_ASSERT(!m_valueProfiles.size());
     if (size_t size = unlinkedCodeBlock->numberOfObjectAllocationProfiles())
         m_objectAllocationProfiles = RefCountedArray<ObjectAllocationProfile>(size);
 
@@ -524,6 +526,12 @@ bool CodeBlock::finishCreation(VM& vm, ScriptExecutable* ownerExecutable, Unlink
 
     unsigned valueProfileCount = 0;
     auto linkValueProfile = [&](unsigned bytecodeOffset, unsigned opLength) {
+        if (!vm.canUseJIT()) {
+            ASSERT(vm.noJITValueProfileSingleton);
+            instructions[bytecodeOffset + opLength - 1] = vm.noJITValueProfileSingleton.get();
+            return;
+        }
+
         unsigned valueProfileIndex = valueProfileCount++;
         ValueProfile* profile = &m_valueProfiles[valueProfileIndex];
         ASSERT(profile->m_bytecodeOffset == -1);
@@ -967,7 +975,7 @@ void CodeBlock::setNumParameters(int newValue)
 {
     m_numParameters = newValue;
 
-    m_argumentValueProfiles = RefCountedArray<ValueProfile>(newValue);
+    m_argumentValueProfiles = RefCountedArray<ValueProfile>(vm()->canUseJIT() ? newValue : 0);
 }
 
 CodeBlock* CodeBlock::specialOSREntryBlockOrNull()
index 86723ab..854f34f 100644 (file)
@@ -417,11 +417,12 @@ public:
     unsigned numberOfArgumentValueProfiles()
     {
         ASSERT(m_numParameters >= 0);
-        ASSERT(m_argumentValueProfiles.size() == static_cast<unsigned>(m_numParameters));
+        ASSERT(m_argumentValueProfiles.size() == static_cast<unsigned>(m_numParameters) || !vm()->canUseJIT());
         return m_argumentValueProfiles.size();
     }
     ValueProfile& valueProfileForArgument(unsigned argumentIndex)
     {
+        ASSERT(vm()->canUseJIT()); // This is only called from the various JIT compilers or places that first check numberOfArgumentValueProfiles before calling this.
         ValueProfile& result = m_argumentValueProfiles[argumentIndex];
         ASSERT(result.m_bytecodeOffset == -1);
         return result;
index e7795db..8695ca0 100644 (file)
@@ -1294,8 +1294,10 @@ UnlinkedObjectAllocationProfile BytecodeGenerator::newObjectAllocationProfile()
 
 UnlinkedValueProfile BytecodeGenerator::emitProfiledOpcode(OpcodeID opcodeID)
 {
-    UnlinkedValueProfile result = m_codeBlock->addValueProfile();
     emitOpcode(opcodeID);
+    if (!m_vm->canUseJIT())
+        return static_cast<UnlinkedValueProfile>(-1);
+    UnlinkedValueProfile result = m_codeBlock->addValueProfile();
     return result;
 }
 
index 3bc9e5b..0787119 100644 (file)
@@ -1457,6 +1457,9 @@ NEVER_INLINE bool Heap::runEndPhase(GCConductor conn)
         
     if (vm()->typeProfiler())
         vm()->typeProfiler()->invalidateTypeSetCache();
+
+    if (ValueProfile* profile = vm()->noJITValueProfileSingleton.get())
+        *profile = ValueProfile(0);
         
     reapWeakHandles();
     pruneStaleEntriesFromWeakGCMaps();
index adc1d6e..3001e29 100644 (file)
@@ -1119,6 +1119,7 @@ macro functionInitialization(profileArgSkip)
     assert(macro (ok) bpgteq t0, 0, ok end)
     btpz t0, .argumentProfileDone
     loadp CodeBlock::m_argumentValueProfiles + VectorBufferOffset[t1], t3
+    bpeq 0, t3, .argumentProfileDone # When we can't JIT, we don't allocate any argument value profiles.
     mulp sizeof ValueProfile, t0, t2 # Aaaaahhhh! Need strength reduction!
     lshiftp 3, t0
     addp t2, t3
index 1a1deae..fb00478 100644 (file)
@@ -490,6 +490,9 @@ VM::VM(VMType vmType, HeapType heapType)
     }
 #endif
 
+    if (!canUseJIT())
+        noJITValueProfileSingleton = std::make_unique<ValueProfile>(0);
+
     VMInspector::instance().add(this);
 }
 
index 613c56b..24a91cd 100644 (file)
@@ -171,6 +171,7 @@ class Signature;
 
 struct HashTable;
 struct Instruction;
+struct ValueProfile;
 
 struct LocalTimeOffsetCache {
     LocalTimeOffsetCache()
@@ -721,6 +722,8 @@ public:
     RTTraceList* m_rtTraceList;
 #endif
 
+    std::unique_ptr<ValueProfile> noJITValueProfileSingleton;
+
     JS_EXPORT_PRIVATE void resetDateCache();
 
     RegExpCache* regExpCache() { return m_regExpCache; }
index 571658d..508bec6 100644 (file)
@@ -1,3 +1,13 @@
+2018-05-11  Saam Barati  <sbarati@apple.com>
+
+        Don't allocate value profiles when the JIT is disabled
+        https://bugs.webkit.org/show_bug.cgi?id=185525
+
+        Reviewed by Michael Saboff.
+
+        * wtf/RefCountedArray.h:
+        (WTF::RefCountedArray::RefCountedArray):
+
 2018-05-10  Tim Horton  <timothy_horton@apple.com>
 
         Fix the build after r231393
index cf7cc56..3f68363 100644 (file)
@@ -63,6 +63,7 @@ public:
     explicit RefCountedArray(size_t size)
     {
         if (!size) {
+            // NOTE: JSC's LowLevelInterpreter relies on this being nullptr when the size is zero.
             PtrTraits::exchange(m_data, nullptr);
             return;
         }