/
githubmirror
/
node
Обзор
Документация
Войти
/
githubmirror
/
node
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
deps/v8/src/codegen/code-stub-assembler-inl.h
251 строка
10 KB
Michaël Zasso
deps: update V8 to 13.6.233.8
02 май 2025, 16:06
Не верифицирован
02 май 2025, 16:06
918fe04
Код
Авторство
О чём код?
// Copyright 2023 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_CODEGEN_CODE_STUB_ASSEMBLER_INL_H_ #define V8_CODEGEN_CODE_STUB_ASSEMBLER_INL_H_ #include "src/codegen/code-stub-assembler.h" // Include the non-inl header before the rest of the headers. #include <functional> #include "src/builtins/builtins-constructor-gen.h" #include "src/builtins/builtins-inl.h" #include "src/common/globals.h" namespace v8 { namespace internal { #include "src/codegen/define-code-stub-assembler-macros.inc" template <typename TCallable, class... TArgs> TNode<JSAny> CodeStubAssembler::Call(TNode<Context> context, TNode<TCallable> callable, ConvertReceiverMode mode, TNode<JSAny> receiver, TArgs... args) { static_assert(is_subtype_v<TCallable, Object>); static_assert(!is_subtype_v<TCallable, JSFunction>, "Use CallFunction() when the callable is a JSFunction."); if (IsUndefinedConstant(receiver) || IsNullConstant(receiver)) { DCHECK_NE(mode, ConvertReceiverMode::kNotNullOrUndefined); return CallJS(Builtins::Call(ConvertReceiverMode::kNullOrUndefined), context, callable, receiver, args...); } DCheckReceiver(mode, receiver); return CallJS(Builtins::Call(mode), context, callable, receiver, args...); } template <typename TCallable, class... TArgs> TNode<JSAny> CodeStubAssembler::Call(TNode<Context> context, TNode<TCallable> callable, TNode<JSReceiver> receiver, TArgs... args) { return Call(context, callable, ConvertReceiverMode::kNotNullOrUndefined, receiver, args...); } template <typename TCallable, class... TArgs> TNode<JSAny> CodeStubAssembler::Call(TNode<Context> context, TNode<TCallable> callable, TNode<JSAny> receiver, TArgs... args) { return Call(context, callable, ConvertReceiverMode::kAny, receiver, args...); } template <class... TArgs> TNode<JSAny> CodeStubAssembler::CallFunction(TNode<Context> context, TNode<JSFunction> callable, ConvertReceiverMode mode, TNode<JSAny> receiver, TArgs... args) { if (IsUndefinedConstant(receiver) || IsNullConstant(receiver)) { DCHECK_NE(mode, ConvertReceiverMode::kNotNullOrUndefined); return CallJS(Builtins::CallFunction(ConvertReceiverMode::kNullOrUndefined), context, callable, receiver, args...); } DCheckReceiver(mode, receiver); return CallJS(Builtins::CallFunction(mode), context, callable, receiver, args...); } template <class... TArgs> TNode<JSAny> CodeStubAssembler::CallFunction(TNode<Context> context, TNode<JSFunction> callable, TNode<JSReceiver> receiver, TArgs... args) { return CallFunction(context, callable, ConvertReceiverMode::kNotNullOrUndefined, receiver, args...); } template <class... TArgs> TNode<JSAny> CodeStubAssembler::CallFunction(TNode<Context> context, TNode<JSFunction> callable, TNode<JSAny> receiver, TArgs... args) { return CallFunction(context, callable, ConvertReceiverMode::kAny, receiver, args...); } template <typename Function> TNode<Object> CodeStubAssembler::FastCloneJSObject( TNode<HeapObject> object, TNode<Map> source_map, TNode<Map> target_map, const Function& materialize_target, bool target_is_new) { Label done_copy_properties(this), done_copy_elements(this); // This macro only suport JSObjects. CSA_DCHECK(this, InstanceTypeEqual(LoadInstanceType(object), JS_OBJECT_TYPE)); CSA_DCHECK(this, IsStrong(TNode<MaybeObject>(target_map))); CSA_DCHECK( this, InstanceTypeEqual(LoadMapInstanceType(target_map), JS_OBJECT_TYPE)); // We do not want to deal with slack-tracking here. CSA_DCHECK(this, IsNotSetWord32<Map::Bits3::ConstructionCounterBits>( LoadMapBitField3(source_map))); CSA_DCHECK(this, IsNotSetWord32<Map::Bits3::ConstructionCounterBits>( LoadMapBitField3(target_map))); TVARIABLE((Union<FixedArray, PropertyArray>), var_properties, EmptyFixedArrayConstant()); TVARIABLE(FixedArray, var_elements, EmptyFixedArrayConstant()); // Copy the PropertyArray backing store. The source PropertyArray // must be either an Smi, or a PropertyArray. Comment("FastCloneJSObject: cloning properties"); TNode<Object> source_properties = LoadObjectField(object, JSObject::kPropertiesOrHashOffset); { GotoIf(TaggedIsSmi(source_properties), &done_copy_properties); GotoIf(IsEmptyFixedArray(source_properties), &done_copy_properties); // This fastcase requires that the source object has fast properties. TNode<PropertyArray> source_property_array = CAST(source_properties); TNode<IntPtrT> length = LoadPropertyArrayLength(source_property_array); GotoIf(IntPtrEqual(length, IntPtrConstant(0)), &done_copy_properties); TNode<PropertyArray> property_array = AllocatePropertyArray(length); FillPropertyArrayWithUndefined(property_array, IntPtrConstant(0), length); CopyPropertyArrayValues(source_property_array, property_array, length, SKIP_WRITE_BARRIER, DestroySource::kNo); var_properties = property_array; } Goto(&done_copy_properties); BIND(&done_copy_properties); Comment("FastCloneJSObject: cloning elements"); TNode<FixedArrayBase> source_elements = LoadElements(CAST(object)); GotoIf(TaggedEqual(source_elements, EmptyFixedArrayConstant()), &done_copy_elements); var_elements = CAST(CloneFixedArray( source_elements, ExtractFixedArrayFlag::kAllFixedArraysDontCopyCOW)); Goto(&done_copy_elements); BIND(&done_copy_elements); Comment("FastCloneJSObject: initialize the target object"); TNode<JSReceiver> target = materialize_target( target_map, var_properties.value(), var_elements.value()); // Lastly, clone any in-object properties. #ifdef DEBUG { TNode<IntPtrT> source_used_instance_size = MapUsedInstanceSizeInWords(source_map); TNode<IntPtrT> target_used_instance_size = MapUsedInstanceSizeInWords(target_map); TNode<IntPtrT> source_inobject_properties_start = LoadMapInobjectPropertiesStartInWords(source_map); TNode<IntPtrT> target_inobject_properties_start = LoadMapInobjectPropertiesStartInWords(target_map); CSA_DCHECK(this, IntPtrEqual(IntPtrSub(target_used_instance_size, target_inobject_properties_start), IntPtrSub(source_used_instance_size, source_inobject_properties_start))); } #endif // DEBUG // 1) Initialize unused in-object properties. Comment("FastCloneJSObject: initializing unused in-object properties"); TNode<IntPtrT> target_used_payload_end = TimesTaggedSize(MapUsedInstanceSizeInWords(target_map)); TNode<IntPtrT> target_payload_end = TimesTaggedSize(LoadMapInstanceSizeInWords(target_map)); InitializeFieldsWithRoot(target, target_used_payload_end, target_payload_end, RootIndex::kUndefinedValue); // 2) Copy all used in-object properties. Comment("FastCloneJSObject: copying used in-object properties"); TNode<IntPtrT> source_payload_start = TimesTaggedSize(LoadMapInobjectPropertiesStartInWords(source_map)); TNode<IntPtrT> target_payload_start = TimesTaggedSize(LoadMapInobjectPropertiesStartInWords(target_map)); TNode<IntPtrT> field_offset_difference = IntPtrSub(source_payload_start, target_payload_start); Label done_copy_used(this); auto EmitCopyLoop = [&](bool write_barrier) { if (write_barrier) { Comment( "FastCloneJSObject: copying used in-object properties with write " "barrier"); } else { Comment( "FastCloneJSObject: copying used in-object properties without write " "barrier"); } BuildFastLoop<IntPtrT>( target_payload_start, target_used_payload_end, [&](TNode<IntPtrT> result_offset) { TNode<IntPtrT> source_offset = IntPtrSub(result_offset, field_offset_difference); if (write_barrier) { TNode<Object> field = LoadObjectField(object, source_offset); StoreObjectField(target, result_offset, field); } else { TNode<TaggedT> field = LoadObjectField<TaggedT>(object, source_offset); StoreObjectFieldNoWriteBarrier(target, result_offset, field); } }, kTaggedSize, LoopUnrollingMode::kYes, IndexAdvanceMode::kPost); }; if (!target_is_new) { Label if_no_write_barrier(this), if_needs_write_barrier(this, Label::kDeferred); TrySkipWriteBarrier(target, &if_needs_write_barrier); Goto(&if_no_write_barrier); BIND(&if_needs_write_barrier); EmitCopyLoop(true); Goto(&done_copy_used); BIND(&if_no_write_barrier); } EmitCopyLoop(false); Goto(&done_copy_used); BIND(&done_copy_used); // 3) Duplicate heap number boxes if needed. // We need to go through the {object} again here and properly clone // them. We use a second loop here to ensure that the GC (and heap // verifier) always sees properly initialized objects, i.e. never // hits undefined values in double fields. Comment("FastCloneJSObject: cloning heap numbers"); ConstructorBuiltinsAssembler(state()).CopyMutableHeapNumbersInObject( target, target_payload_start, target_used_payload_end); return target; } #include "src/codegen/undef-code-stub-assembler-macros.inc" } // namespace internal } // namespace v8 #endif // V8_CODEGEN_CODE_STUB_ASSEMBLER_INL_H_