/ bytecode / CallLinkStatus.h
CallLinkStatus.h
  1  /*
  2   * Copyright (C) 2012-2018 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  #pragma once
 27  
 28  #include "CallLinkInfo.h"
 29  #include "CallVariant.h"
 30  #include "CodeOrigin.h"
 31  #include "ConcurrentJSLock.h"
 32  #include "ExitFlag.h"
 33  #include "ICStatusMap.h"
 34  #include "JSCJSValue.h"
 35  
 36  namespace JSC {
 37  
 38  class CodeBlock;
 39  class InternalFunction;
 40  class JSFunction;
 41  class Structure;
 42  class CallLinkInfo;
 43  
 44  class CallLinkStatus final {
 45      WTF_MAKE_FAST_ALLOCATED;
 46  public:
 47      CallLinkStatus()
 48      {
 49      }
 50      
 51      static CallLinkStatus takesSlowPath()
 52      {
 53          CallLinkStatus result;
 54          result.m_couldTakeSlowPath = true;
 55          return result;
 56      }
 57      
 58      explicit CallLinkStatus(JSValue);
 59      
 60      CallLinkStatus(CallVariant variant)
 61          : m_variants(1, variant)
 62      {
 63      }
 64      
 65      struct ExitSiteData {
 66          ExitFlag takesSlowPath;
 67          ExitFlag badFunction;
 68      };
 69      static ExitSiteData computeExitSiteData(CodeBlock*, BytecodeIndex);
 70      
 71      static CallLinkStatus computeFor(CodeBlock*, BytecodeIndex, const ICStatusMap&, ExitSiteData);
 72      static CallLinkStatus computeFor(CodeBlock*, BytecodeIndex, const ICStatusMap&);
 73  
 74  #if ENABLE(JIT)
 75      // Computes the status assuming that we never took slow path and never previously
 76      // exited.
 77      static CallLinkStatus computeFor(const ConcurrentJSLocker&, CodeBlock*, CallLinkInfo&);
 78      
 79      // Computes the status accounting for exits.
 80      static CallLinkStatus computeFor(
 81          const ConcurrentJSLocker&, CodeBlock*, CallLinkInfo&, ExitSiteData, ExitingInlineKind = ExitFromAnyInlineKind);
 82  #endif
 83      
 84      static CallLinkStatus computeFor(
 85          CodeBlock*, CodeOrigin, const ICStatusMap&, const ICStatusContextStack&);
 86      
 87      void setProvenConstantCallee(CallVariant);
 88      
 89      bool isSet() const { return !m_variants.isEmpty() || m_couldTakeSlowPath; }
 90      
 91      explicit operator bool() const { return isSet(); }
 92      
 93      bool couldTakeSlowPath() const { return m_couldTakeSlowPath; }
 94      
 95      void setCouldTakeSlowPath(bool value) { m_couldTakeSlowPath = value; }
 96      
 97      CallVariantList variants() const { return m_variants; }
 98      unsigned size() const { return m_variants.size(); }
 99      CallVariant at(unsigned i) const { return m_variants[i]; }
100      CallVariant operator[](unsigned i) const { return at(i); }
101      bool isProved() const { return m_isProved; }
102      bool isBasedOnStub() const { return m_isBasedOnStub; }
103      bool canOptimize() const { return !m_variants.isEmpty(); }
104  
105      bool isClosureCall() const; // Returns true if any callee is a closure call.
106      
107      unsigned maxArgumentCountIncludingThis() const { return m_maxArgumentCountIncludingThis; }
108      
109      bool finalize(VM&);
110      
111      void merge(const CallLinkStatus&);
112      
113      void filter(VM&, JSValue);
114      
115      void dump(PrintStream&) const;
116      
117  private:
118      void makeClosureCall();
119      
120      static CallLinkStatus computeFromLLInt(const ConcurrentJSLocker&, CodeBlock*, BytecodeIndex);
121  #if ENABLE(JIT)
122      static CallLinkStatus computeFromCallLinkInfo(
123          const ConcurrentJSLocker&, CallLinkInfo&);
124  #endif
125      
126      void accountForExits(ExitSiteData, ExitingInlineKind);
127      
128      CallVariantList m_variants;
129      bool m_couldTakeSlowPath { false };
130      bool m_isProved { false };
131      bool m_isBasedOnStub { false };
132      unsigned m_maxArgumentCountIncludingThis { 0 };
133  };
134  
135  } // namespace JSC