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