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/roots/roots.h"
25
26 namespace v8 {
27 namespace internal {
28
29 V8_INLINE constexpr bool operator<(RootIndex lhs, RootIndex rhs) {
30 using type = typename std::underlying_type<RootIndex>::type;
31 return static_cast<type>(lhs) < static_cast<type>(rhs);
32 }
33
34 V8_INLINE RootIndex
35 operator++(RootIndex& index) { // NOLINT(runtime/references)
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