1014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Copyright 2015 the V8 project authors. All rights reserved.
2014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Use of this source code is governed by a BSD-style license that can be
3014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// found in the LICENSE file.
4014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
5014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#ifndef V8_IDENTITY_MAP_H_
6014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define V8_IDENTITY_MAP_H_
7014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
8342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch#include "src/base/functional.h"
9014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/handles.h"
10014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
11014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochnamespace v8 {
12014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochnamespace internal {
13014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
14014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Forward declarations.
15014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochclass Heap;
16014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochclass Zone;
17014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
18014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Base class of identity maps contains shared code for all template
19014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// instantions.
20014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochclass IdentityMapBase {
21014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch protected:
22014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Allow Tester to access internals, including changing the address of objects
23014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // within the {keys_} array in order to simulate a moving GC.
24014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  friend class IdentityMapTester;
25014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
26014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  typedef void** RawEntry;
27014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
28014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  IdentityMapBase(Heap* heap, Zone* zone)
29014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      : heap_(heap),
30014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        zone_(zone),
31014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        gc_counter_(-1),
32014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        size_(0),
33014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        mask_(0),
34014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        keys_(nullptr),
35014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        values_(nullptr) {}
36014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ~IdentityMapBase();
37014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
38014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  RawEntry GetEntry(Object* key);
39014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  RawEntry FindEntry(Object* key);
40342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  void Clear();
41014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
42014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch private:
43014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Internal implementation should not be called directly by subclasses.
44014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int LookupIndex(Object* address);
45014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int InsertIndex(Object* address);
46014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void Rehash();
47014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void Resize();
48014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  RawEntry Lookup(Object* key);
49014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  RawEntry Insert(Object* key);
50014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int Hash(Object* address);
51014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
52342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  base::hash<uintptr_t> hasher_;
53014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Heap* heap_;
54014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Zone* zone_;
55014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int gc_counter_;
56014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int size_;
57014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int mask_;
58014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Object** keys_;
59014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void** values_;
60014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch};
61014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
62014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Implements an identity map from object addresses to a given value type {V}.
63014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// The map is robust w.r.t. garbage collection by synchronization with the
64014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// supplied {heap}.
65014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch//  * Keys are treated as strong roots.
66014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch//  * SMIs are valid keys, except SMI #0.
67014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch//  * The value type {V} must be reinterpret_cast'able to {void*}
68014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch//  * The value type {V} must not be a heap type.
69014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochtemplate <typename V>
70014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochclass IdentityMap : public IdentityMapBase {
71014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch public:
72014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  IdentityMap(Heap* heap, Zone* zone) : IdentityMapBase(heap, zone) {}
73014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
74014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Searches this map for the given key using the object's address
75014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // as the identity, returning:
76014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  //    found => a pointer to the storage location for the value
77014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  //    not found => a pointer to a new storage location for the value
78014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V* Get(Handle<Object> key) { return Get(*key); }
79014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V* Get(Object* key) { return reinterpret_cast<V*>(GetEntry(key)); }
80014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
81014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Searches this map for the given key using the object's address
82014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // as the identity, returning:
83014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  //    found => a pointer to the storage location for the value
84014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  //    not found => {nullptr}
85014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V* Find(Handle<Object> key) { return Find(*key); }
86014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V* Find(Object* key) { return reinterpret_cast<V*>(FindEntry(key)); }
87014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
88014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Set the value for the given key.
89014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void Set(Handle<Object> key, V v) { Set(*key, v); }
90014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void Set(Object* key, V v) { *(reinterpret_cast<V*>(GetEntry(key))) = v; }
91342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch
92342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  // Removes all elements from the map.
93342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  void Clear() { IdentityMapBase::Clear(); }
94014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch};
95014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace internal
96014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace v8
97014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
98014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#endif  // V8_IDENTITY_MAP_H_
99