1// Copyright 2018 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#if !V8_ENABLE_WEBASSEMBLY
6#error This header should only be included if WebAssembly is enabled.
7#endif  // !V8_ENABLE_WEBASSEMBLY
8
9#ifndef V8_WASM_WASM_IMPORT_WRAPPER_CACHE_H_
10#define V8_WASM_WASM_IMPORT_WRAPPER_CACHE_H_
11
12#include "src/base/platform/mutex.h"
13#include "src/compiler/wasm-compiler.h"
14
15namespace v8 {
16namespace internal {
17
18class Counters;
19
20namespace wasm {
21
22class WasmCode;
23class WasmEngine;
24
25using FunctionSig = Signature<ValueType>;
26
27// Implements a cache for import wrappers.
28class WasmImportWrapperCache {
29 public:
30  struct CacheKey {
31    CacheKey(const compiler::WasmImportCallKind& _kind, const FunctionSig* _sig,
32             int _expected_arity, Suspend _suspend)
33        : kind(_kind),
34          signature(_sig),
35          expected_arity(_expected_arity == kDontAdaptArgumentsSentinel
36                             ? 0
37                             : _expected_arity),
38          suspend(_suspend) {}
39
40    bool operator==(const CacheKey& rhs) const {
41      return kind == rhs.kind && signature == rhs.signature &&
42             expected_arity == rhs.expected_arity && suspend == rhs.suspend;
43    }
44
45    compiler::WasmImportCallKind kind;
46    const FunctionSig* signature;
47    int expected_arity;
48    Suspend suspend;
49  };
50
51  class CacheKeyHash {
52   public:
53    size_t operator()(const CacheKey& key) const {
54      return base::hash_combine(static_cast<uint8_t>(key.kind), key.signature,
55                                key.expected_arity);
56    }
57  };
58
59  // Helper class to modify the cache under a lock.
60  class V8_NODISCARD ModificationScope {
61   public:
62    explicit ModificationScope(WasmImportWrapperCache* cache)
63        : cache_(cache), guard_(&cache->mutex_) {}
64
65    V8_EXPORT_PRIVATE WasmCode*& operator[](const CacheKey& key);
66
67   private:
68    WasmImportWrapperCache* const cache_;
69    base::MutexGuard guard_;
70  };
71
72  // Not thread-safe, use ModificationScope to get exclusive write access to the
73  // cache.
74  V8_EXPORT_PRIVATE WasmCode*& operator[](const CacheKey& key);
75
76  // Thread-safe. Assumes the key exists in the map.
77  V8_EXPORT_PRIVATE WasmCode* Get(compiler::WasmImportCallKind kind,
78                                  const FunctionSig* sig, int expected_arity,
79                                  Suspend suspend) const;
80  // Thread-safe. Returns nullptr if the key doesn't exist in the map.
81  WasmCode* MaybeGet(compiler::WasmImportCallKind kind, const FunctionSig* sig,
82                     int expected_arity, Suspend suspend) const;
83
84  ~WasmImportWrapperCache();
85
86 private:
87  mutable base::Mutex mutex_;
88  std::unordered_map<CacheKey, WasmCode*, CacheKeyHash> entry_map_;
89};
90
91}  // namespace wasm
92}  // namespace internal
93}  // namespace v8
94
95#endif  // V8_WASM_WASM_IMPORT_WRAPPER_CACHE_H_
96