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 #ifndef V8_ROOTS_ROOTS_INL_H_
6 #define V8_ROOTS_ROOTS_INL_H_
7 
8 #include "src/execution/isolate.h"
9 #include "src/execution/local-isolate.h"
10 #include "src/handles/handles.h"
11 #include "src/heap/read-only-heap.h"
12 #include "src/objects/api-callbacks.h"
13 #include "src/objects/descriptor-array.h"
14 #include "src/objects/feedback-vector.h"
15 #include "src/objects/heap-number.h"
16 #include "src/objects/literal-objects.h"
17 #include "src/objects/map.h"
18 #include "src/objects/oddball.h"
19 #include "src/objects/property-array.h"
20 #include "src/objects/property-cell.h"
21 #include "src/objects/scope-info.h"
22 #include "src/objects/slots.h"
23 #include "src/objects/string.h"
24 #include "src/objects/swiss-name-dictionary.h"
25 #include "src/roots/roots.h"
26 
27 namespace v8 {
28 namespace internal {
29 
30 V8_INLINE constexpr bool operator<(RootIndex lhs, RootIndex rhs) {
31   using type = typename std::underlying_type<RootIndex>::type;
32   return static_cast<type>(lhs) < static_cast<type>(rhs);
33 }
34 
35 V8_INLINE RootIndex operator++(RootIndex& index) {
36   using type = typename std::underlying_type<RootIndex>::type;
37   index = static_cast<RootIndex>(static_cast<type>(index) + 1);
38   return index;
39 }
40 
IsRootHandleLocation(Address * handle_location,RootIndex * index)41 bool RootsTable::IsRootHandleLocation(Address* handle_location,
42                                       RootIndex* index) const {
43   FullObjectSlot location(handle_location);
44   FullObjectSlot first_root(&roots_[0]);
45   FullObjectSlot last_root(&roots_[kEntriesCount]);
46   if (location >= last_root) return false;
47   if (location < first_root) return false;
48   *index = static_cast<RootIndex>(location - first_root);
49   return true;
50 }
51 
52 template <typename T>
IsRootHandle(Handle<T> handle,RootIndex * index)53 bool RootsTable::IsRootHandle(Handle<T> handle, RootIndex* index) const {
54   // This can't use handle.location() because it is called from places
55   // where handle dereferencing is disallowed. Comparing the handle's
56   // location against the root handle list is safe though.
57   Address* handle_location = reinterpret_cast<Address*>(handle.address());
58   return IsRootHandleLocation(handle_location, index);
59 }
60 
ReadOnlyRoots(Heap * heap)61 ReadOnlyRoots::ReadOnlyRoots(Heap* heap)
62     : ReadOnlyRoots(Isolate::FromHeap(heap)) {}
63 
ReadOnlyRoots(Isolate * isolate)64 ReadOnlyRoots::ReadOnlyRoots(Isolate* isolate)
65     : read_only_roots_(reinterpret_cast<Address*>(
66           isolate->roots_table().read_only_roots_begin().address())) {}
67 
ReadOnlyRoots(LocalIsolate * isolate)68 ReadOnlyRoots::ReadOnlyRoots(LocalIsolate* isolate)
69     : ReadOnlyRoots(isolate->factory()->read_only_roots()) {}
70 
71 // We use unchecked_cast below because we trust our read-only roots to
72 // have the right type, and to avoid the heavy #includes that would be
73 // required for checked casts.
74 
75 #define ROOT_ACCESSOR(Type, name, CamelName)                  \
76   Type ReadOnlyRoots::name() const {                          \
77     DCHECK(CheckType_##name());                               \
78     return unchecked_##name();                                \
79   }                                                           \
80   Type ReadOnlyRoots::unchecked_##name() const {              \
81     return Type::unchecked_cast(                              \
82         Object(*GetLocation(RootIndex::k##CamelName)));       \
83   }                                                           \
84   Handle<Type> ReadOnlyRoots::name##_handle() const {         \
85     DCHECK(CheckType_##name());                               \
86     Address* location = GetLocation(RootIndex::k##CamelName); \
87     return Handle<Type>(location);                            \
88   }
89 
READ_ONLY_ROOT_LIST(ROOT_ACCESSOR)90 READ_ONLY_ROOT_LIST(ROOT_ACCESSOR)
91 #undef ROOT_ACCESSOR
92 
93 Address* ReadOnlyRoots::GetLocation(RootIndex root_index) const {
94   size_t index = static_cast<size_t>(root_index);
95   DCHECK_LT(index, kEntriesCount);
96   return &read_only_roots_[index];
97 }
98 
at(RootIndex root_index)99 Address ReadOnlyRoots::at(RootIndex root_index) const {
100   return *GetLocation(root_index);
101 }
102 
103 }  // namespace internal
104 }  // namespace v8
105 
106 #endif  // V8_ROOTS_ROOTS_INL_H_
107