DFGExitProfile.cpp
1 /* 2 * Copyright (C) 2011, 2016 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #include "config.h" 27 #include "DFGExitProfile.h" 28 29 #if ENABLE(DFG_JIT) 30 31 #include "CodeBlock.h" 32 #include "VMInlines.h" 33 34 namespace JSC { namespace DFG { 35 36 void FrequentExitSite::dump(PrintStream& out) const 37 { 38 out.print(m_bytecodeIndex, ": ", m_kind, "/", m_jitType, "/", m_inlineKind); 39 } 40 41 ExitProfile::ExitProfile() { } 42 ExitProfile::~ExitProfile() { } 43 44 bool ExitProfile::add(CodeBlock* owner, const FrequentExitSite& site) 45 { 46 RELEASE_ASSERT(site.jitType() != ExitFromAnything); 47 RELEASE_ASSERT(site.inlineKind() != ExitFromAnyInlineKind); 48 49 ConcurrentJSLocker locker(owner->unlinkedCodeBlock()->m_lock); 50 51 CODEBLOCK_LOG_EVENT(owner, "frequentExit", (site)); 52 53 dataLogLnIf(Options::verboseExitProfile(), pointerDump(owner), ": Adding exit site: ", site); 54 55 ExitProfile& profile = owner->unlinkedCodeBlock()->exitProfile(); 56 57 // If we've never seen any frequent exits then create the list and put this site 58 // into it. 59 if (!profile.m_frequentExitSites) { 60 profile.m_frequentExitSites = makeUnique<Vector<FrequentExitSite>>(); 61 profile.m_frequentExitSites->append(site); 62 return true; 63 } 64 65 // Don't add it if it's already there. This is O(n), but that's OK, because we 66 // know that the total number of places where code exits tends to not be large, 67 // and this code is only used when recompilation is triggered. 68 for (unsigned i = 0; i < profile.m_frequentExitSites->size(); ++i) { 69 if (profile.m_frequentExitSites->at(i) == site) 70 return false; 71 } 72 73 profile.m_frequentExitSites->append(site); 74 return true; 75 } 76 77 Vector<FrequentExitSite> ExitProfile::exitSitesFor(BytecodeIndex bytecodeIndex) 78 { 79 Vector<FrequentExitSite> result; 80 81 if (!m_frequentExitSites) 82 return result; 83 84 for (unsigned i = 0; i < m_frequentExitSites->size(); ++i) { 85 if (m_frequentExitSites->at(i).bytecodeIndex() == bytecodeIndex) 86 result.append(m_frequentExitSites->at(i)); 87 } 88 89 return result; 90 } 91 92 bool ExitProfile::hasExitSite(const ConcurrentJSLocker&, const FrequentExitSite& site) const 93 { 94 if (!m_frequentExitSites) 95 return false; 96 97 for (unsigned i = m_frequentExitSites->size(); i--;) { 98 if (site.subsumes(m_frequentExitSites->at(i))) 99 return true; 100 } 101 return false; 102 } 103 104 QueryableExitProfile::QueryableExitProfile() { } 105 QueryableExitProfile::~QueryableExitProfile() { } 106 107 void QueryableExitProfile::initialize(UnlinkedCodeBlock* unlinkedCodeBlock) 108 { 109 ConcurrentJSLocker locker(unlinkedCodeBlock->m_lock); 110 const ExitProfile& profile = unlinkedCodeBlock->exitProfile(); 111 if (!profile.m_frequentExitSites) 112 return; 113 114 for (unsigned i = 0; i < profile.m_frequentExitSites->size(); ++i) 115 m_frequentExitSites.add(profile.m_frequentExitSites->at(i)); 116 } 117 118 } } // namespace JSC::DFG 119 120 #endif