v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
code-stub-assembler-inl.h
Go to the documentation of this file.
1// Copyright 2023 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_CODEGEN_CODE_STUB_ASSEMBLER_INL_H_
6#define V8_CODEGEN_CODE_STUB_ASSEMBLER_INL_H_
7
9// Include the non-inl header before the rest of the headers.
10
11#include <functional>
12
15#include "src/common/globals.h"
16
17namespace v8 {
18namespace internal {
19
21
22template <typename TCallable, class... TArgs>
24 TNode<TCallable> callable,
26 TNode<JSAny> receiver, TArgs... args) {
29 "Use CallFunction() when the callable is a JSFunction.");
30
34 context, callable, receiver, args...);
35 }
37 return CallJS(Builtins::Call(mode), context, callable, receiver, args...);
38}
39
40template <typename TCallable, class... TArgs>
48
49template <typename TCallable, class... TArgs>
51 TNode<TCallable> callable,
52 TNode<JSAny> receiver, TArgs... args) {
53 return Call(context, callable, ConvertReceiverMode::kAny, receiver, args...);
54}
55
56template <class... TArgs>
71
72template <class... TArgs>
81
82template <class... TArgs>
90
91template <typename Function>
93 TNode<HeapObject> object, TNode<Map> source_map, TNode<Map> target_map,
94 const Function& materialize_target, bool target_is_new) {
95 Label done_copy_properties(this), done_copy_elements(this);
96
97 // This macro only suport JSObjects.
98 CSA_DCHECK(this, InstanceTypeEqual(LoadInstanceType(object), JS_OBJECT_TYPE));
99 CSA_DCHECK(this, IsStrong(TNode<MaybeObject>(target_map)));
101 this, InstanceTypeEqual(LoadMapInstanceType(target_map), JS_OBJECT_TYPE));
102 // We do not want to deal with slack-tracking here.
104 LoadMapBitField3(source_map)));
106 LoadMapBitField3(target_map)));
107
109 EmptyFixedArrayConstant());
110 TVARIABLE(FixedArray, var_elements, EmptyFixedArrayConstant());
111
112 // Copy the PropertyArray backing store. The source PropertyArray
113 // must be either an Smi, or a PropertyArray.
114 Comment("FastCloneJSObject: cloning properties");
115 TNode<Object> source_properties =
116 LoadObjectField(object, JSObject::kPropertiesOrHashOffset);
117 {
118 GotoIf(TaggedIsSmi(source_properties), &done_copy_properties);
119 GotoIf(IsEmptyFixedArray(source_properties), &done_copy_properties);
120
121 // This fastcase requires that the source object has fast properties.
122 TNode<PropertyArray> source_property_array = CAST(source_properties);
123
124 TNode<IntPtrT> length = LoadPropertyArrayLength(source_property_array);
125 GotoIf(IntPtrEqual(length, IntPtrConstant(0)), &done_copy_properties);
126
127 TNode<PropertyArray> property_array = AllocatePropertyArray(length);
128 FillPropertyArrayWithUndefined(property_array, IntPtrConstant(0), length);
129 CopyPropertyArrayValues(source_property_array, property_array, length,
131 var_properties = property_array;
132 }
133
134 Goto(&done_copy_properties);
135 BIND(&done_copy_properties);
136
137 Comment("FastCloneJSObject: cloning elements");
138 TNode<FixedArrayBase> source_elements = LoadElements(CAST(object));
139 GotoIf(TaggedEqual(source_elements, EmptyFixedArrayConstant()),
140 &done_copy_elements);
141 var_elements = CAST(CloneFixedArray(
143
144 Goto(&done_copy_elements);
145 BIND(&done_copy_elements);
146
147 Comment("FastCloneJSObject: initialize the target object");
148 TNode<JSReceiver> target = materialize_target(
149 target_map, var_properties.value(), var_elements.value());
150
151 // Lastly, clone any in-object properties.
152#ifdef DEBUG
153 {
154 TNode<IntPtrT> source_used_instance_size =
155 MapUsedInstanceSizeInWords(source_map);
156 TNode<IntPtrT> target_used_instance_size =
157 MapUsedInstanceSizeInWords(target_map);
158 TNode<IntPtrT> source_inobject_properties_start =
160 TNode<IntPtrT> target_inobject_properties_start =
162 CSA_DCHECK(this, IntPtrEqual(IntPtrSub(target_used_instance_size,
163 target_inobject_properties_start),
164 IntPtrSub(source_used_instance_size,
165 source_inobject_properties_start)));
166 }
167#endif // DEBUG
168
169 // 1) Initialize unused in-object properties.
170 Comment("FastCloneJSObject: initializing unused in-object properties");
171 TNode<IntPtrT> target_used_payload_end =
173 TNode<IntPtrT> target_payload_end =
175 InitializeFieldsWithRoot(target, target_used_payload_end, target_payload_end,
176 RootIndex::kUndefinedValue);
177
178 // 2) Copy all used in-object properties.
179 Comment("FastCloneJSObject: copying used in-object properties");
180 TNode<IntPtrT> source_payload_start =
182 TNode<IntPtrT> target_payload_start =
184 TNode<IntPtrT> field_offset_difference =
185 IntPtrSub(source_payload_start, target_payload_start);
186
187 Label done_copy_used(this);
188 auto EmitCopyLoop = [&](bool write_barrier) {
189 if (write_barrier) {
190 Comment(
191 "FastCloneJSObject: copying used in-object properties with write "
192 "barrier");
193 } else {
194 Comment(
195 "FastCloneJSObject: copying used in-object properties without write "
196 "barrier");
197 }
199 target_payload_start, target_used_payload_end,
200 [&](TNode<IntPtrT> result_offset) {
201 TNode<IntPtrT> source_offset =
202 IntPtrSub(result_offset, field_offset_difference);
203 if (write_barrier) {
204 TNode<Object> field = LoadObjectField(object, source_offset);
205 StoreObjectField(target, result_offset, field);
206 } else {
207 TNode<TaggedT> field =
208 LoadObjectField<TaggedT>(object, source_offset);
209 StoreObjectFieldNoWriteBarrier(target, result_offset, field);
210 }
211 },
213 };
214
215 if (!target_is_new) {
216 Label if_no_write_barrier(this),
217 if_needs_write_barrier(this, Label::kDeferred);
218
219 TrySkipWriteBarrier(target, &if_needs_write_barrier);
220 Goto(&if_no_write_barrier);
221
222 BIND(&if_needs_write_barrier);
223 EmitCopyLoop(true);
224
225 Goto(&done_copy_used);
226 BIND(&if_no_write_barrier);
227 }
228
229 EmitCopyLoop(false);
230 Goto(&done_copy_used);
231
232 BIND(&done_copy_used);
233
234 // 3) Duplicate heap number boxes if needed.
235 // We need to go through the {object} again here and properly clone
236 // them. We use a second loop here to ensure that the GC (and heap
237 // verifier) always sees properly initialized objects, i.e. never
238 // hits undefined values in double fields.
239 Comment("FastCloneJSObject: cloning heap numbers");
241 target, target_payload_start, target_used_payload_end);
242
243 return target;
244}
245
247
248} // namespace internal
249} // namespace v8
250
251#endif // V8_CODEGEN_CODE_STUB_ASSEMBLER_INL_H_
#define BIND(label)
#define TVARIABLE(...)
#define CSA_DCHECK(csa,...)
static constexpr Builtin CallFunction(ConvertReceiverMode=ConvertReceiverMode::kAny)
static constexpr Builtin Call(ConvertReceiverMode=ConvertReceiverMode::kAny)
TNode< WordT > TimesTaggedSize(TNode< WordT > value)
void FillPropertyArrayWithUndefined(TNode< PropertyArray > array, TNode< IntPtrT > from_index, TNode< IntPtrT > to_index)
TNode< BoolT > IsStrong(TNode< MaybeObject > value)
void CopyPropertyArrayValues(TNode< HeapObject > from_array, TNode< PropertyArray > to_array, TNode< IntPtrT > length, WriteBarrierMode barrier_mode, DestroySource destroy_source)
TNode< IntPtrT > LoadMapInobjectPropertiesStartInWords(TNode< Map > map)
TNode< BoolT > InstanceTypeEqual(TNode< Int32T > instance_type, int type)
void InitializeFieldsWithRoot(TNode< HeapObject > object, TNode< IntPtrT > start_offset, TNode< IntPtrT > end_offset, RootIndex root)
void TrySkipWriteBarrier(TNode< Object > object, Label *if_needs_write_barrier)
void DCheckReceiver(ConvertReceiverMode mode, TNode< JSAny > receiver)
TNode< BoolT > TaggedEqual(TNode< AnyTaggedT > a, TNode< AnyTaggedT > b)
TNode< FixedArrayBase > LoadElements(TNode< JSObject > object)
TNode< T > LoadObjectField(TNode< HeapObject > object, int offset)
TNode< BoolT > IsNotSetWord32(TNode< Word32T > word32)
TNode< Uint32T > LoadMapBitField3(TNode< Map > map)
TNode< IntPtrT > LoadPropertyArrayLength(TNode< PropertyArray > object)
void BuildFastLoop(const VariableList &vars, TVariable< TIndex > &var_index, TNode< TIndex > start_index, TNode< TIndex > end_index, const FastLoopBody< TIndex > &body, TNode< TIndex > increment, LoopUnrollingMode unrolling_mode, IndexAdvanceMode advance_mode, IndexAdvanceDirection advance_direction)
void StoreObjectFieldNoWriteBarrier(TNode< HeapObject > object, TNode< IntPtrT > offset, TNode< T > value)
TNode< JSAny > Call(TNode< Context > context, TNode< TCallable > callable, ConvertReceiverMode mode, TNode< JSAny > receiver, TArgs... args)
TNode< Uint16T > LoadMapInstanceType(TNode< Map > map)
TNode< Uint16T > LoadInstanceType(TNode< HeapObject > object)
TNode< BoolT > TaggedIsSmi(TNode< MaybeObject > a)
TNode< PropertyArray > AllocatePropertyArray(TNode< IntPtrT > capacity)
TNode< IntPtrT > MapUsedInstanceSizeInWords(TNode< Map > map)
TNode< Object > FastCloneJSObject(TNode< HeapObject > source, TNode< Map > source_map, TNode< Map > target_map, const Function &materialize_target, bool target_is_new)
TNode< JSAny > CallFunction(TNode< Context > context, TNode< JSFunction > callable, ConvertReceiverMode mode, TNode< JSAny > receiver, TArgs... args)
void StoreObjectField(TNode< HeapObject > object, int offset, TNode< Smi > value)
TNode< IntPtrT > LoadMapInstanceSizeInWords(TNode< Map > map)
TNode< FixedArrayBase > CloneFixedArray(TNode< FixedArrayBase > source, ExtractFixedArrayFlags flags=ExtractFixedArrayFlag::kAllFixedArraysDontCopyCOW)
void CopyMutableHeapNumbersInObject(TNode< HeapObject > copy, TNode< IntPtrT > start_offset, TNode< IntPtrT > instance_size)
void Comment(MessageWithSourceLocation message, Args &&... args)
bool IsUndefinedConstant(TNode< Object > node)
TNode< IntPtrT > IntPtrConstant(intptr_t value)
bool IsNullConstant(TNode< Object > node)
void GotoIf(TNode< IntegralT > condition, Label *true_label, GotoHint goto_hint=GotoHint::kNone)
TNode< BoolT > IntPtrEqual(TNode< WordT > left, TNode< WordT > right)
TNode< IntPtrT > IntPtrSub(TNode< IntPtrT > left, TNode< IntPtrT > right)
TNode< JSAny > CallJS(Builtin builtin, TNode< Context > context, TNode< Object > function, TNode< JSAny > receiver, TArgs... args)
#define CAST(x)
base::Vector< const DirectHandle< Object > > args
Definition execution.cc:74
TNode< Object > target
TNode< Object > receiver
constexpr int kTaggedSize
Definition globals.h:542
@ SKIP_WRITE_BARRIER
Definition objects.h:52
static constexpr bool is_subtype_v
Definition tagged.h:121
#define DCHECK_NE(v1, v2)
Definition logging.h:486