blob: 9d5e062ef5de073e1d5d57989f3ffcb6c8bdd7b5 [file]
// 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_OBJECTS_API_CALLBACKS_INL_H_
#define V8_OBJECTS_API_CALLBACKS_INL_H_
#include "src/objects/api-callbacks.h"
// Include the non-inl header before the rest of the headers.
#include <algorithm>
#include "src/heap/heap-write-barrier-inl.h"
#include "src/heap/heap-write-barrier.h"
#include "src/objects/foreign-inl.h"
#include "src/objects/heap-object-field-inl.h"
#include "src/objects/js-objects-inl.h"
#include "src/objects/name.h"
#include "src/objects/oddball.h"
#include "src/objects/templates.h"
#include "src/utils/memcopy.h"
// Has to be the last include (doesn't have include guards):
#include "src/objects/object-macros.h"
namespace v8 {
namespace internal {
// Make sure that Api can read Data value from both AccessorInfo and
// InterceptorInfo without checking the type.
static_assert(Internals::kCallbackInfoDataOffset ==
offsetof(AccessorInfo, data_));
static_assert(Internals::kCallbackInfoDataOffset ==
offsetof(InterceptorInfo, data_));
Tagged<UnionOf<Foreign, Smi, Undefined>> AccessCheckInfo::callback() const {
return callback_.load();
}
void AccessCheckInfo::set_callback(
Tagged<UnionOf<Foreign, Smi, Undefined>> value, WriteBarrierMode mode) {
callback_.store(this, value, mode);
}
Tagged<UnionOf<InterceptorInfo, Smi, Undefined>>
AccessCheckInfo::named_interceptor() const {
return named_interceptor_.load();
}
void AccessCheckInfo::set_named_interceptor(
Tagged<UnionOf<InterceptorInfo, Smi, Undefined>> value,
WriteBarrierMode mode) {
named_interceptor_.store(this, value, mode);
}
Tagged<UnionOf<InterceptorInfo, Smi, Undefined>>
AccessCheckInfo::indexed_interceptor() const {
return indexed_interceptor_.load();
}
void AccessCheckInfo::set_indexed_interceptor(
Tagged<UnionOf<InterceptorInfo, Smi, Undefined>> value,
WriteBarrierMode mode) {
indexed_interceptor_.store(this, value, mode);
}
Tagged<Object> AccessCheckInfo::data() const { return data_.load(); }
void AccessCheckInfo::set_data(Tagged<Object> value, WriteBarrierMode mode) {
data_.store(this, value, mode);
}
// AccessorInfo.
Tagged<Object> AccessorInfo::data() const { return data_.load(); }
void AccessorInfo::set_data(Tagged<Object> value, WriteBarrierMode mode) {
data_.store(this, value, mode);
}
Tagged<Name> AccessorInfo::name() const { return name_.load(); }
void AccessorInfo::set_name(Tagged<Name> value, WriteBarrierMode mode) {
name_.store(this, value, mode);
}
uint32_t AccessorInfo::flags() const { return flags_; }
void AccessorInfo::set_flags(uint32_t value) { flags_ = value; }
// InterceptorInfo.
Tagged<Object> InterceptorInfo::data() const { return data_.load(); }
void InterceptorInfo::set_data(Tagged<Object> value, WriteBarrierMode mode) {
data_.store(this, value, mode);
}
uint32_t InterceptorInfo::flags() const { return flags_; }
void InterceptorInfo::set_flags(uint32_t value) { flags_ = value; }
REDIRECTED_CALLBACK_ACCESSORS_MAYBE_READ_ONLY_HOST(
AccessorInfo, getter, Address, offsetof(AccessorInfo, getter_),
kAccessorInfoGetterTag, ExternalReference::DIRECT_GETTER_CALL)
EXTERNAL_POINTER_ACCESSORS_MAYBE_READ_ONLY_HOST(AccessorInfo, setter, Address,
offsetof(AccessorInfo, setter_),
kAccessorInfoSetterTag)
bool AccessorInfo::has_getter(Isolate* isolate) {
return getter(isolate) != kNullAddress;
}
bool AccessorInfo::has_setter(Isolate* isolate) {
return setter(isolate) != kNullAddress;
}
BIT_FIELD_ACCESSORS(AccessorInfo, flags, replace_on_access,
AccessorInfo::ReplaceOnAccessBit)
BIT_FIELD_ACCESSORS(AccessorInfo, flags, is_sloppy, AccessorInfo::IsSloppyBit)
BIT_FIELD_ACCESSORS(AccessorInfo, flags, getter_side_effect_type,
AccessorInfo::GetterSideEffectTypeBits)
SideEffectType AccessorInfo::setter_side_effect_type() const {
return SetterSideEffectTypeBits::decode(flags());
}
void AccessorInfo::set_setter_side_effect_type(SideEffectType value) {
// We do not support describing setters as having no side effect, since
// calling set accessors must go through a store bytecode. Store bytecodes
// support checking receivers for temporary objects, but still expect
// the receiver to be written to.
CHECK_NE(value, SideEffectType::kHasNoSideEffect);
set_flags(SetterSideEffectTypeBits::update(flags(), value));
}
BIT_FIELD_ACCESSORS(AccessorInfo, flags, initial_property_attributes,
AccessorInfo::InitialAttributesBits)
void AccessorInfo::RemoveCallbackRedirectionForSerialization(
IsolateForSandbox isolate) {
CHECK(USE_SIMULATOR_BOOL);
remove_getter_redirection(isolate);
}
void AccessorInfo::RestoreCallbackRedirectionAfterDeserialization(
IsolateForSandbox isolate) {
CHECK(USE_SIMULATOR_BOOL);
init_getter_redirection(isolate);
}
void AccessorInfo::clear_padding() {
if (FIELD_SIZE(kOptionalPaddingOffset) == 0) return;
std::fill_n(reinterpret_cast<uint8_t*>(address() + kOptionalPaddingOffset),
FIELD_SIZE(kOptionalPaddingOffset), 0);
}
// For the purpose of checking whether the respective callback field is
// initialized we can use any of the named/indexed versions.
#define INTERCEPTOR_INFO_HAS_GETTER(name) \
bool InterceptorInfo::has_##name() const { return has_named_##name(); }
INTERCEPTOR_INFO_HAS_GETTER(getter)
INTERCEPTOR_INFO_HAS_GETTER(setter)
INTERCEPTOR_INFO_HAS_GETTER(query)
INTERCEPTOR_INFO_HAS_GETTER(descriptor)
INTERCEPTOR_INFO_HAS_GETTER(deleter)
INTERCEPTOR_INFO_HAS_GETTER(definer)
INTERCEPTOR_INFO_HAS_GETTER(enumerator)
bool InterceptorInfo::has_index_of() const { return has_indexed_index_of(); }
bool InterceptorInfo::has_iterable_to_list() const {
return has_indexed_iterable_to_list();
}
#undef INTERCEPTOR_INFO_HAS_GETTER
LAZY_REDIRECTED_CALLBACK_ACCESSORS_MAYBE_READ_ONLY_HOST_CHECKED2(
InterceptorInfo, named_getter, Address, offsetof(InterceptorInfo, getter_),
kApiNamedPropertyGetterCallbackTag, ExternalReference::DIRECT_GETTER_CALL,
is_named(), is_named() && (value != kNullAddress))
LAZY_REDIRECTED_CALLBACK_ACCESSORS_MAYBE_READ_ONLY_HOST_CHECKED2(
InterceptorInfo, named_setter, Address, offsetof(InterceptorInfo, setter_),
kApiNamedPropertySetterCallbackTag, ExternalReference::DIRECT_SETTER_CALL,
is_named(), is_named() && (value != kNullAddress))
LAZY_EXTERNAL_POINTER_ACCESSORS_MAYBE_READ_ONLY_HOST_CHECKED2(
InterceptorInfo, named_query, Address, offsetof(InterceptorInfo, query_),
kApiNamedPropertyQueryCallbackTag, is_named(),
is_named() && (value != kNullAddress))
LAZY_EXTERNAL_POINTER_ACCESSORS_MAYBE_READ_ONLY_HOST_CHECKED2(
InterceptorInfo, named_descriptor, Address,
offsetof(InterceptorInfo, descriptor_),
kApiNamedPropertyDescriptorCallbackTag, is_named(),
is_named() && (value != kNullAddress))
LAZY_EXTERNAL_POINTER_ACCESSORS_MAYBE_READ_ONLY_HOST_CHECKED2(
InterceptorInfo, named_deleter, Address,
offsetof(InterceptorInfo, deleter_), kApiNamedPropertyDeleterCallbackTag,
is_named(), is_named() && (value != kNullAddress))
LAZY_EXTERNAL_POINTER_ACCESSORS_MAYBE_READ_ONLY_HOST_CHECKED2(
InterceptorInfo, named_enumerator, Address,
offsetof(InterceptorInfo, enumerator_),
kApiNamedPropertyEnumeratorCallbackTag, is_named(),
is_named() && (value != kNullAddress))
LAZY_EXTERNAL_POINTER_ACCESSORS_MAYBE_READ_ONLY_HOST_CHECKED2(
InterceptorInfo, named_definer, Address,
offsetof(InterceptorInfo, definer_), kApiNamedPropertyDefinerCallbackTag,
is_named(), is_named() && (value != kNullAddress))
LAZY_EXTERNAL_POINTER_ACCESSORS_MAYBE_READ_ONLY_HOST_CHECKED2(
InterceptorInfo, indexed_getter, Address,
offsetof(InterceptorInfo, getter_), kApiIndexedPropertyGetterCallbackTag,
!is_named(), !is_named() && (value != kNullAddress))
LAZY_EXTERNAL_POINTER_ACCESSORS_MAYBE_READ_ONLY_HOST_CHECKED2(
InterceptorInfo, indexed_setter, Address,
offsetof(InterceptorInfo, setter_), kApiIndexedPropertySetterCallbackTag,
!is_named(), !is_named() && (value != kNullAddress))
LAZY_EXTERNAL_POINTER_ACCESSORS_MAYBE_READ_ONLY_HOST_CHECKED2(
InterceptorInfo, indexed_query, Address, offsetof(InterceptorInfo, query_),
kApiIndexedPropertyQueryCallbackTag, !is_named(),
!is_named() && (value != kNullAddress))
LAZY_EXTERNAL_POINTER_ACCESSORS_MAYBE_READ_ONLY_HOST_CHECKED2(
InterceptorInfo, indexed_descriptor, Address,
offsetof(InterceptorInfo, descriptor_),
kApiIndexedPropertyDescriptorCallbackTag, !is_named(),
!is_named() && (value != kNullAddress))
LAZY_EXTERNAL_POINTER_ACCESSORS_MAYBE_READ_ONLY_HOST_CHECKED2(
InterceptorInfo, indexed_deleter, Address,
offsetof(InterceptorInfo, deleter_), kApiIndexedPropertyDeleterCallbackTag,
!is_named(), !is_named() && (value != kNullAddress))
LAZY_EXTERNAL_POINTER_ACCESSORS_MAYBE_READ_ONLY_HOST_CHECKED2(
InterceptorInfo, indexed_enumerator, Address,
offsetof(InterceptorInfo, enumerator_),
kApiIndexedPropertyEnumeratorCallbackTag, !is_named(),
!is_named() && (value != kNullAddress))
LAZY_EXTERNAL_POINTER_ACCESSORS_MAYBE_READ_ONLY_HOST_CHECKED2(
InterceptorInfo, indexed_definer, Address,
offsetof(InterceptorInfo, definer_), kApiIndexedPropertyDefinerCallbackTag,
!is_named(), !is_named() && (value != kNullAddress))
LAZY_EXTERNAL_POINTER_ACCESSORS_MAYBE_READ_ONLY_HOST_CHECKED2(
InterceptorInfo, indexed_index_of, Address,
offsetof(InterceptorInfo, index_of_), kApiIndexedPropertyIndexOfCallbackTag,
!is_named(), !is_named() && (value != kNullAddress))
LAZY_EXTERNAL_POINTER_ACCESSORS_MAYBE_READ_ONLY_HOST_CHECKED2(
InterceptorInfo, indexed_iterable_to_list, Address,
offsetof(InterceptorInfo, iterable_to_list_),
kApiIndexedPropertyIterableToListCallbackTag, !is_named(),
!is_named() && (value != kNullAddress))
BOOL_ACCESSORS(InterceptorInfo, flags, can_intercept_symbols,
CanInterceptSymbolsBit::kShift)
BOOL_ACCESSORS(InterceptorInfo, flags, non_masking, NonMaskingBit::kShift)
BOOL_GETTER(InterceptorInfo, flags, is_named, NamedBit::kShift)
BOOL_ACCESSORS(InterceptorInfo, flags, has_no_side_effect,
HasNoSideEffectBit::kShift)
// TODO(ishell): remove once all the Api changes are done.
BOOL_ACCESSORS(InterceptorInfo, flags, has_new_callbacks_signature,
HasNewCallbacksSignatureBit::kShift)
BOOL_ACCESSORS(InterceptorInfo, flags, has_dont_delete_property,
HasDontDeletePropertyBit::kShift)
void InterceptorInfo::RemoveCallbackRedirectionForSerialization(
IsolateForSandbox isolate) {
CHECK(USE_SIMULATOR_BOOL);
if (is_named()) {
remove_named_getter_redirection(isolate);
}
}
void InterceptorInfo::RestoreCallbackRedirectionAfterDeserialization(
IsolateForSandbox isolate) {
CHECK(USE_SIMULATOR_BOOL);
if (is_named()) {
init_named_getter_redirection(isolate);
}
}
void InterceptorInfo::clear_padding() {
if (FIELD_SIZE(kOptionalPaddingOffset) == 0) return;
std::fill_n(reinterpret_cast<uint8_t*>(address() + kOptionalPaddingOffset),
FIELD_SIZE(kOptionalPaddingOffset), 0);
}
// Returns holder object suitable for Api callbacks - in case the holder is
// JSGlobalObject returns respective JSGlobalProxy.
inline Tagged<JSObject> GetHolderForApi(Tagged<JSObject> holder) {
Tagged<JSGlobalObject> global_object;
if (TryCast<JSGlobalObject>(holder, &global_object)) {
Tagged<JSGlobalProxy> global_proxy = global_object->global_proxy_for_api();
DCHECK(!global_proxy->IsDetachedFrom(global_object));
return global_proxy;
}
return Cast<JSObject>(holder);
}
} // namespace internal
} // namespace v8
#include "src/objects/object-macros-undef.h"
#endif // V8_OBJECTS_API_CALLBACKS_INL_H_