// Copyright 2018 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef V8_ROOTS_INL_H_ #define V8_ROOTS_INL_H_ #include "src/roots.h" #include "src/feedback-vector.h" #include "src/handles.h" #include "src/isolate.h" #include "src/objects/api-callbacks.h" #include "src/objects/descriptor-array.h" #include "src/objects/heap-number.h" #include "src/objects/literal-objects.h" #include "src/objects/map.h" #include "src/objects/oddball.h" #include "src/objects/property-array.h" #include "src/objects/property-cell.h" #include "src/objects/scope-info.h" #include "src/objects/slots.h" #include "src/objects/string.h" namespace v8 { namespace internal { V8_INLINE constexpr bool operator<(RootIndex lhs, RootIndex rhs) { typedef typename std::underlying_type::type type; return static_cast(lhs) < static_cast(rhs); } V8_INLINE RootIndex operator++(RootIndex& index) { typedef typename std::underlying_type::type type; index = static_cast(static_cast(index) + 1); return index; } bool RootsTable::IsRootHandleLocation(Address* handle_location, RootIndex* index) const { FullObjectSlot location(handle_location); FullObjectSlot first_root(&roots_[0]); FullObjectSlot last_root(&roots_[kEntriesCount]); if (location >= last_root) return false; if (location < first_root) return false; *index = static_cast(location - first_root); return true; } template bool RootsTable::IsRootHandle(Handle handle, RootIndex* index) const { // This can't use handle.location() because it is called from places // where handle dereferencing is disallowed. Comparing the handle's // location against the root handle list is safe though. Address* handle_location = reinterpret_cast(handle.address()); return IsRootHandleLocation(handle_location, index); } ReadOnlyRoots::ReadOnlyRoots(Heap* heap) : roots_table_(Isolate::FromHeap(heap)->roots_table()) {} ReadOnlyRoots::ReadOnlyRoots(Isolate* isolate) : roots_table_(isolate->roots_table()) {} // We use unchecked_cast below because we trust our read-only roots to // have the right type, and to avoid the heavy #includes that would be // required for checked casts. #define ROOT_ACCESSOR(Type, name, CamelName) \ Type ReadOnlyRoots::name() const { \ DCHECK(CheckType(RootIndex::k##CamelName)); \ return Type::unchecked_cast( \ Object(roots_table_[RootIndex::k##CamelName])); \ } \ Handle ReadOnlyRoots::name##_handle() const { \ DCHECK(CheckType(RootIndex::k##CamelName)); \ return Handle(&roots_table_[RootIndex::k##CamelName]); \ } READ_ONLY_ROOT_LIST(ROOT_ACCESSOR) #undef ROOT_ACCESSOR Map ReadOnlyRoots::MapForFixedTypedArray(ExternalArrayType array_type) { RootIndex root_index = RootsTable::RootIndexForFixedTypedArray(array_type); DCHECK(CheckType(root_index)); return Map::unchecked_cast(Object(roots_table_[root_index])); } Map ReadOnlyRoots::MapForFixedTypedArray(ElementsKind elements_kind) { RootIndex root_index = RootsTable::RootIndexForFixedTypedArray(elements_kind); DCHECK(CheckType(root_index)); return Map::unchecked_cast(Object(roots_table_[root_index])); } FixedTypedArrayBase ReadOnlyRoots::EmptyFixedTypedArrayForTypedArray( ElementsKind elements_kind) { RootIndex root_index = RootsTable::RootIndexForEmptyFixedTypedArray(elements_kind); DCHECK(CheckType(root_index)); return FixedTypedArrayBase::unchecked_cast(Object(roots_table_[root_index])); } } // namespace internal } // namespace v8 #endif // V8_ROOTS_INL_H_