1// Copyright 2020 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#include "src/heap/code-object-registry.h"
6
7#include <algorithm>
8
9#include "src/base/logging.h"
10
11namespace v8 {
12namespace internal {
13
14void CodeObjectRegistry::RegisterNewlyAllocatedCodeObject(Address code) {
15  base::MutexGuard guard(&code_object_registry_mutex_);
16  if (is_sorted_) {
17    is_sorted_ =
18        (code_object_registry_.empty() || code_object_registry_.back() < code);
19  }
20  code_object_registry_.push_back(code);
21}
22
23void CodeObjectRegistry::RegisterAlreadyExistingCodeObject(Address code) {
24  // This function is not protected by the mutex, and should only be called
25  // by the sweeper.
26  DCHECK(is_sorted_);
27  DCHECK(code_object_registry_.empty() || code_object_registry_.back() < code);
28  code_object_registry_.push_back(code);
29}
30
31void CodeObjectRegistry::Clear() {
32  // This function is not protected by the mutex, and should only be called
33  // by the sweeper.
34  code_object_registry_.clear();
35  is_sorted_ = true;
36}
37
38void CodeObjectRegistry::Finalize() {
39  // This function is not protected by the mutex, and should only be called
40  // by the sweeper.
41  DCHECK(is_sorted_);
42  code_object_registry_.shrink_to_fit();
43}
44
45bool CodeObjectRegistry::Contains(Address object) const {
46  base::MutexGuard guard(&code_object_registry_mutex_);
47  if (!is_sorted_) {
48    std::sort(code_object_registry_.begin(), code_object_registry_.end());
49    is_sorted_ = true;
50  }
51  return (std::binary_search(code_object_registry_.begin(),
52                             code_object_registry_.end(), object));
53}
54
55Address CodeObjectRegistry::GetCodeObjectStartFromInnerAddress(
56    Address address) const {
57  base::MutexGuard guard(&code_object_registry_mutex_);
58  if (!is_sorted_) {
59    std::sort(code_object_registry_.begin(), code_object_registry_.end());
60    is_sorted_ = true;
61  }
62
63  // The code registry can't be empty, else the code object can't exist.
64  DCHECK(!code_object_registry_.empty());
65
66  // std::upper_bound returns the first code object strictly greater than
67  // address, so the code object containing the address has to be the previous
68  // one.
69  auto it = std::upper_bound(code_object_registry_.begin(),
70                             code_object_registry_.end(), address);
71  // The address has to be contained in a code object, so necessarily the
72  // address can't be smaller than the first code object.
73  DCHECK_NE(it, code_object_registry_.begin());
74  return *(--it);
75}
76
77}  // namespace internal
78}  // namespace v8
79