summaryrefslogtreecommitdiff
path: root/runtime/class_table.h
blob: af25131ab4296efbe7dc135171227ef38b9b1459 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ART_RUNTIME_CLASS_TABLE_H_
#define ART_RUNTIME_CLASS_TABLE_H_

#include <string>
#include <utility>
#include <vector>

#include "base/allocator.h"
#include "base/hash_set.h"
#include "base/macros.h"
#include "base/mutex.h"
#include "dex_file.h"
#include "gc_root.h"
#include "object_callbacks.h"
#include "runtime.h"

namespace art {

namespace mirror {
  class ClassLoader;
}  // namespace mirror

typedef bool (ClassVisitor)(mirror::Class* c, void* arg);

// Each loader has a ClassTable
class ClassTable {
 public:
  ClassTable();

  // Used by image writer for checking.
  bool Contains(mirror::Class* klass)
      REQUIRES(Locks::classlinker_classes_lock_) SHARED_REQUIRES(Locks::mutator_lock_);

  // Freeze the current class tables by allocating a new table and never updating or modifying the
  // existing table. This helps prevents dirty pages after caused by inserting after zygote fork.
  void FreezeSnapshot()
      REQUIRES(Locks::classlinker_classes_lock_) SHARED_REQUIRES(Locks::mutator_lock_);

  // Returns the number of classes in previous snapshots.
  size_t NumZygoteClasses() const REQUIRES(Locks::classlinker_classes_lock_);

  // Returns all off the classes in the lastest snapshot.
  size_t NumNonZygoteClasses() const REQUIRES(Locks::classlinker_classes_lock_);

  // Update a class in the table with the new class. Returns the existing class which was replaced.
  mirror::Class* UpdateClass(const char* descriptor, mirror::Class* new_klass, size_t hash)
      REQUIRES(Locks::classlinker_classes_lock_) SHARED_REQUIRES(Locks::mutator_lock_);

  void VisitRoots(RootVisitor* visitor, VisitRootFlags flags)
      REQUIRES(Locks::classlinker_classes_lock_) SHARED_REQUIRES(Locks::mutator_lock_);

  // Return false if the callback told us to exit.
  bool Visit(ClassVisitor* visitor, void* arg)
      REQUIRES(Locks::classlinker_classes_lock_) SHARED_REQUIRES(Locks::mutator_lock_);

  mirror::Class* Lookup(const char* descriptor, size_t hash)
      SHARED_REQUIRES(Locks::classlinker_classes_lock_, Locks::mutator_lock_);

  void Insert(mirror::Class* klass)
      REQUIRES(Locks::classlinker_classes_lock_) SHARED_REQUIRES(Locks::mutator_lock_);
  void InsertWithHash(mirror::Class* klass, size_t hash)
      REQUIRES(Locks::classlinker_classes_lock_) SHARED_REQUIRES(Locks::mutator_lock_);

  // Returns true if the class was found and removed, false otherwise.
  bool Remove(const char* descriptor)
      REQUIRES(Locks::classlinker_classes_lock_) SHARED_REQUIRES(Locks::mutator_lock_);

 private:
  class ClassDescriptorHashEquals {
   public:
    // Same class loader and descriptor.
    std::size_t operator()(const GcRoot<mirror::Class>& root) const NO_THREAD_SAFETY_ANALYSIS;
    bool operator()(const GcRoot<mirror::Class>& a, const GcRoot<mirror::Class>& b) const
        NO_THREAD_SAFETY_ANALYSIS;;
    // Same descriptor.
    bool operator()(const GcRoot<mirror::Class>& a, const char* descriptor) const
        NO_THREAD_SAFETY_ANALYSIS;
    std::size_t operator()(const char* descriptor) const NO_THREAD_SAFETY_ANALYSIS;
  };
  class GcRootEmptyFn {
   public:
    void MakeEmpty(GcRoot<mirror::Class>& item) const {
      item = GcRoot<mirror::Class>();
    }
    bool IsEmpty(const GcRoot<mirror::Class>& item) const {
      return item.IsNull();
    }
  };
  // hash set which hashes class descriptor, and compares descriptors nad class loaders. Results
  // should be compared for a matching Class descriptor and class loader.
  typedef HashSet<GcRoot<mirror::Class>, GcRootEmptyFn, ClassDescriptorHashEquals,
      ClassDescriptorHashEquals, TrackingAllocator<GcRoot<mirror::Class>, kAllocatorTagClassTable>>
      ClassSet;

  // TODO: shard lock to have one per class loader.
  std::vector<ClassSet> classes_ GUARDED_BY(Locks::classlinker_classes_lock_);
};

}  // namespace art

#endif  // ART_RUNTIME_CLASS_TABLE_H_