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 
20 namespace v8 {
21 namespace internal {
22 
23 #include "torque-generated/src/objects/api-callbacks-tq-inl.inc"
24 
25 TQ_OBJECT_CONSTRUCTORS_IMPL(AccessCheckInfo)
TQ_OBJECT_CONSTRUCTORS_IMPL(AccessorInfo)26 TQ_OBJECT_CONSTRUCTORS_IMPL(AccessorInfo)
27 TQ_OBJECT_CONSTRUCTORS_IMPL(InterceptorInfo)
28 
29 TQ_OBJECT_CONSTRUCTORS_IMPL(CallHandlerInfo)
30 
31 ACCESSORS_CHECKED2(AccessorInfo, getter, Object, kGetterOffset, true,
32                    Foreign::IsNormalized(value))
33 ACCESSORS_CHECKED2(AccessorInfo, setter, Object, kSetterOffset, true,
34                    Foreign::IsNormalized(value))
35 
36 bool 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 
has_setter()44 bool 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 
BIT_FIELD_ACCESSORS(AccessorInfo,flags,all_can_read,AccessorInfo::AllCanReadBit)52 BIT_FIELD_ACCESSORS(AccessorInfo, flags, all_can_read,
53                     AccessorInfo::AllCanReadBit)
54 BIT_FIELD_ACCESSORS(AccessorInfo, flags, all_can_write,
55                     AccessorInfo::AllCanWriteBit)
56 BIT_FIELD_ACCESSORS(AccessorInfo, flags, is_special_data_property,
57                     AccessorInfo::IsSpecialDataPropertyBit)
58 BIT_FIELD_ACCESSORS(AccessorInfo, flags, replace_on_access,
59                     AccessorInfo::ReplaceOnAccessBit)
60 BIT_FIELD_ACCESSORS(AccessorInfo, flags, is_sloppy, AccessorInfo::IsSloppyBit)
61 BIT_FIELD_ACCESSORS(AccessorInfo, flags, getter_side_effect_type,
62                     AccessorInfo::GetterSideEffectTypeBits)
63 
64 SideEffectType AccessorInfo::setter_side_effect_type() const {
65   return SetterSideEffectTypeBits::decode(flags());
66 }
67 
set_setter_side_effect_type(SideEffectType value)68 void 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 
BIT_FIELD_ACCESSORS(AccessorInfo,flags,initial_property_attributes,AccessorInfo::InitialAttributesBits)77 BIT_FIELD_ACCESSORS(AccessorInfo, flags, initial_property_attributes,
78                     AccessorInfo::InitialAttributesBits)
79 
80 bool 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 
HasExpectedReceiverType()87 bool AccessorInfo::HasExpectedReceiverType() {
88   return expected_receiver_type().IsFunctionTemplateInfo();
89 }
90 
BOOL_ACCESSORS(InterceptorInfo,flags,can_intercept_symbols,CanInterceptSymbolsBit::kShift)91 BOOL_ACCESSORS(InterceptorInfo, flags, can_intercept_symbols,
92                CanInterceptSymbolsBit::kShift)
93 BOOL_ACCESSORS(InterceptorInfo, flags, all_can_read, AllCanReadBit::kShift)
94 BOOL_ACCESSORS(InterceptorInfo, flags, non_masking, NonMaskingBit::kShift)
95 BOOL_ACCESSORS(InterceptorInfo, flags, is_named, NamedBit::kShift)
96 BOOL_ACCESSORS(InterceptorInfo, flags, has_no_side_effect,
97                HasNoSideEffectBit::kShift)
98 
99 bool 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 
IsSideEffectCallHandlerInfo()107 bool 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 
SetNextCallHasNoSideEffect()115 void CallHandlerInfo::SetNextCallHasNoSideEffect() {
116   set_map(
117       GetReadOnlyRoots().next_call_side_effect_free_call_handler_info_map());
118 }
119 
NextCallHasNoSideEffect()120 bool 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