/ bytecode / DirectEvalCodeCache.h
DirectEvalCodeCache.h
  1  /*
  2   * Copyright (C) 2008-2019 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   *
  8   * 1.  Redistributions of source code must retain the above copyright
  9   *     notice, this list of conditions and the following disclaimer.
 10   * 2.  Redistributions in binary form must reproduce the above copyright
 11   *     notice, this list of conditions and the following disclaimer in the
 12   *     documentation and/or other materials provided with the distribution.
 13   * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
 14   *     its contributors may be used to endorse or promote products derived
 15   *     from this software without specific prior written permission.
 16   *
 17   * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
 18   * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 19   * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 20   * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
 21   * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 22   * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 23   * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 24   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 25   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 26   * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 27   */
 28  
 29  #pragma once
 30  
 31  #include "DirectEvalExecutable.h"
 32  #include <wtf/HashMap.h>
 33  #include <wtf/RefPtr.h>
 34  #include <wtf/text/StringHash.h>
 35  
 36  namespace JSC {
 37  
 38      class SlotVisitor;
 39  
 40      class DirectEvalCodeCache {
 41      public:
 42          class CacheKey {
 43          public:
 44              CacheKey(const String& source, CallSiteIndex callSiteIndex)
 45                  : m_source(source.impl())
 46                  , m_callSiteIndex(callSiteIndex)
 47              {
 48              }
 49  
 50              CacheKey(WTF::HashTableDeletedValueType)
 51                  : m_source(WTF::HashTableDeletedValue)
 52              {
 53              }
 54  
 55              CacheKey() = default;
 56  
 57              unsigned hash() const { return m_source->hash() ^ m_callSiteIndex.bits(); }
 58  
 59              bool isEmptyValue() const { return !m_source; }
 60  
 61              bool operator==(const CacheKey& other) const
 62              {
 63                  return m_callSiteIndex == other.m_callSiteIndex && WTF::equal(m_source.get(), other.m_source.get());
 64              }
 65  
 66              bool isHashTableDeletedValue() const { return m_source.isHashTableDeletedValue(); }
 67  
 68              struct Hash {
 69                  static unsigned hash(const CacheKey& key)
 70                  {
 71                      return key.hash();
 72                  }
 73                  static bool equal(const CacheKey& lhs, const CacheKey& rhs)
 74                  {
 75                      return lhs == rhs;
 76                  }
 77                  static constexpr bool safeToCompareToEmptyOrDeleted = false;
 78              };
 79  
 80              typedef SimpleClassHashTraits<CacheKey> HashTraits;
 81  
 82          private:
 83              RefPtr<StringImpl> m_source;
 84              CallSiteIndex m_callSiteIndex;
 85          };
 86  
 87          DirectEvalExecutable* tryGet(const String& evalSource, CallSiteIndex callSiteIndex)
 88          {
 89              return m_cacheMap.inlineGet(CacheKey(evalSource, callSiteIndex)).get();
 90          }
 91          
 92          void set(JSGlobalObject* globalObject, JSCell* owner, const String& evalSource, CallSiteIndex callSiteIndex, DirectEvalExecutable* evalExecutable)
 93          {
 94              if (m_cacheMap.size() < maxCacheEntries)
 95                  setSlow(globalObject, owner, evalSource, callSiteIndex, evalExecutable);
 96          }
 97  
 98          bool isEmpty() const { return m_cacheMap.isEmpty(); }
 99  
100          void visitAggregate(SlotVisitor&);
101  
102          void clear();
103  
104      private:
105          static constexpr int maxCacheEntries = 64;
106  
107          void setSlow(JSGlobalObject*, JSCell* owner, const String& evalSource, CallSiteIndex, DirectEvalExecutable*);
108  
109          typedef HashMap<CacheKey, WriteBarrier<DirectEvalExecutable>, CacheKey::Hash, CacheKey::HashTraits> EvalCacheMap;
110          EvalCacheMap m_cacheMap;
111          Lock m_lock;
112      };
113  
114  } // namespace JSC