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_OBJECTS_API_CALLBACKS_INL_H_
6#define V8_OBJECTS_API_CALLBACKS_INL_H_
7
8#include "src/objects/api-callbacks.h"
9
10#include "src/heap/heap-write-barrier-inl.h"
11#include "src/heap/heap-write-barrier.h"
12#include "src/objects/foreign-inl.h"
13#include "src/objects/js-objects-inl.h"
14#include "src/objects/name.h"
15#include "src/objects/templates.h"
16
17// Has to be the last include (doesn't have include guards):
18#include "src/objects/object-macros.h"
19
20namespace v8 {
21namespace internal {
22
23#include "torque-generated/src/objects/api-callbacks-tq-inl.inc"
24
25TQ_OBJECT_CONSTRUCTORS_IMPL(AccessCheckInfo)
26TQ_OBJECT_CONSTRUCTORS_IMPL(AccessorInfo)
27TQ_OBJECT_CONSTRUCTORS_IMPL(InterceptorInfo)
28
29TQ_OBJECT_CONSTRUCTORS_IMPL(CallHandlerInfo)
30
31ACCESSORS_CHECKED2(AccessorInfo, getter, Object, kGetterOffset, true,
32                   Foreign::IsNormalized(value))
33ACCESSORS_CHECKED2(AccessorInfo, setter, Object, kSetterOffset, true,
34                   Foreign::IsNormalized(value))
35
36bool AccessorInfo::has_getter() {
37  bool result = getter() != Smi::zero();
38  DCHECK_EQ(result,
39            getter() != Smi::zero() &&
40                Foreign::cast(getter()).foreign_address() != kNullAddress);
41  return result;
42}
43
44bool AccessorInfo::has_setter() {
45  bool result = setter() != Smi::zero();
46  DCHECK_EQ(result,
47            setter() != Smi::zero() &&
48                Foreign::cast(setter()).foreign_address() != kNullAddress);
49  return result;
50}
51
52BIT_FIELD_ACCESSORS(AccessorInfo, flags, all_can_read,
53                    AccessorInfo::AllCanReadBit)
54BIT_FIELD_ACCESSORS(AccessorInfo, flags, all_can_write,
55                    AccessorInfo::AllCanWriteBit)
56BIT_FIELD_ACCESSORS(AccessorInfo, flags, is_special_data_property,
57                    AccessorInfo::IsSpecialDataPropertyBit)
58BIT_FIELD_ACCESSORS(AccessorInfo, flags, replace_on_access,
59                    AccessorInfo::ReplaceOnAccessBit)
60BIT_FIELD_ACCESSORS(AccessorInfo, flags, is_sloppy, AccessorInfo::IsSloppyBit)
61BIT_FIELD_ACCESSORS(AccessorInfo, flags, getter_side_effect_type,
62                    AccessorInfo::GetterSideEffectTypeBits)
63
64SideEffectType AccessorInfo::setter_side_effect_type() const {
65  return SetterSideEffectTypeBits::decode(flags());
66}
67
68void AccessorInfo::set_setter_side_effect_type(SideEffectType value) {
69  // We do not support describing setters as having no side effect, since
70  // calling set accessors must go through a store bytecode. Store bytecodes
71  // support checking receivers for temporary objects, but still expect
72  // the receiver to be written to.
73  CHECK_NE(value, SideEffectType::kHasNoSideEffect);
74  set_flags(SetterSideEffectTypeBits::update(flags(), value));
75}
76
77BIT_FIELD_ACCESSORS(AccessorInfo, flags, initial_property_attributes,
78                    AccessorInfo::InitialAttributesBits)
79
80bool AccessorInfo::IsCompatibleReceiver(Object receiver) {
81  if (!HasExpectedReceiverType()) return true;
82  if (!receiver.IsJSObject()) return false;
83  return FunctionTemplateInfo::cast(expected_receiver_type())
84      .IsTemplateFor(JSObject::cast(receiver).map());
85}
86
87bool AccessorInfo::HasExpectedReceiverType() {
88  return expected_receiver_type().IsFunctionTemplateInfo();
89}
90
91BOOL_ACCESSORS(InterceptorInfo, flags, can_intercept_symbols,
92               CanInterceptSymbolsBit::kShift)
93BOOL_ACCESSORS(InterceptorInfo, flags, all_can_read, AllCanReadBit::kShift)
94BOOL_ACCESSORS(InterceptorInfo, flags, non_masking, NonMaskingBit::kShift)
95BOOL_ACCESSORS(InterceptorInfo, flags, is_named, NamedBit::kShift)
96BOOL_ACCESSORS(InterceptorInfo, flags, has_no_side_effect,
97               HasNoSideEffectBit::kShift)
98
99bool CallHandlerInfo::IsSideEffectFreeCallHandlerInfo() const {
100  ReadOnlyRoots roots = GetReadOnlyRoots();
101  DCHECK(map() == roots.side_effect_call_handler_info_map() ||
102         map() == roots.side_effect_free_call_handler_info_map() ||
103         map() == roots.next_call_side_effect_free_call_handler_info_map());
104  return map() == roots.side_effect_free_call_handler_info_map();
105}
106
107bool CallHandlerInfo::IsSideEffectCallHandlerInfo() const {
108  ReadOnlyRoots roots = GetReadOnlyRoots();
109  DCHECK(map() == roots.side_effect_call_handler_info_map() ||
110         map() == roots.side_effect_free_call_handler_info_map() ||
111         map() == roots.next_call_side_effect_free_call_handler_info_map());
112  return map() == roots.side_effect_call_handler_info_map();
113}
114
115void CallHandlerInfo::SetNextCallHasNoSideEffect() {
116  set_map(
117      GetReadOnlyRoots().next_call_side_effect_free_call_handler_info_map());
118}
119
120bool CallHandlerInfo::NextCallHasNoSideEffect() {
121  ReadOnlyRoots roots = GetReadOnlyRoots();
122  if (map() == roots.next_call_side_effect_free_call_handler_info_map()) {
123    set_map(roots.side_effect_call_handler_info_map());
124    return true;
125  }
126  return false;
127}
128
129}  // namespace internal
130}  // namespace v8
131
132#include "src/objects/object-macros-undef.h"
133
134#endif  // V8_OBJECTS_API_CALLBACKS_INL_H_
135