Move ExitProfile to UnlinkedCodeBlock so it can be shared amongst CodeBlocks backed...
authorsbarati@apple.com <sbarati@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 13 Jan 2018 00:36:37 +0000 (00:36 +0000)
committersbarati@apple.com <sbarati@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 13 Jan 2018 00:36:37 +0000 (00:36 +0000)
https://bugs.webkit.org/show_bug.cgi?id=181545

Reviewed by Michael Saboff.

This patch follows the theme of putting optimization profiling information on
UnlinkedCodeBlock. This allows the unlinked code cache to remember OSR exit data.
This often leads to the first compile of a CodeBlock, backed by an UnlinkedCodeBlock
pulled from the code cache, making better compilation decisions, usually
resulting in fewer exits, and fewer recompilations.

This is a 1% Speedometer progression in my testing.

* bytecode/BytecodeDumper.cpp:
(JSC::BytecodeDumper<CodeBlock>::dumpProfilesForBytecodeOffset):
* bytecode/CallLinkStatus.cpp:
(JSC::CallLinkStatus::computeFromLLInt):
(JSC::CallLinkStatus::computeFor):
(JSC::CallLinkStatus::computeExitSiteData):
(JSC::CallLinkStatus::computeDFGStatuses):
* bytecode/CallLinkStatus.h:
* bytecode/CodeBlock.h:
(JSC::CodeBlock::addFrequentExitSite): Deleted.
(JSC::CodeBlock::hasExitSite const): Deleted.
(JSC::CodeBlock::exitProfile): Deleted.
* bytecode/DFGExitProfile.cpp:
(JSC::DFG::ExitProfile::add):
(JSC::DFG::QueryableExitProfile::initialize):
* bytecode/DFGExitProfile.h:
(JSC::DFG::ExitProfile::hasExitSite const):
* bytecode/GetByIdStatus.cpp:
(JSC::GetByIdStatus::hasExitSite):
(JSC::GetByIdStatus::computeFor):
(JSC::GetByIdStatus::computeForStubInfo):
* bytecode/GetByIdStatus.h:
* bytecode/PutByIdStatus.cpp:
(JSC::PutByIdStatus::hasExitSite):
(JSC::PutByIdStatus::computeFor):
(JSC::PutByIdStatus::computeForStubInfo):
* bytecode/PutByIdStatus.h:
* bytecode/UnlinkedCodeBlock.cpp:
(JSC::UnlinkedCodeBlock::livenessAnalysisSlow):
* bytecode/UnlinkedCodeBlock.h:
(JSC::UnlinkedCodeBlock::hasExitSite const):
(JSC::UnlinkedCodeBlock::hasExitSite):
(JSC::UnlinkedCodeBlock::exitProfile):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::InlineStackEntry::InlineStackEntry):
* dfg/DFGGraph.h:
(JSC::DFG::Graph::hasGlobalExitSite):
(JSC::DFG::Graph::hasExitSite):
* dfg/DFGLICMPhase.cpp:
(JSC::DFG::LICMPhase::attemptHoist):
* dfg/DFGOSRExitBase.cpp:
(JSC::DFG::OSRExitBase::considerAddingAsFrequentExitSiteSlow):

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

17 files changed:
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/bytecode/BytecodeDumper.cpp
Source/JavaScriptCore/bytecode/CallLinkStatus.cpp
Source/JavaScriptCore/bytecode/CallLinkStatus.h
Source/JavaScriptCore/bytecode/CodeBlock.h
Source/JavaScriptCore/bytecode/DFGExitProfile.cpp
Source/JavaScriptCore/bytecode/DFGExitProfile.h
Source/JavaScriptCore/bytecode/GetByIdStatus.cpp
Source/JavaScriptCore/bytecode/GetByIdStatus.h
Source/JavaScriptCore/bytecode/PutByIdStatus.cpp
Source/JavaScriptCore/bytecode/PutByIdStatus.h
Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp
Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h
Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
Source/JavaScriptCore/dfg/DFGGraph.h
Source/JavaScriptCore/dfg/DFGLICMPhase.cpp
Source/JavaScriptCore/dfg/DFGOSRExitBase.cpp

index d1793c9..0607a5e 100644 (file)
@@ -1,3 +1,61 @@
+2018-01-12  Saam Barati  <sbarati@apple.com>
+
+        Move ExitProfile to UnlinkedCodeBlock so it can be shared amongst CodeBlocks backed by the same UnlinkedCodeBlock
+        https://bugs.webkit.org/show_bug.cgi?id=181545
+
+        Reviewed by Michael Saboff.
+
+        This patch follows the theme of putting optimization profiling information on
+        UnlinkedCodeBlock. This allows the unlinked code cache to remember OSR exit data.
+        This often leads to the first compile of a CodeBlock, backed by an UnlinkedCodeBlock
+        pulled from the code cache, making better compilation decisions, usually
+        resulting in fewer exits, and fewer recompilations.
+        
+        This is a 1% Speedometer progression in my testing.
+
+        * bytecode/BytecodeDumper.cpp:
+        (JSC::BytecodeDumper<CodeBlock>::dumpProfilesForBytecodeOffset):
+        * bytecode/CallLinkStatus.cpp:
+        (JSC::CallLinkStatus::computeFromLLInt):
+        (JSC::CallLinkStatus::computeFor):
+        (JSC::CallLinkStatus::computeExitSiteData):
+        (JSC::CallLinkStatus::computeDFGStatuses):
+        * bytecode/CallLinkStatus.h:
+        * bytecode/CodeBlock.h:
+        (JSC::CodeBlock::addFrequentExitSite): Deleted.
+        (JSC::CodeBlock::hasExitSite const): Deleted.
+        (JSC::CodeBlock::exitProfile): Deleted.
+        * bytecode/DFGExitProfile.cpp:
+        (JSC::DFG::ExitProfile::add):
+        (JSC::DFG::QueryableExitProfile::initialize):
+        * bytecode/DFGExitProfile.h:
+        (JSC::DFG::ExitProfile::hasExitSite const):
+        * bytecode/GetByIdStatus.cpp:
+        (JSC::GetByIdStatus::hasExitSite):
+        (JSC::GetByIdStatus::computeFor):
+        (JSC::GetByIdStatus::computeForStubInfo):
+        * bytecode/GetByIdStatus.h:
+        * bytecode/PutByIdStatus.cpp:
+        (JSC::PutByIdStatus::hasExitSite):
+        (JSC::PutByIdStatus::computeFor):
+        (JSC::PutByIdStatus::computeForStubInfo):
+        * bytecode/PutByIdStatus.h:
+        * bytecode/UnlinkedCodeBlock.cpp:
+        (JSC::UnlinkedCodeBlock::livenessAnalysisSlow):
+        * bytecode/UnlinkedCodeBlock.h:
+        (JSC::UnlinkedCodeBlock::hasExitSite const):
+        (JSC::UnlinkedCodeBlock::hasExitSite):
+        (JSC::UnlinkedCodeBlock::exitProfile):
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::InlineStackEntry::InlineStackEntry):
+        * dfg/DFGGraph.h:
+        (JSC::DFG::Graph::hasGlobalExitSite):
+        (JSC::DFG::Graph::hasExitSite):
+        * dfg/DFGLICMPhase.cpp:
+        (JSC::DFG::LICMPhase::attemptHoist):
+        * dfg/DFGOSRExitBase.cpp:
+        (JSC::DFG::OSRExitBase::considerAddingAsFrequentExitSiteSlow):
+
 2018-01-12  JF Bastien  <jfbastien@apple.com>
 
         PoisonedWriteBarrier
index d35695f..fd3be4d 100644 (file)
@@ -226,7 +226,7 @@ void BytecodeDumper<CodeBlock>::dumpProfilesForBytecodeOffset(PrintStream& out,
     }
 
 #if ENABLE(DFG_JIT)
-    Vector<DFG::FrequentExitSite> exitSites = block()->exitProfile().exitSitesFor(location);
+    Vector<DFG::FrequentExitSite> exitSites = block()->unlinkedCodeBlock()->exitProfile().exitSitesFor(location);
     if (!exitSites.isEmpty()) {
         out.print(" !! frequent exits: ");
         CommaPrinter comma;
index f284e30..b0934c7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012-2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2012-2018 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -54,12 +54,12 @@ CallLinkStatus::CallLinkStatus(JSValue value)
     m_variants.append(CallVariant(value.asCell()));
 }
 
-CallLinkStatus CallLinkStatus::computeFromLLInt(const ConcurrentJSLocker& locker, CodeBlock* profiledBlock, unsigned bytecodeIndex)
+CallLinkStatus CallLinkStatus::computeFromLLInt(const ConcurrentJSLocker&, CodeBlock* profiledBlock, unsigned bytecodeIndex)
 {
     UNUSED_PARAM(profiledBlock);
     UNUSED_PARAM(bytecodeIndex);
 #if ENABLE(DFG_JIT)
-    if (profiledBlock->hasExitSite(locker, DFG::FrequentExitSite(bytecodeIndex, BadCell))) {
+    if (profiledBlock->unlinkedCodeBlock()->hasExitSite(DFG::FrequentExitSite(bytecodeIndex, BadCell))) {
         // We could force this to be a closure call, but instead we'll just assume that it
         // takes slow path.
         return takesSlowPath();
@@ -87,7 +87,7 @@ CallLinkStatus CallLinkStatus::computeFor(
     UNUSED_PARAM(bytecodeIndex);
     UNUSED_PARAM(map);
 #if ENABLE(DFG_JIT)
-    ExitSiteData exitSiteData = computeExitSiteData(locker, profiledBlock, bytecodeIndex);
+    ExitSiteData exitSiteData = computeExitSiteData(profiledBlock, bytecodeIndex);
     
     CallLinkInfo* callLinkInfo = map.get(CodeOrigin(bytecodeIndex));
     if (!callLinkInfo) {
@@ -102,17 +102,18 @@ CallLinkStatus CallLinkStatus::computeFor(
 #endif
 }
 
-CallLinkStatus::ExitSiteData CallLinkStatus::computeExitSiteData(
-    const ConcurrentJSLocker& locker, CodeBlock* profiledBlock, unsigned bytecodeIndex)
+CallLinkStatus::ExitSiteData CallLinkStatus::computeExitSiteData(CodeBlock* profiledBlock, unsigned bytecodeIndex)
 {
     ExitSiteData exitSiteData;
-    
 #if ENABLE(DFG_JIT)
+    UnlinkedCodeBlock* codeBlock = profiledBlock->unlinkedCodeBlock();
+    ConcurrentJSLocker locker(codeBlock->m_lock);
+
     exitSiteData.takesSlowPath =
-        profiledBlock->hasExitSite(locker, DFG::FrequentExitSite(bytecodeIndex, BadType))
-        || profiledBlock->hasExitSite(locker, DFG::FrequentExitSite(bytecodeIndex, BadExecutable));
+        codeBlock->hasExitSite(locker, DFG::FrequentExitSite(bytecodeIndex, BadType))
+        || codeBlock->hasExitSite(locker, DFG::FrequentExitSite(bytecodeIndex, BadExecutable));
     exitSiteData.badFunction =
-        profiledBlock->hasExitSite(locker, DFG::FrequentExitSite(bytecodeIndex, BadCell));
+        codeBlock->hasExitSite(locker, DFG::FrequentExitSite(bytecodeIndex, BadCell));
 #else
     UNUSED_PARAM(locker);
     UNUSED_PARAM(profiledBlock);
@@ -275,12 +276,7 @@ void CallLinkStatus::computeDFGStatuses(
         // InlineCallFrames.
         CodeBlock* currentBaseline =
             baselineCodeBlockForOriginAndBaselineCodeBlock(codeOrigin, baselineCodeBlock);
-        ExitSiteData exitSiteData;
-        {
-            ConcurrentJSLocker locker(currentBaseline->m_lock);
-            exitSiteData = computeExitSiteData(
-                locker, currentBaseline, codeOrigin.bytecodeIndex);
-        }
+        ExitSiteData exitSiteData = computeExitSiteData(currentBaseline, codeOrigin.bytecodeIndex);
         
         {
             ConcurrentJSLocker locker(dfgCodeBlock->m_lock);
index 1024ae7..61d0ee7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012-2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2012-2018 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -67,7 +67,7 @@ public:
         bool takesSlowPath { false };
         bool badFunction { false };
     };
-    static ExitSiteData computeExitSiteData(const ConcurrentJSLocker&, CodeBlock*, unsigned bytecodeIndex);
+    static ExitSiteData computeExitSiteData(CodeBlock*, unsigned bytecodeIndex);
     
 #if ENABLE(JIT)
     // Computes the status assuming that we never took slow path and never previously
index c7acb01..601e4ce 100644 (file)
@@ -40,7 +40,6 @@
 #include "CompilationResult.h"
 #include "ConcurrentJSLock.h"
 #include "DFGCommon.h"
-#include "DFGExitProfile.h"
 #include "DirectEvalCodeCache.h"
 #include "EvalExecutable.h"
 #include "ExecutionCounter.h"
@@ -512,25 +511,6 @@ public:
         return codeOrigins()[index.bits()];
     }
 
-    bool addFrequentExitSite(const DFG::FrequentExitSite& site)
-    {
-        ASSERT(JITCode::isBaselineCode(jitType()));
-        ConcurrentJSLocker locker(m_lock);
-        return m_exitProfile.add(locker, this, site);
-    }
-
-    bool hasExitSite(const ConcurrentJSLocker& locker, const DFG::FrequentExitSite& site) const
-    {
-        return m_exitProfile.hasExitSite(locker, site);
-    }
-    bool hasExitSite(const DFG::FrequentExitSite& site) const
-    {
-        ConcurrentJSLocker locker(m_lock);
-        return hasExitSite(locker, site);
-    }
-
-    DFG::ExitProfile& exitProfile() { return m_exitProfile; }
-
     CompressedLazyOperandValueProfileHolder& lazyOperandValueProfiles()
     {
         return m_lazyOperandValueProfiles;
@@ -1019,7 +999,6 @@ private:
 #if ENABLE(DFG_JIT)
     // This is relevant to non-DFG code blocks that serve as the profiled code block
     // for DFG code blocks.
-    DFG::ExitProfile m_exitProfile;
     CompressedLazyOperandValueProfileHolder m_lazyOperandValueProfiles;
 #endif
     RefCountedArray<ValueProfile> m_argumentValueProfiles;
index 64fe9a3..9aa536a 100644 (file)
@@ -41,32 +41,35 @@ void FrequentExitSite::dump(PrintStream& out) const
 ExitProfile::ExitProfile() { }
 ExitProfile::~ExitProfile() { }
 
-bool ExitProfile::add(const ConcurrentJSLocker&, CodeBlock* owner, const FrequentExitSite& site)
+bool ExitProfile::add(CodeBlock* owner, const FrequentExitSite& site)
 {
+    ConcurrentJSLocker locker(owner->unlinkedCodeBlock()->m_lock);
     ASSERT(site.jitType() != ExitFromAnything);
 
     CODEBLOCK_LOG_EVENT(owner, "frequentExit", (site));
     
     if (Options::verboseExitProfile())
         dataLog(pointerDump(owner), ": Adding exit site: ", site, "\n");
+
+    ExitProfile& profile = owner->unlinkedCodeBlock()->exitProfile();
     
     // If we've never seen any frequent exits then create the list and put this site
     // into it.
-    if (!m_frequentExitSites) {
-        m_frequentExitSites = std::make_unique<Vector<FrequentExitSite>>();
-        m_frequentExitSites->append(site);
+    if (!profile.m_frequentExitSites) {
+        profile.m_frequentExitSites = std::make_unique<Vector<FrequentExitSite>>();
+        profile.m_frequentExitSites->append(site);
         return true;
     }
     
     // Don't add it if it's already there. This is O(n), but that's OK, because we
     // know that the total number of places where code exits tends to not be large,
     // and this code is only used when recompilation is triggered.
-    for (unsigned i = 0; i < m_frequentExitSites->size(); ++i) {
-        if (m_frequentExitSites->at(i) == site)
+    for (unsigned i = 0; i < profile.m_frequentExitSites->size(); ++i) {
+        if (profile.m_frequentExitSites->at(i) == site)
             return false;
     }
     
-    m_frequentExitSites->append(site);
+    profile.m_frequentExitSites->append(site);
     return true;
 }
 
@@ -100,8 +103,10 @@ bool ExitProfile::hasExitSite(const ConcurrentJSLocker&, const FrequentExitSite&
 QueryableExitProfile::QueryableExitProfile() { }
 QueryableExitProfile::~QueryableExitProfile() { }
 
-void QueryableExitProfile::initialize(const ConcurrentJSLocker&, const ExitProfile& profile)
+void QueryableExitProfile::initialize(UnlinkedCodeBlock* unlinkedCodeBlock)
 {
+    ConcurrentJSLocker locker(unlinkedCodeBlock->m_lock);
+    const ExitProfile& profile = unlinkedCodeBlock->exitProfile();
     if (!profile.m_frequentExitSites)
         return;
     
index ce55749..be18487 100644 (file)
@@ -160,7 +160,7 @@ public:
     // be called a fixed number of times per recompilation. Recompilation is
     // rare to begin with, and implies doing O(n) operations on the CodeBlock
     // anyway.
-    bool add(const ConcurrentJSLocker&, CodeBlock* owner, const FrequentExitSite&);
+    static bool add(CodeBlock*, const FrequentExitSite&);
     
     // Get the frequent exit sites for a bytecode index. This is O(n), and is
     // meant to only be used from debugging/profiling code.
@@ -175,10 +175,6 @@ public:
     {
         return hasExitSite(locker, FrequentExitSite(kind));
     }
-    bool hasExitSite(const ConcurrentJSLocker& locker, unsigned bytecodeIndex, ExitKind kind) const
-    {
-        return hasExitSite(locker, FrequentExitSite(bytecodeIndex, kind));
-    }
     
 private:
     friend class QueryableExitProfile;
@@ -191,7 +187,7 @@ public:
     QueryableExitProfile();
     ~QueryableExitProfile();
     
-    void initialize(const ConcurrentJSLocker&, const ExitProfile&);
+    void initialize(UnlinkedCodeBlock*);
 
     bool hasExitSite(const FrequentExitSite& site) const
     {
index cc0a247..6038026 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012-2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2012-2018 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -65,10 +65,12 @@ bool GetByIdStatus::appendVariant(const GetByIdVariant& variant)
 }
 
 #if ENABLE(DFG_JIT)
-bool GetByIdStatus::hasExitSite(const ConcurrentJSLocker& locker, CodeBlock* profiledBlock, unsigned bytecodeIndex)
+bool GetByIdStatus::hasExitSite(CodeBlock* profiledBlock, unsigned bytecodeIndex)
 {
-    return profiledBlock->hasExitSite(locker, DFG::FrequentExitSite(bytecodeIndex, BadCache))
-        || profiledBlock->hasExitSite(locker, DFG::FrequentExitSite(bytecodeIndex, BadConstantCache));
+    UnlinkedCodeBlock* unlinkedCodeBlock = profiledBlock->unlinkedCodeBlock();
+    ConcurrentJSLocker locker(unlinkedCodeBlock->m_lock);
+    return unlinkedCodeBlock->hasExitSite(locker, DFG::FrequentExitSite(bytecodeIndex, BadCache))
+        || unlinkedCodeBlock->hasExitSite(locker, DFG::FrequentExitSite(bytecodeIndex, BadConstantCache));
 }
 #endif
 
@@ -119,10 +121,10 @@ GetByIdStatus GetByIdStatus::computeFor(CodeBlock* profiledBlock, StubInfoMap& m
 #if ENABLE(DFG_JIT)
     result = computeForStubInfoWithoutExitSiteFeedback(
         locker, profiledBlock, map.get(CodeOrigin(bytecodeIndex)), uid,
-        CallLinkStatus::computeExitSiteData(locker, profiledBlock, bytecodeIndex));
+        CallLinkStatus::computeExitSiteData(profiledBlock, bytecodeIndex));
     
     if (!result.takesSlowPath()
-        && hasExitSite(locker, profiledBlock, bytecodeIndex))
+        && hasExitSite(profiledBlock, bytecodeIndex))
         return GetByIdStatus(result.makesCalls() ? MakesCalls : TakesSlowPath, true);
 #else
     UNUSED_PARAM(map);
@@ -139,9 +141,9 @@ GetByIdStatus GetByIdStatus::computeForStubInfo(const ConcurrentJSLocker& locker
 {
     GetByIdStatus result = GetByIdStatus::computeForStubInfoWithoutExitSiteFeedback(
         locker, profiledBlock, stubInfo, uid,
-        CallLinkStatus::computeExitSiteData(locker, profiledBlock, codeOrigin.bytecodeIndex));
+        CallLinkStatus::computeExitSiteData(profiledBlock, codeOrigin.bytecodeIndex));
 
-    if (!result.takesSlowPath() && GetByIdStatus::hasExitSite(locker, profiledBlock, codeOrigin.bytecodeIndex))
+    if (!result.takesSlowPath() && GetByIdStatus::hasExitSite(profiledBlock, codeOrigin.bytecodeIndex))
         return GetByIdStatus(result.makesCalls() ? GetByIdStatus::MakesCalls : GetByIdStatus::TakesSlowPath, true);
     return result;
 }
@@ -328,7 +330,7 @@ GetByIdStatus GetByIdStatus::computeFor(
         {
             ConcurrentJSLocker locker(profiledBlock->m_lock);
             exitSiteData = CallLinkStatus::computeExitSiteData(
-                locker, profiledBlock, codeOrigin.bytecodeIndex);
+                profiledBlock, codeOrigin.bytecodeIndex);
         }
         
         GetByIdStatus result;
@@ -341,11 +343,8 @@ GetByIdStatus GetByIdStatus::computeFor(
         if (result.takesSlowPath())
             return result;
     
-        {
-            ConcurrentJSLocker locker(profiledBlock->m_lock);
-            if (hasExitSite(locker, profiledBlock, codeOrigin.bytecodeIndex))
-                return GetByIdStatus(TakesSlowPath, true);
-        }
+        if (hasExitSite(profiledBlock, codeOrigin.bytecodeIndex))
+            return GetByIdStatus(TakesSlowPath, true);
         
         if (result.isSet())
             return result;
index bc346dc..1d662c9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012, 2013, 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2012-2018 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -119,7 +119,7 @@ public:
     
 private:
 #if ENABLE(DFG_JIT)
-    static bool hasExitSite(const ConcurrentJSLocker&, CodeBlock*, unsigned bytecodeIndex);
+    static bool hasExitSite(CodeBlock*, unsigned bytecodeIndex);
 #endif
 #if ENABLE(JIT)
     GetByIdStatus(const ModuleNamespaceAccessCase&);
index 739e008..d25e58c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012-2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2012-2018 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -55,11 +55,12 @@ bool PutByIdStatus::appendVariant(const PutByIdVariant& variant)
 }
 
 #if ENABLE(DFG_JIT)
-bool PutByIdStatus::hasExitSite(const ConcurrentJSLocker& locker, CodeBlock* profiledBlock, unsigned bytecodeIndex)
+bool PutByIdStatus::hasExitSite(CodeBlock* profiledBlock, unsigned bytecodeIndex)
 {
-    return profiledBlock->hasExitSite(locker, DFG::FrequentExitSite(bytecodeIndex, BadCache))
-        || profiledBlock->hasExitSite(locker, DFG::FrequentExitSite(bytecodeIndex, BadConstantCache));
-    
+    UnlinkedCodeBlock* unlinkedCodeBlock = profiledBlock->unlinkedCodeBlock();
+    ConcurrentJSLocker locker(unlinkedCodeBlock->m_lock);
+    return unlinkedCodeBlock->hasExitSite(locker, DFG::FrequentExitSite(bytecodeIndex, BadCache))
+        || unlinkedCodeBlock->hasExitSite(locker, DFG::FrequentExitSite(bytecodeIndex, BadConstantCache));
 }
 #endif
 
@@ -117,13 +118,13 @@ PutByIdStatus PutByIdStatus::computeFor(CodeBlock* profiledBlock, StubInfoMap& m
     UNUSED_PARAM(bytecodeIndex);
     UNUSED_PARAM(uid);
 #if ENABLE(DFG_JIT)
-    if (hasExitSite(locker, profiledBlock, bytecodeIndex))
+    if (hasExitSite(profiledBlock, bytecodeIndex))
         return PutByIdStatus(TakesSlowPath);
     
     StructureStubInfo* stubInfo = map.get(CodeOrigin(bytecodeIndex));
     PutByIdStatus result = computeForStubInfo(
         locker, profiledBlock, stubInfo, uid,
-        CallLinkStatus::computeExitSiteData(locker, profiledBlock, bytecodeIndex));
+        CallLinkStatus::computeExitSiteData(profiledBlock, bytecodeIndex));
     if (!result)
         return computeFromLLInt(profiledBlock, bytecodeIndex, uid);
     
@@ -139,7 +140,7 @@ PutByIdStatus PutByIdStatus::computeForStubInfo(const ConcurrentJSLocker& locker
 {
     return computeForStubInfo(
         locker, baselineBlock, stubInfo, uid,
-        CallLinkStatus::computeExitSiteData(locker, baselineBlock, codeOrigin.bytecodeIndex));
+        CallLinkStatus::computeExitSiteData(baselineBlock, codeOrigin.bytecodeIndex));
 }
 
 PutByIdStatus PutByIdStatus::computeForStubInfo(
@@ -267,13 +268,13 @@ PutByIdStatus PutByIdStatus::computeFor(CodeBlock* baselineBlock, CodeBlock* dfg
 {
 #if ENABLE(DFG_JIT)
     if (dfgBlock) {
+        if (hasExitSite(baselineBlock, codeOrigin.bytecodeIndex))
+            return PutByIdStatus(TakesSlowPath);
         CallLinkStatus::ExitSiteData exitSiteData;
         {
             ConcurrentJSLocker locker(baselineBlock->m_lock);
-            if (hasExitSite(locker, baselineBlock, codeOrigin.bytecodeIndex))
-                return PutByIdStatus(TakesSlowPath);
             exitSiteData = CallLinkStatus::computeExitSiteData(
-                locker, baselineBlock, codeOrigin.bytecodeIndex);
+                baselineBlock, codeOrigin.bytecodeIndex);
         }
             
         PutByIdStatus result;
index 2b0c2b6..b5cd56a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012, 2013, 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2012-2018 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -95,7 +95,7 @@ public:
     
 private:
 #if ENABLE(DFG_JIT)
-    static bool hasExitSite(const ConcurrentJSLocker&, CodeBlock*, unsigned bytecodeIndex);
+    static bool hasExitSite(CodeBlock*, unsigned bytecodeIndex);
 #endif
 #if ENABLE(JIT)
     static PutByIdStatus computeForStubInfo(
index 90010b5..71f1ca5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012-2017 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2012-2018 Apple Inc. All Rights Reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -422,12 +422,11 @@ BytecodeLivenessAnalysis& UnlinkedCodeBlock::livenessAnalysisSlow(CodeBlock* cod
 {
     RELEASE_ASSERT(codeBlock->unlinkedCodeBlock() == this);
 
-
     {
-        auto locker = holdLock(m_lock);
+        ConcurrentJSLocker locker(m_lock);
         if (!m_liveness) {
             // There is a chance two compiler threads raced to the slow path.
-            // We defend against computing liveness twice.
+            // Grabbing the lock above defends against computing liveness twice.
             m_liveness = std::make_unique<BytecodeLivenessAnalysis>(codeBlock);
         }
     }
index 7e1ae6b..b24dfdc 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "BytecodeConventions.h"
 #include "CodeType.h"
+#include "DFGExitProfile.h"
 #include "ExpressionRangeInfo.h"
 #include "HandlerInfo.h"
 #include "Identifier.h"
@@ -383,6 +384,21 @@ public:
         return livenessAnalysisSlow(codeBlock);
     }
 
+#if ENABLE(DFG_JIT)
+    bool hasExitSite(const ConcurrentJSLocker& locker, const DFG::FrequentExitSite& site) const
+    {
+        return m_exitProfile.hasExitSite(locker, site);
+    }
+
+    bool hasExitSite(const DFG::FrequentExitSite& site)
+    {
+        ConcurrentJSLocker locker(m_lock);
+        return hasExitSite(locker, site);
+    }
+
+    DFG::ExitProfile& exitProfile() { return m_exitProfile; }
+#endif
+
 protected:
     UnlinkedCodeBlock(VM*, Structure*, CodeType, const ExecutableInfo&, DebuggerMode);
     ~UnlinkedCodeBlock();
@@ -419,6 +435,10 @@ private:
     String m_sourceURLDirective;
     String m_sourceMappingURLDirective;
 
+#if ENABLE(DFG_JIT)
+    DFG::ExitProfile m_exitProfile;
+#endif
+
     unsigned m_usesEval : 1;
     unsigned m_isStrictMode : 1;
     unsigned m_isConstructor : 1;
@@ -436,7 +456,9 @@ private:
     unsigned m_lineCount;
     unsigned m_endColumn;
 
-    Lock m_lock;
+public:
+    ConcurrentJSLock m_lock;
+private:
     TriState m_didOptimize;
     SourceParseMode m_parseMode;
     CodeFeatures m_features;
index 403bc38..6176d65 100644 (file)
@@ -6394,9 +6394,10 @@ ByteCodeParser::InlineStackEntry::InlineStackEntry(
     , m_caller(byteCodeParser->m_inlineStackTop)
 {
     {
+        m_exitProfile.initialize(m_profiledBlock->unlinkedCodeBlock());
+
         ConcurrentJSLocker locker(m_profiledBlock->m_lock);
         m_lazyOperands.initialize(locker, m_profiledBlock->lazyOperandValueProfiles());
-        m_exitProfile.initialize(locker, profiledBlock->exitProfile());
         
         // We do this while holding the lock because we want to encourage StructureStubInfo's
         // to be potentially added to operations and because the profiled block could be in the
index 874e185..24fa08b 100644 (file)
@@ -469,12 +469,12 @@ public:
     
     bool hasGlobalExitSite(const CodeOrigin& codeOrigin, ExitKind exitKind)
     {
-        return baselineCodeBlockFor(codeOrigin)->hasExitSite(FrequentExitSite(exitKind));
+        return baselineCodeBlockFor(codeOrigin)->unlinkedCodeBlock()->hasExitSite(FrequentExitSite(exitKind));
     }
     
     bool hasExitSite(const CodeOrigin& codeOrigin, ExitKind exitKind)
     {
-        return baselineCodeBlockFor(codeOrigin)->hasExitSite(FrequentExitSite(codeOrigin.bytecodeIndex, exitKind));
+        return baselineCodeBlockFor(codeOrigin)->unlinkedCodeBlock()->hasExitSite(FrequentExitSite(codeOrigin.bytecodeIndex, exitKind));
     }
     
     bool hasExitSite(Node* node, ExitKind exitKind)
index ef7d647..6da2dc3 100644 (file)
@@ -281,7 +281,7 @@ private:
             && !m_graph.m_controlEquivalenceAnalysis->dominatesEquivalently(data.preHeader, fromBlock);
         
         if (addsBlindSpeculation
-            && m_graph.baselineCodeBlockFor(originalOrigin.semantic)->hasExitSite(FrequentExitSite(HoistingFailed))) {
+            && m_graph.hasExitSite(originalOrigin.semantic, HoistingFailed)) {
             if (verbose) {
                 dataLog(
                     "    Not hoisting ", node, " because it may exit and the pre-header (",
index 7bd5f04..d719f9f 100644 (file)
@@ -47,7 +47,7 @@ void OSRExitBase::considerAddingAsFrequentExitSiteSlow(CodeBlock* profiledCodeBl
             site = FrequentExitSite(HoistingFailed, jitType);
         else
             site = FrequentExitSite(m_codeOriginForExitProfile.bytecodeIndex, m_kind, jitType);
-        sourceProfiledCodeBlock->addFrequentExitSite(site);
+        ExitProfile::add(sourceProfiledCodeBlock, site);
     }
 }