11cb0ef41Sopenharmony_ci// Copyright 2016 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ci#include "src/builtins/builtins-constructor-gen.h" 61cb0ef41Sopenharmony_ci 71cb0ef41Sopenharmony_ci#include "src/ast/ast.h" 81cb0ef41Sopenharmony_ci#include "src/builtins/builtins-call-gen.h" 91cb0ef41Sopenharmony_ci#include "src/builtins/builtins-constructor.h" 101cb0ef41Sopenharmony_ci#include "src/builtins/builtins-utils-gen.h" 111cb0ef41Sopenharmony_ci#include "src/builtins/builtins.h" 121cb0ef41Sopenharmony_ci#include "src/codegen/code-factory.h" 131cb0ef41Sopenharmony_ci#include "src/codegen/code-stub-assembler.h" 141cb0ef41Sopenharmony_ci#include "src/codegen/interface-descriptors.h" 151cb0ef41Sopenharmony_ci#include "src/codegen/macro-assembler.h" 161cb0ef41Sopenharmony_ci#include "src/common/globals.h" 171cb0ef41Sopenharmony_ci#include "src/logging/counters.h" 181cb0ef41Sopenharmony_ci#include "src/objects/objects-inl.h" 191cb0ef41Sopenharmony_ci 201cb0ef41Sopenharmony_cinamespace v8 { 211cb0ef41Sopenharmony_cinamespace internal { 221cb0ef41Sopenharmony_ci 231cb0ef41Sopenharmony_civoid Builtins::Generate_ConstructVarargs(MacroAssembler* masm) { 241cb0ef41Sopenharmony_ci Generate_CallOrConstructVarargs(masm, 251cb0ef41Sopenharmony_ci BUILTIN_CODE(masm->isolate(), Construct)); 261cb0ef41Sopenharmony_ci} 271cb0ef41Sopenharmony_ci 281cb0ef41Sopenharmony_civoid Builtins::Generate_ConstructForwardVarargs(MacroAssembler* masm) { 291cb0ef41Sopenharmony_ci Generate_CallOrConstructForwardVarargs( 301cb0ef41Sopenharmony_ci masm, CallOrConstructMode::kConstruct, 311cb0ef41Sopenharmony_ci BUILTIN_CODE(masm->isolate(), Construct)); 321cb0ef41Sopenharmony_ci} 331cb0ef41Sopenharmony_ci 341cb0ef41Sopenharmony_civoid Builtins::Generate_ConstructFunctionForwardVarargs(MacroAssembler* masm) { 351cb0ef41Sopenharmony_ci Generate_CallOrConstructForwardVarargs( 361cb0ef41Sopenharmony_ci masm, CallOrConstructMode::kConstruct, 371cb0ef41Sopenharmony_ci BUILTIN_CODE(masm->isolate(), ConstructFunction)); 381cb0ef41Sopenharmony_ci} 391cb0ef41Sopenharmony_ci 401cb0ef41Sopenharmony_ciTF_BUILTIN(Construct_Baseline, CallOrConstructBuiltinsAssembler) { 411cb0ef41Sopenharmony_ci auto target = Parameter<Object>(Descriptor::kTarget); 421cb0ef41Sopenharmony_ci auto new_target = Parameter<Object>(Descriptor::kNewTarget); 431cb0ef41Sopenharmony_ci auto argc = UncheckedParameter<Int32T>(Descriptor::kActualArgumentsCount); 441cb0ef41Sopenharmony_ci auto slot = UncheckedParameter<UintPtrT>(Descriptor::kSlot); 451cb0ef41Sopenharmony_ci 461cb0ef41Sopenharmony_ci BuildConstruct( 471cb0ef41Sopenharmony_ci target, new_target, argc, [=] { return LoadContextFromBaseline(); }, 481cb0ef41Sopenharmony_ci [=] { return LoadFeedbackVectorFromBaseline(); }, slot, 491cb0ef41Sopenharmony_ci UpdateFeedbackMode::kGuaranteedFeedback); 501cb0ef41Sopenharmony_ci} 511cb0ef41Sopenharmony_ci 521cb0ef41Sopenharmony_ciTF_BUILTIN(Construct_WithFeedback, CallOrConstructBuiltinsAssembler) { 531cb0ef41Sopenharmony_ci auto target = Parameter<Object>(Descriptor::kTarget); 541cb0ef41Sopenharmony_ci auto new_target = Parameter<Object>(Descriptor::kNewTarget); 551cb0ef41Sopenharmony_ci auto argc = UncheckedParameter<Int32T>(Descriptor::kActualArgumentsCount); 561cb0ef41Sopenharmony_ci auto context = Parameter<Context>(Descriptor::kContext); 571cb0ef41Sopenharmony_ci auto feedback_vector = Parameter<FeedbackVector>(Descriptor::kFeedbackVector); 581cb0ef41Sopenharmony_ci auto slot = UncheckedParameter<UintPtrT>(Descriptor::kSlot); 591cb0ef41Sopenharmony_ci 601cb0ef41Sopenharmony_ci BuildConstruct( 611cb0ef41Sopenharmony_ci target, new_target, argc, [=] { return context; }, 621cb0ef41Sopenharmony_ci [=] { return feedback_vector; }, slot, 631cb0ef41Sopenharmony_ci UpdateFeedbackMode::kOptionalFeedback); 641cb0ef41Sopenharmony_ci} 651cb0ef41Sopenharmony_ci 661cb0ef41Sopenharmony_civoid CallOrConstructBuiltinsAssembler::BuildConstruct( 671cb0ef41Sopenharmony_ci TNode<Object> target, TNode<Object> new_target, TNode<Int32T> argc, 681cb0ef41Sopenharmony_ci const LazyNode<Context>& context, 691cb0ef41Sopenharmony_ci const LazyNode<HeapObject>& feedback_vector, TNode<UintPtrT> slot, 701cb0ef41Sopenharmony_ci UpdateFeedbackMode mode) { 711cb0ef41Sopenharmony_ci TVARIABLE(AllocationSite, allocation_site); 721cb0ef41Sopenharmony_ci Label if_construct_generic(this), if_construct_array(this); 731cb0ef41Sopenharmony_ci TNode<Context> eager_context = context(); 741cb0ef41Sopenharmony_ci CollectConstructFeedback(eager_context, target, new_target, feedback_vector(), 751cb0ef41Sopenharmony_ci slot, mode, &if_construct_generic, 761cb0ef41Sopenharmony_ci &if_construct_array, &allocation_site); 771cb0ef41Sopenharmony_ci 781cb0ef41Sopenharmony_ci BIND(&if_construct_generic); 791cb0ef41Sopenharmony_ci TailCallBuiltin(Builtin::kConstruct, eager_context, target, new_target, argc); 801cb0ef41Sopenharmony_ci 811cb0ef41Sopenharmony_ci BIND(&if_construct_array); 821cb0ef41Sopenharmony_ci TailCallBuiltin(Builtin::kArrayConstructorImpl, eager_context, target, 831cb0ef41Sopenharmony_ci new_target, argc, allocation_site.value()); 841cb0ef41Sopenharmony_ci} 851cb0ef41Sopenharmony_ci 861cb0ef41Sopenharmony_ciTF_BUILTIN(ConstructWithArrayLike, CallOrConstructBuiltinsAssembler) { 871cb0ef41Sopenharmony_ci auto target = Parameter<Object>(Descriptor::kTarget); 881cb0ef41Sopenharmony_ci auto new_target = Parameter<Object>(Descriptor::kNewTarget); 891cb0ef41Sopenharmony_ci auto arguments_list = Parameter<Object>(Descriptor::kArgumentsList); 901cb0ef41Sopenharmony_ci auto context = Parameter<Context>(Descriptor::kContext); 911cb0ef41Sopenharmony_ci CallOrConstructWithArrayLike(target, new_target, arguments_list, context); 921cb0ef41Sopenharmony_ci} 931cb0ef41Sopenharmony_ci 941cb0ef41Sopenharmony_ciTF_BUILTIN(ConstructWithArrayLike_WithFeedback, 951cb0ef41Sopenharmony_ci CallOrConstructBuiltinsAssembler) { 961cb0ef41Sopenharmony_ci auto target = Parameter<Object>(Descriptor::kTarget); 971cb0ef41Sopenharmony_ci auto new_target = Parameter<Object>(Descriptor::kNewTarget); 981cb0ef41Sopenharmony_ci auto arguments_list = Parameter<Object>(Descriptor::kArgumentsList); 991cb0ef41Sopenharmony_ci auto context = Parameter<Context>(Descriptor::kContext); 1001cb0ef41Sopenharmony_ci auto feedback_vector = Parameter<FeedbackVector>(Descriptor::kFeedbackVector); 1011cb0ef41Sopenharmony_ci auto slot = UncheckedParameter<UintPtrT>(Descriptor::kSlot); 1021cb0ef41Sopenharmony_ci 1031cb0ef41Sopenharmony_ci TVARIABLE(AllocationSite, allocation_site); 1041cb0ef41Sopenharmony_ci Label if_construct_generic(this), if_construct_array(this); 1051cb0ef41Sopenharmony_ci CollectConstructFeedback(context, target, new_target, feedback_vector, slot, 1061cb0ef41Sopenharmony_ci UpdateFeedbackMode::kOptionalFeedback, 1071cb0ef41Sopenharmony_ci &if_construct_generic, &if_construct_array, 1081cb0ef41Sopenharmony_ci &allocation_site); 1091cb0ef41Sopenharmony_ci 1101cb0ef41Sopenharmony_ci BIND(&if_construct_array); 1111cb0ef41Sopenharmony_ci Goto(&if_construct_generic); // Not implemented. 1121cb0ef41Sopenharmony_ci 1131cb0ef41Sopenharmony_ci BIND(&if_construct_generic); 1141cb0ef41Sopenharmony_ci CallOrConstructWithArrayLike(target, new_target, arguments_list, context); 1151cb0ef41Sopenharmony_ci} 1161cb0ef41Sopenharmony_ci 1171cb0ef41Sopenharmony_ciTF_BUILTIN(ConstructWithSpread, CallOrConstructBuiltinsAssembler) { 1181cb0ef41Sopenharmony_ci auto target = Parameter<Object>(Descriptor::kTarget); 1191cb0ef41Sopenharmony_ci auto new_target = Parameter<Object>(Descriptor::kNewTarget); 1201cb0ef41Sopenharmony_ci auto spread = Parameter<Object>(Descriptor::kSpread); 1211cb0ef41Sopenharmony_ci auto args_count = 1221cb0ef41Sopenharmony_ci UncheckedParameter<Int32T>(Descriptor::kActualArgumentsCount); 1231cb0ef41Sopenharmony_ci auto context = Parameter<Context>(Descriptor::kContext); 1241cb0ef41Sopenharmony_ci CallOrConstructWithSpread(target, new_target, spread, args_count, context); 1251cb0ef41Sopenharmony_ci} 1261cb0ef41Sopenharmony_ci 1271cb0ef41Sopenharmony_ciTF_BUILTIN(ConstructWithSpread_Baseline, CallOrConstructBuiltinsAssembler) { 1281cb0ef41Sopenharmony_ci auto target = Parameter<Object>(Descriptor::kTarget); 1291cb0ef41Sopenharmony_ci auto new_target = Parameter<Object>(Descriptor::kNewTarget); 1301cb0ef41Sopenharmony_ci auto spread = Parameter<Object>(Descriptor::kSpread); 1311cb0ef41Sopenharmony_ci auto args_count = 1321cb0ef41Sopenharmony_ci UncheckedParameter<Int32T>(Descriptor::kActualArgumentsCount); 1331cb0ef41Sopenharmony_ci auto slot = UncheckedParameter<UintPtrT>(Descriptor::kSlot); 1341cb0ef41Sopenharmony_ci return BuildConstructWithSpread( 1351cb0ef41Sopenharmony_ci target, new_target, spread, args_count, 1361cb0ef41Sopenharmony_ci [=] { return LoadContextFromBaseline(); }, 1371cb0ef41Sopenharmony_ci [=] { return LoadFeedbackVectorFromBaseline(); }, slot, 1381cb0ef41Sopenharmony_ci UpdateFeedbackMode::kGuaranteedFeedback); 1391cb0ef41Sopenharmony_ci} 1401cb0ef41Sopenharmony_ci 1411cb0ef41Sopenharmony_ciTF_BUILTIN(ConstructWithSpread_WithFeedback, CallOrConstructBuiltinsAssembler) { 1421cb0ef41Sopenharmony_ci auto target = Parameter<Object>(Descriptor::kTarget); 1431cb0ef41Sopenharmony_ci auto new_target = Parameter<Object>(Descriptor::kNewTarget); 1441cb0ef41Sopenharmony_ci auto spread = Parameter<Object>(Descriptor::kSpread); 1451cb0ef41Sopenharmony_ci auto args_count = 1461cb0ef41Sopenharmony_ci UncheckedParameter<Int32T>(Descriptor::kActualArgumentsCount); 1471cb0ef41Sopenharmony_ci auto context = Parameter<Context>(Descriptor::kContext); 1481cb0ef41Sopenharmony_ci auto feedback_vector = Parameter<HeapObject>(Descriptor::kFeedbackVector); 1491cb0ef41Sopenharmony_ci auto slot = UncheckedParameter<UintPtrT>(Descriptor::kSlot); 1501cb0ef41Sopenharmony_ci 1511cb0ef41Sopenharmony_ci return BuildConstructWithSpread( 1521cb0ef41Sopenharmony_ci target, new_target, spread, args_count, [=] { return context; }, 1531cb0ef41Sopenharmony_ci [=] { return feedback_vector; }, slot, 1541cb0ef41Sopenharmony_ci UpdateFeedbackMode::kGuaranteedFeedback); 1551cb0ef41Sopenharmony_ci} 1561cb0ef41Sopenharmony_ci 1571cb0ef41Sopenharmony_civoid CallOrConstructBuiltinsAssembler::BuildConstructWithSpread( 1581cb0ef41Sopenharmony_ci TNode<Object> target, TNode<Object> new_target, TNode<Object> spread, 1591cb0ef41Sopenharmony_ci TNode<Int32T> argc, const LazyNode<Context>& context, 1601cb0ef41Sopenharmony_ci const LazyNode<HeapObject>& feedback_vector, TNode<UintPtrT> slot, 1611cb0ef41Sopenharmony_ci UpdateFeedbackMode mode) { 1621cb0ef41Sopenharmony_ci TVARIABLE(AllocationSite, allocation_site); 1631cb0ef41Sopenharmony_ci Label if_construct_generic(this), if_construct_array(this); 1641cb0ef41Sopenharmony_ci TNode<Context> eager_context = context(); 1651cb0ef41Sopenharmony_ci CollectConstructFeedback(eager_context, target, new_target, feedback_vector(), 1661cb0ef41Sopenharmony_ci slot, UpdateFeedbackMode::kGuaranteedFeedback, 1671cb0ef41Sopenharmony_ci &if_construct_generic, &if_construct_array, 1681cb0ef41Sopenharmony_ci &allocation_site); 1691cb0ef41Sopenharmony_ci 1701cb0ef41Sopenharmony_ci BIND(&if_construct_array); 1711cb0ef41Sopenharmony_ci Goto(&if_construct_generic); // Not implemented. 1721cb0ef41Sopenharmony_ci 1731cb0ef41Sopenharmony_ci BIND(&if_construct_generic); 1741cb0ef41Sopenharmony_ci CallOrConstructWithSpread(target, new_target, spread, argc, eager_context); 1751cb0ef41Sopenharmony_ci} 1761cb0ef41Sopenharmony_ci 1771cb0ef41Sopenharmony_ciTF_BUILTIN(FastNewClosure, ConstructorBuiltinsAssembler) { 1781cb0ef41Sopenharmony_ci auto shared_function_info = 1791cb0ef41Sopenharmony_ci Parameter<SharedFunctionInfo>(Descriptor::kSharedFunctionInfo); 1801cb0ef41Sopenharmony_ci auto feedback_cell = Parameter<FeedbackCell>(Descriptor::kFeedbackCell); 1811cb0ef41Sopenharmony_ci auto context = Parameter<Context>(Descriptor::kContext); 1821cb0ef41Sopenharmony_ci 1831cb0ef41Sopenharmony_ci IncrementCounter(isolate()->counters()->fast_new_closure_total(), 1); 1841cb0ef41Sopenharmony_ci 1851cb0ef41Sopenharmony_ci // Bump the closure counter encoded the {feedback_cell}s map. 1861cb0ef41Sopenharmony_ci { 1871cb0ef41Sopenharmony_ci const TNode<Map> feedback_cell_map = LoadMap(feedback_cell); 1881cb0ef41Sopenharmony_ci Label no_closures(this), one_closure(this), cell_done(this); 1891cb0ef41Sopenharmony_ci 1901cb0ef41Sopenharmony_ci GotoIf(IsNoClosuresCellMap(feedback_cell_map), &no_closures); 1911cb0ef41Sopenharmony_ci GotoIf(IsOneClosureCellMap(feedback_cell_map), &one_closure); 1921cb0ef41Sopenharmony_ci CSA_DCHECK(this, IsManyClosuresCellMap(feedback_cell_map), 1931cb0ef41Sopenharmony_ci feedback_cell_map, feedback_cell); 1941cb0ef41Sopenharmony_ci Goto(&cell_done); 1951cb0ef41Sopenharmony_ci 1961cb0ef41Sopenharmony_ci BIND(&no_closures); 1971cb0ef41Sopenharmony_ci StoreMapNoWriteBarrier(feedback_cell, RootIndex::kOneClosureCellMap); 1981cb0ef41Sopenharmony_ci Goto(&cell_done); 1991cb0ef41Sopenharmony_ci 2001cb0ef41Sopenharmony_ci BIND(&one_closure); 2011cb0ef41Sopenharmony_ci StoreMapNoWriteBarrier(feedback_cell, RootIndex::kManyClosuresCellMap); 2021cb0ef41Sopenharmony_ci Goto(&cell_done); 2031cb0ef41Sopenharmony_ci 2041cb0ef41Sopenharmony_ci BIND(&cell_done); 2051cb0ef41Sopenharmony_ci } 2061cb0ef41Sopenharmony_ci 2071cb0ef41Sopenharmony_ci // The calculation of |function_map_index| must be in sync with 2081cb0ef41Sopenharmony_ci // SharedFunctionInfo::function_map_index(). 2091cb0ef41Sopenharmony_ci TNode<Uint32T> flags = LoadObjectField<Uint32T>( 2101cb0ef41Sopenharmony_ci shared_function_info, SharedFunctionInfo::kFlagsOffset); 2111cb0ef41Sopenharmony_ci const TNode<IntPtrT> function_map_index = Signed(IntPtrAdd( 2121cb0ef41Sopenharmony_ci DecodeWordFromWord32<SharedFunctionInfo::FunctionMapIndexBits>(flags), 2131cb0ef41Sopenharmony_ci IntPtrConstant(Context::FIRST_FUNCTION_MAP_INDEX))); 2141cb0ef41Sopenharmony_ci CSA_DCHECK(this, UintPtrLessThanOrEqual( 2151cb0ef41Sopenharmony_ci function_map_index, 2161cb0ef41Sopenharmony_ci IntPtrConstant(Context::LAST_FUNCTION_MAP_INDEX))); 2171cb0ef41Sopenharmony_ci 2181cb0ef41Sopenharmony_ci // Get the function map in the current native context and set that 2191cb0ef41Sopenharmony_ci // as the map of the allocated object. 2201cb0ef41Sopenharmony_ci const TNode<NativeContext> native_context = LoadNativeContext(context); 2211cb0ef41Sopenharmony_ci const TNode<Map> function_map = 2221cb0ef41Sopenharmony_ci CAST(LoadContextElement(native_context, function_map_index)); 2231cb0ef41Sopenharmony_ci 2241cb0ef41Sopenharmony_ci // Create a new closure from the given function info in new space 2251cb0ef41Sopenharmony_ci TNode<IntPtrT> instance_size_in_bytes = 2261cb0ef41Sopenharmony_ci TimesTaggedSize(LoadMapInstanceSizeInWords(function_map)); 2271cb0ef41Sopenharmony_ci TNode<HeapObject> result = Allocate(instance_size_in_bytes); 2281cb0ef41Sopenharmony_ci StoreMapNoWriteBarrier(result, function_map); 2291cb0ef41Sopenharmony_ci InitializeJSObjectBodyNoSlackTracking(result, function_map, 2301cb0ef41Sopenharmony_ci instance_size_in_bytes, 2311cb0ef41Sopenharmony_ci JSFunction::kSizeWithoutPrototype); 2321cb0ef41Sopenharmony_ci 2331cb0ef41Sopenharmony_ci // Initialize the rest of the function. 2341cb0ef41Sopenharmony_ci StoreObjectFieldRoot(result, JSObject::kPropertiesOrHashOffset, 2351cb0ef41Sopenharmony_ci RootIndex::kEmptyFixedArray); 2361cb0ef41Sopenharmony_ci StoreObjectFieldRoot(result, JSObject::kElementsOffset, 2371cb0ef41Sopenharmony_ci RootIndex::kEmptyFixedArray); 2381cb0ef41Sopenharmony_ci { 2391cb0ef41Sopenharmony_ci // Set function prototype if necessary. 2401cb0ef41Sopenharmony_ci Label done(this), init_prototype(this); 2411cb0ef41Sopenharmony_ci Branch(IsFunctionWithPrototypeSlotMap(function_map), &init_prototype, 2421cb0ef41Sopenharmony_ci &done); 2431cb0ef41Sopenharmony_ci 2441cb0ef41Sopenharmony_ci BIND(&init_prototype); 2451cb0ef41Sopenharmony_ci StoreObjectFieldRoot(result, JSFunction::kPrototypeOrInitialMapOffset, 2461cb0ef41Sopenharmony_ci RootIndex::kTheHoleValue); 2471cb0ef41Sopenharmony_ci Goto(&done); 2481cb0ef41Sopenharmony_ci BIND(&done); 2491cb0ef41Sopenharmony_ci } 2501cb0ef41Sopenharmony_ci 2511cb0ef41Sopenharmony_ci STATIC_ASSERT(JSFunction::kSizeWithoutPrototype == 7 * kTaggedSize); 2521cb0ef41Sopenharmony_ci StoreObjectFieldNoWriteBarrier(result, JSFunction::kFeedbackCellOffset, 2531cb0ef41Sopenharmony_ci feedback_cell); 2541cb0ef41Sopenharmony_ci StoreObjectFieldNoWriteBarrier(result, JSFunction::kSharedFunctionInfoOffset, 2551cb0ef41Sopenharmony_ci shared_function_info); 2561cb0ef41Sopenharmony_ci StoreObjectFieldNoWriteBarrier(result, JSFunction::kContextOffset, context); 2571cb0ef41Sopenharmony_ci TNode<CodeT> lazy_builtin = 2581cb0ef41Sopenharmony_ci HeapConstant(BUILTIN_CODE(isolate(), CompileLazy)); 2591cb0ef41Sopenharmony_ci StoreObjectFieldNoWriteBarrier(result, JSFunction::kCodeOffset, lazy_builtin); 2601cb0ef41Sopenharmony_ci Return(result); 2611cb0ef41Sopenharmony_ci} 2621cb0ef41Sopenharmony_ci 2631cb0ef41Sopenharmony_ciTF_BUILTIN(FastNewObject, ConstructorBuiltinsAssembler) { 2641cb0ef41Sopenharmony_ci auto context = Parameter<Context>(Descriptor::kContext); 2651cb0ef41Sopenharmony_ci auto target = Parameter<JSFunction>(Descriptor::kTarget); 2661cb0ef41Sopenharmony_ci auto new_target = Parameter<JSReceiver>(Descriptor::kNewTarget); 2671cb0ef41Sopenharmony_ci 2681cb0ef41Sopenharmony_ci Label call_runtime(this); 2691cb0ef41Sopenharmony_ci 2701cb0ef41Sopenharmony_ci TNode<JSObject> result = 2711cb0ef41Sopenharmony_ci FastNewObject(context, target, new_target, &call_runtime); 2721cb0ef41Sopenharmony_ci Return(result); 2731cb0ef41Sopenharmony_ci 2741cb0ef41Sopenharmony_ci BIND(&call_runtime); 2751cb0ef41Sopenharmony_ci TailCallRuntime(Runtime::kNewObject, context, target, new_target); 2761cb0ef41Sopenharmony_ci} 2771cb0ef41Sopenharmony_ci 2781cb0ef41Sopenharmony_ciTNode<JSObject> ConstructorBuiltinsAssembler::FastNewObject( 2791cb0ef41Sopenharmony_ci TNode<Context> context, TNode<JSFunction> target, 2801cb0ef41Sopenharmony_ci TNode<JSReceiver> new_target) { 2811cb0ef41Sopenharmony_ci TVARIABLE(JSObject, var_obj); 2821cb0ef41Sopenharmony_ci Label call_runtime(this), end(this); 2831cb0ef41Sopenharmony_ci 2841cb0ef41Sopenharmony_ci var_obj = FastNewObject(context, target, new_target, &call_runtime); 2851cb0ef41Sopenharmony_ci Goto(&end); 2861cb0ef41Sopenharmony_ci 2871cb0ef41Sopenharmony_ci BIND(&call_runtime); 2881cb0ef41Sopenharmony_ci var_obj = CAST(CallRuntime(Runtime::kNewObject, context, target, new_target)); 2891cb0ef41Sopenharmony_ci Goto(&end); 2901cb0ef41Sopenharmony_ci 2911cb0ef41Sopenharmony_ci BIND(&end); 2921cb0ef41Sopenharmony_ci return var_obj.value(); 2931cb0ef41Sopenharmony_ci} 2941cb0ef41Sopenharmony_ci 2951cb0ef41Sopenharmony_ciTNode<JSObject> ConstructorBuiltinsAssembler::FastNewObject( 2961cb0ef41Sopenharmony_ci TNode<Context> context, TNode<JSFunction> target, 2971cb0ef41Sopenharmony_ci TNode<JSReceiver> new_target, Label* call_runtime) { 2981cb0ef41Sopenharmony_ci // Verify that the new target is a JSFunction. 2991cb0ef41Sopenharmony_ci Label end(this); 3001cb0ef41Sopenharmony_ci TNode<JSFunction> new_target_func = 3011cb0ef41Sopenharmony_ci HeapObjectToJSFunctionWithPrototypeSlot(new_target, call_runtime); 3021cb0ef41Sopenharmony_ci // Fast path. 3031cb0ef41Sopenharmony_ci 3041cb0ef41Sopenharmony_ci // Load the initial map and verify that it's in fact a map. 3051cb0ef41Sopenharmony_ci TNode<Object> initial_map_or_proto = 3061cb0ef41Sopenharmony_ci LoadJSFunctionPrototypeOrInitialMap(new_target_func); 3071cb0ef41Sopenharmony_ci GotoIf(TaggedIsSmi(initial_map_or_proto), call_runtime); 3081cb0ef41Sopenharmony_ci GotoIf(DoesntHaveInstanceType(CAST(initial_map_or_proto), MAP_TYPE), 3091cb0ef41Sopenharmony_ci call_runtime); 3101cb0ef41Sopenharmony_ci TNode<Map> initial_map = CAST(initial_map_or_proto); 3111cb0ef41Sopenharmony_ci 3121cb0ef41Sopenharmony_ci // Fall back to runtime if the target differs from the new target's 3131cb0ef41Sopenharmony_ci // initial map constructor. 3141cb0ef41Sopenharmony_ci TNode<Object> new_target_constructor = LoadObjectField( 3151cb0ef41Sopenharmony_ci initial_map, Map::kConstructorOrBackPointerOrNativeContextOffset); 3161cb0ef41Sopenharmony_ci GotoIf(TaggedNotEqual(target, new_target_constructor), call_runtime); 3171cb0ef41Sopenharmony_ci 3181cb0ef41Sopenharmony_ci TVARIABLE(HeapObject, properties); 3191cb0ef41Sopenharmony_ci 3201cb0ef41Sopenharmony_ci Label instantiate_map(this), allocate_properties(this); 3211cb0ef41Sopenharmony_ci GotoIf(IsDictionaryMap(initial_map), &allocate_properties); 3221cb0ef41Sopenharmony_ci { 3231cb0ef41Sopenharmony_ci properties = EmptyFixedArrayConstant(); 3241cb0ef41Sopenharmony_ci Goto(&instantiate_map); 3251cb0ef41Sopenharmony_ci } 3261cb0ef41Sopenharmony_ci BIND(&allocate_properties); 3271cb0ef41Sopenharmony_ci { 3281cb0ef41Sopenharmony_ci if (V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL) { 3291cb0ef41Sopenharmony_ci properties = 3301cb0ef41Sopenharmony_ci AllocateSwissNameDictionary(SwissNameDictionary::kInitialCapacity); 3311cb0ef41Sopenharmony_ci } else { 3321cb0ef41Sopenharmony_ci properties = AllocateNameDictionary(NameDictionary::kInitialCapacity); 3331cb0ef41Sopenharmony_ci } 3341cb0ef41Sopenharmony_ci Goto(&instantiate_map); 3351cb0ef41Sopenharmony_ci } 3361cb0ef41Sopenharmony_ci 3371cb0ef41Sopenharmony_ci BIND(&instantiate_map); 3381cb0ef41Sopenharmony_ci return AllocateJSObjectFromMap(initial_map, properties.value(), base::nullopt, 3391cb0ef41Sopenharmony_ci AllocationFlag::kNone, kWithSlackTracking); 3401cb0ef41Sopenharmony_ci} 3411cb0ef41Sopenharmony_ci 3421cb0ef41Sopenharmony_ciTNode<Context> ConstructorBuiltinsAssembler::FastNewFunctionContext( 3431cb0ef41Sopenharmony_ci TNode<ScopeInfo> scope_info, TNode<Uint32T> slots, TNode<Context> context, 3441cb0ef41Sopenharmony_ci ScopeType scope_type) { 3451cb0ef41Sopenharmony_ci TNode<IntPtrT> slots_intptr = Signed(ChangeUint32ToWord(slots)); 3461cb0ef41Sopenharmony_ci TNode<IntPtrT> size = ElementOffsetFromIndex(slots_intptr, PACKED_ELEMENTS, 3471cb0ef41Sopenharmony_ci Context::kTodoHeaderSize); 3481cb0ef41Sopenharmony_ci 3491cb0ef41Sopenharmony_ci // Create a new closure from the given function info in new space 3501cb0ef41Sopenharmony_ci TNode<Context> function_context = 3511cb0ef41Sopenharmony_ci UncheckedCast<Context>(AllocateInNewSpace(size)); 3521cb0ef41Sopenharmony_ci 3531cb0ef41Sopenharmony_ci TNode<NativeContext> native_context = LoadNativeContext(context); 3541cb0ef41Sopenharmony_ci Context::Field index; 3551cb0ef41Sopenharmony_ci switch (scope_type) { 3561cb0ef41Sopenharmony_ci case EVAL_SCOPE: 3571cb0ef41Sopenharmony_ci index = Context::EVAL_CONTEXT_MAP_INDEX; 3581cb0ef41Sopenharmony_ci break; 3591cb0ef41Sopenharmony_ci case FUNCTION_SCOPE: 3601cb0ef41Sopenharmony_ci index = Context::FUNCTION_CONTEXT_MAP_INDEX; 3611cb0ef41Sopenharmony_ci break; 3621cb0ef41Sopenharmony_ci default: 3631cb0ef41Sopenharmony_ci UNREACHABLE(); 3641cb0ef41Sopenharmony_ci } 3651cb0ef41Sopenharmony_ci TNode<Map> map = CAST(LoadContextElement(native_context, index)); 3661cb0ef41Sopenharmony_ci // Set up the header. 3671cb0ef41Sopenharmony_ci StoreMapNoWriteBarrier(function_context, map); 3681cb0ef41Sopenharmony_ci TNode<IntPtrT> min_context_slots = IntPtrConstant(Context::MIN_CONTEXT_SLOTS); 3691cb0ef41Sopenharmony_ci // TODO(ishell): for now, length also includes MIN_CONTEXT_SLOTS. 3701cb0ef41Sopenharmony_ci TNode<IntPtrT> length = IntPtrAdd(slots_intptr, min_context_slots); 3711cb0ef41Sopenharmony_ci StoreObjectFieldNoWriteBarrier(function_context, Context::kLengthOffset, 3721cb0ef41Sopenharmony_ci SmiTag(length)); 3731cb0ef41Sopenharmony_ci StoreObjectFieldNoWriteBarrier(function_context, Context::kScopeInfoOffset, 3741cb0ef41Sopenharmony_ci scope_info); 3751cb0ef41Sopenharmony_ci StoreObjectFieldNoWriteBarrier(function_context, Context::kPreviousOffset, 3761cb0ef41Sopenharmony_ci context); 3771cb0ef41Sopenharmony_ci 3781cb0ef41Sopenharmony_ci // Initialize the varrest of the slots to undefined. 3791cb0ef41Sopenharmony_ci TNode<Oddball> undefined = UndefinedConstant(); 3801cb0ef41Sopenharmony_ci TNode<IntPtrT> start_offset = IntPtrConstant(Context::kTodoHeaderSize); 3811cb0ef41Sopenharmony_ci CodeStubAssembler::VariableList vars(0, zone()); 3821cb0ef41Sopenharmony_ci BuildFastLoop<IntPtrT>( 3831cb0ef41Sopenharmony_ci vars, start_offset, size, 3841cb0ef41Sopenharmony_ci [=](TNode<IntPtrT> offset) { 3851cb0ef41Sopenharmony_ci StoreObjectFieldNoWriteBarrier(function_context, offset, undefined); 3861cb0ef41Sopenharmony_ci }, 3871cb0ef41Sopenharmony_ci kTaggedSize, IndexAdvanceMode::kPost); 3881cb0ef41Sopenharmony_ci return function_context; 3891cb0ef41Sopenharmony_ci} 3901cb0ef41Sopenharmony_ci 3911cb0ef41Sopenharmony_ciTNode<JSRegExp> ConstructorBuiltinsAssembler::CreateRegExpLiteral( 3921cb0ef41Sopenharmony_ci TNode<HeapObject> maybe_feedback_vector, TNode<TaggedIndex> slot, 3931cb0ef41Sopenharmony_ci TNode<Object> pattern, TNode<Smi> flags, TNode<Context> context) { 3941cb0ef41Sopenharmony_ci Label call_runtime(this, Label::kDeferred), end(this); 3951cb0ef41Sopenharmony_ci 3961cb0ef41Sopenharmony_ci GotoIf(IsUndefined(maybe_feedback_vector), &call_runtime); 3971cb0ef41Sopenharmony_ci 3981cb0ef41Sopenharmony_ci TVARIABLE(JSRegExp, result); 3991cb0ef41Sopenharmony_ci TNode<FeedbackVector> feedback_vector = CAST(maybe_feedback_vector); 4001cb0ef41Sopenharmony_ci TNode<Object> literal_site = 4011cb0ef41Sopenharmony_ci CAST(LoadFeedbackVectorSlot(feedback_vector, slot)); 4021cb0ef41Sopenharmony_ci GotoIfNot(HasBoilerplate(literal_site), &call_runtime); 4031cb0ef41Sopenharmony_ci { 4041cb0ef41Sopenharmony_ci STATIC_ASSERT(JSRegExp::kDataOffset == JSObject::kHeaderSize); 4051cb0ef41Sopenharmony_ci STATIC_ASSERT(JSRegExp::kSourceOffset == 4061cb0ef41Sopenharmony_ci JSRegExp::kDataOffset + kTaggedSize); 4071cb0ef41Sopenharmony_ci STATIC_ASSERT(JSRegExp::kFlagsOffset == 4081cb0ef41Sopenharmony_ci JSRegExp::kSourceOffset + kTaggedSize); 4091cb0ef41Sopenharmony_ci STATIC_ASSERT(JSRegExp::kHeaderSize == 4101cb0ef41Sopenharmony_ci JSRegExp::kFlagsOffset + kTaggedSize); 4111cb0ef41Sopenharmony_ci STATIC_ASSERT(JSRegExp::kLastIndexOffset == JSRegExp::kHeaderSize); 4121cb0ef41Sopenharmony_ci DCHECK_EQ(JSRegExp::Size(), JSRegExp::kLastIndexOffset + kTaggedSize); 4131cb0ef41Sopenharmony_ci 4141cb0ef41Sopenharmony_ci TNode<RegExpBoilerplateDescription> boilerplate = CAST(literal_site); 4151cb0ef41Sopenharmony_ci TNode<HeapObject> new_object = Allocate(JSRegExp::Size()); 4161cb0ef41Sopenharmony_ci 4171cb0ef41Sopenharmony_ci // Initialize Object fields. 4181cb0ef41Sopenharmony_ci TNode<JSFunction> regexp_function = CAST(LoadContextElement( 4191cb0ef41Sopenharmony_ci LoadNativeContext(context), Context::REGEXP_FUNCTION_INDEX)); 4201cb0ef41Sopenharmony_ci TNode<Map> initial_map = CAST(LoadObjectField( 4211cb0ef41Sopenharmony_ci regexp_function, JSFunction::kPrototypeOrInitialMapOffset)); 4221cb0ef41Sopenharmony_ci StoreMapNoWriteBarrier(new_object, initial_map); 4231cb0ef41Sopenharmony_ci // Initialize JSReceiver fields. 4241cb0ef41Sopenharmony_ci StoreObjectFieldRoot(new_object, JSReceiver::kPropertiesOrHashOffset, 4251cb0ef41Sopenharmony_ci RootIndex::kEmptyFixedArray); 4261cb0ef41Sopenharmony_ci // Initialize JSObject fields. 4271cb0ef41Sopenharmony_ci StoreObjectFieldRoot(new_object, JSObject::kElementsOffset, 4281cb0ef41Sopenharmony_ci RootIndex::kEmptyFixedArray); 4291cb0ef41Sopenharmony_ci // Initialize JSRegExp fields. 4301cb0ef41Sopenharmony_ci StoreObjectFieldNoWriteBarrier( 4311cb0ef41Sopenharmony_ci new_object, JSRegExp::kDataOffset, 4321cb0ef41Sopenharmony_ci LoadObjectField(boilerplate, 4331cb0ef41Sopenharmony_ci RegExpBoilerplateDescription::kDataOffset)); 4341cb0ef41Sopenharmony_ci StoreObjectFieldNoWriteBarrier( 4351cb0ef41Sopenharmony_ci new_object, JSRegExp::kSourceOffset, 4361cb0ef41Sopenharmony_ci LoadObjectField(boilerplate, 4371cb0ef41Sopenharmony_ci RegExpBoilerplateDescription::kSourceOffset)); 4381cb0ef41Sopenharmony_ci StoreObjectFieldNoWriteBarrier( 4391cb0ef41Sopenharmony_ci new_object, JSRegExp::kFlagsOffset, 4401cb0ef41Sopenharmony_ci LoadObjectField(boilerplate, 4411cb0ef41Sopenharmony_ci RegExpBoilerplateDescription::kFlagsOffset)); 4421cb0ef41Sopenharmony_ci StoreObjectFieldNoWriteBarrier( 4431cb0ef41Sopenharmony_ci new_object, JSRegExp::kLastIndexOffset, 4441cb0ef41Sopenharmony_ci SmiConstant(JSRegExp::kInitialLastIndexValue)); 4451cb0ef41Sopenharmony_ci 4461cb0ef41Sopenharmony_ci result = CAST(new_object); 4471cb0ef41Sopenharmony_ci Goto(&end); 4481cb0ef41Sopenharmony_ci } 4491cb0ef41Sopenharmony_ci 4501cb0ef41Sopenharmony_ci BIND(&call_runtime); 4511cb0ef41Sopenharmony_ci { 4521cb0ef41Sopenharmony_ci result = CAST(CallRuntime(Runtime::kCreateRegExpLiteral, context, 4531cb0ef41Sopenharmony_ci maybe_feedback_vector, slot, pattern, flags)); 4541cb0ef41Sopenharmony_ci Goto(&end); 4551cb0ef41Sopenharmony_ci } 4561cb0ef41Sopenharmony_ci 4571cb0ef41Sopenharmony_ci BIND(&end); 4581cb0ef41Sopenharmony_ci return result.value(); 4591cb0ef41Sopenharmony_ci} 4601cb0ef41Sopenharmony_ci 4611cb0ef41Sopenharmony_ciTNode<JSArray> ConstructorBuiltinsAssembler::CreateShallowArrayLiteral( 4621cb0ef41Sopenharmony_ci TNode<FeedbackVector> feedback_vector, TNode<TaggedIndex> slot, 4631cb0ef41Sopenharmony_ci TNode<Context> context, AllocationSiteMode allocation_site_mode, 4641cb0ef41Sopenharmony_ci Label* call_runtime) { 4651cb0ef41Sopenharmony_ci Label zero_capacity(this), cow_elements(this), fast_elements(this), 4661cb0ef41Sopenharmony_ci return_result(this); 4671cb0ef41Sopenharmony_ci 4681cb0ef41Sopenharmony_ci TNode<Object> maybe_allocation_site = 4691cb0ef41Sopenharmony_ci CAST(LoadFeedbackVectorSlot(feedback_vector, slot)); 4701cb0ef41Sopenharmony_ci GotoIfNot(HasBoilerplate(maybe_allocation_site), call_runtime); 4711cb0ef41Sopenharmony_ci 4721cb0ef41Sopenharmony_ci TNode<AllocationSite> allocation_site = CAST(maybe_allocation_site); 4731cb0ef41Sopenharmony_ci TNode<JSArray> boilerplate = CAST(LoadBoilerplate(allocation_site)); 4741cb0ef41Sopenharmony_ci 4751cb0ef41Sopenharmony_ci if (allocation_site_mode == TRACK_ALLOCATION_SITE && 4761cb0ef41Sopenharmony_ci V8_ALLOCATION_SITE_TRACKING_BOOL) { 4771cb0ef41Sopenharmony_ci return CloneFastJSArray(context, boilerplate, allocation_site); 4781cb0ef41Sopenharmony_ci } else { 4791cb0ef41Sopenharmony_ci return CloneFastJSArray(context, boilerplate); 4801cb0ef41Sopenharmony_ci } 4811cb0ef41Sopenharmony_ci} 4821cb0ef41Sopenharmony_ci 4831cb0ef41Sopenharmony_ciTNode<JSArray> ConstructorBuiltinsAssembler::CreateEmptyArrayLiteral( 4841cb0ef41Sopenharmony_ci TNode<FeedbackVector> feedback_vector, TNode<TaggedIndex> slot, 4851cb0ef41Sopenharmony_ci TNode<Context> context) { 4861cb0ef41Sopenharmony_ci // Array literals always have a valid AllocationSite to properly track 4871cb0ef41Sopenharmony_ci // elements transitions. 4881cb0ef41Sopenharmony_ci TNode<Object> maybe_allocation_site = 4891cb0ef41Sopenharmony_ci CAST(LoadFeedbackVectorSlot(feedback_vector, slot)); 4901cb0ef41Sopenharmony_ci TVARIABLE(AllocationSite, allocation_site); 4911cb0ef41Sopenharmony_ci 4921cb0ef41Sopenharmony_ci Label create_empty_array(this), 4931cb0ef41Sopenharmony_ci initialize_allocation_site(this, Label::kDeferred), done(this); 4941cb0ef41Sopenharmony_ci GotoIf(TaggedIsSmi(maybe_allocation_site), &initialize_allocation_site); 4951cb0ef41Sopenharmony_ci { 4961cb0ef41Sopenharmony_ci allocation_site = CAST(maybe_allocation_site); 4971cb0ef41Sopenharmony_ci Goto(&create_empty_array); 4981cb0ef41Sopenharmony_ci } 4991cb0ef41Sopenharmony_ci // TODO(cbruni): create the AllocationSite in CSA. 5001cb0ef41Sopenharmony_ci BIND(&initialize_allocation_site); 5011cb0ef41Sopenharmony_ci { 5021cb0ef41Sopenharmony_ci allocation_site = CreateAllocationSiteInFeedbackVector( 5031cb0ef41Sopenharmony_ci feedback_vector, 5041cb0ef41Sopenharmony_ci // TODO(v8:10047): pass slot as TaggedIndex here 5051cb0ef41Sopenharmony_ci Unsigned(TaggedIndexToIntPtr(slot))); 5061cb0ef41Sopenharmony_ci Goto(&create_empty_array); 5071cb0ef41Sopenharmony_ci } 5081cb0ef41Sopenharmony_ci 5091cb0ef41Sopenharmony_ci BIND(&create_empty_array); 5101cb0ef41Sopenharmony_ci TNode<Int32T> kind = LoadElementsKind(allocation_site.value()); 5111cb0ef41Sopenharmony_ci TNode<NativeContext> native_context = LoadNativeContext(context); 5121cb0ef41Sopenharmony_ci Comment("LoadJSArrayElementsMap"); 5131cb0ef41Sopenharmony_ci TNode<Map> array_map = LoadJSArrayElementsMap(kind, native_context); 5141cb0ef41Sopenharmony_ci TNode<IntPtrT> zero_intptr = IntPtrConstant(0); 5151cb0ef41Sopenharmony_ci TNode<Smi> zero = SmiConstant(0); 5161cb0ef41Sopenharmony_ci Comment("Allocate JSArray"); 5171cb0ef41Sopenharmony_ci base::Optional<TNode<AllocationSite>> site = 5181cb0ef41Sopenharmony_ci V8_ALLOCATION_SITE_TRACKING_BOOL 5191cb0ef41Sopenharmony_ci ? base::make_optional(allocation_site.value()) 5201cb0ef41Sopenharmony_ci : base::nullopt; 5211cb0ef41Sopenharmony_ci TNode<JSArray> result = AllocateJSArray(GetInitialFastElementsKind(), 5221cb0ef41Sopenharmony_ci array_map, zero_intptr, zero, site); 5231cb0ef41Sopenharmony_ci 5241cb0ef41Sopenharmony_ci Goto(&done); 5251cb0ef41Sopenharmony_ci BIND(&done); 5261cb0ef41Sopenharmony_ci 5271cb0ef41Sopenharmony_ci return result; 5281cb0ef41Sopenharmony_ci} 5291cb0ef41Sopenharmony_ci 5301cb0ef41Sopenharmony_ciTNode<HeapObject> ConstructorBuiltinsAssembler::CreateShallowObjectLiteral( 5311cb0ef41Sopenharmony_ci TNode<FeedbackVector> feedback_vector, TNode<TaggedIndex> slot, 5321cb0ef41Sopenharmony_ci Label* call_runtime) { 5331cb0ef41Sopenharmony_ci TNode<Object> maybe_allocation_site = 5341cb0ef41Sopenharmony_ci CAST(LoadFeedbackVectorSlot(feedback_vector, slot)); 5351cb0ef41Sopenharmony_ci GotoIfNot(HasBoilerplate(maybe_allocation_site), call_runtime); 5361cb0ef41Sopenharmony_ci 5371cb0ef41Sopenharmony_ci TNode<AllocationSite> allocation_site = CAST(maybe_allocation_site); 5381cb0ef41Sopenharmony_ci TNode<JSObject> boilerplate = LoadBoilerplate(allocation_site); 5391cb0ef41Sopenharmony_ci TNode<Map> boilerplate_map = LoadMap(boilerplate); 5401cb0ef41Sopenharmony_ci CSA_DCHECK(this, IsJSObjectMap(boilerplate_map)); 5411cb0ef41Sopenharmony_ci 5421cb0ef41Sopenharmony_ci TVARIABLE(HeapObject, var_properties); 5431cb0ef41Sopenharmony_ci { 5441cb0ef41Sopenharmony_ci TNode<Uint32T> bit_field_3 = LoadMapBitField3(boilerplate_map); 5451cb0ef41Sopenharmony_ci GotoIf(IsSetWord32<Map::Bits3::IsDeprecatedBit>(bit_field_3), call_runtime); 5461cb0ef41Sopenharmony_ci // Directly copy over the property store for dict-mode boilerplates. 5471cb0ef41Sopenharmony_ci Label if_dictionary(this), if_fast(this), done(this); 5481cb0ef41Sopenharmony_ci Branch(IsSetWord32<Map::Bits3::IsDictionaryMapBit>(bit_field_3), 5491cb0ef41Sopenharmony_ci &if_dictionary, &if_fast); 5501cb0ef41Sopenharmony_ci BIND(&if_dictionary); 5511cb0ef41Sopenharmony_ci { 5521cb0ef41Sopenharmony_ci Comment("Copy dictionary properties"); 5531cb0ef41Sopenharmony_ci if (V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL) { 5541cb0ef41Sopenharmony_ci var_properties = 5551cb0ef41Sopenharmony_ci CopySwissNameDictionary(CAST(LoadSlowProperties(boilerplate))); 5561cb0ef41Sopenharmony_ci } else { 5571cb0ef41Sopenharmony_ci var_properties = CopyNameDictionary( 5581cb0ef41Sopenharmony_ci CAST(LoadSlowProperties(boilerplate)), call_runtime); 5591cb0ef41Sopenharmony_ci } 5601cb0ef41Sopenharmony_ci // Slow objects have no in-object properties. 5611cb0ef41Sopenharmony_ci Goto(&done); 5621cb0ef41Sopenharmony_ci } 5631cb0ef41Sopenharmony_ci BIND(&if_fast); 5641cb0ef41Sopenharmony_ci { 5651cb0ef41Sopenharmony_ci // TODO(cbruni): support copying out-of-object properties. 5661cb0ef41Sopenharmony_ci TNode<HeapObject> boilerplate_properties = 5671cb0ef41Sopenharmony_ci LoadFastProperties(boilerplate); 5681cb0ef41Sopenharmony_ci GotoIfNot(IsEmptyFixedArray(boilerplate_properties), call_runtime); 5691cb0ef41Sopenharmony_ci var_properties = EmptyFixedArrayConstant(); 5701cb0ef41Sopenharmony_ci Goto(&done); 5711cb0ef41Sopenharmony_ci } 5721cb0ef41Sopenharmony_ci BIND(&done); 5731cb0ef41Sopenharmony_ci } 5741cb0ef41Sopenharmony_ci 5751cb0ef41Sopenharmony_ci TVARIABLE(FixedArrayBase, var_elements); 5761cb0ef41Sopenharmony_ci { 5771cb0ef41Sopenharmony_ci // Copy the elements backing store, assuming that it's flat. 5781cb0ef41Sopenharmony_ci Label if_empty_fixed_array(this), if_copy_elements(this), done(this); 5791cb0ef41Sopenharmony_ci TNode<FixedArrayBase> boilerplate_elements = LoadElements(boilerplate); 5801cb0ef41Sopenharmony_ci Branch(IsEmptyFixedArray(boilerplate_elements), &if_empty_fixed_array, 5811cb0ef41Sopenharmony_ci &if_copy_elements); 5821cb0ef41Sopenharmony_ci 5831cb0ef41Sopenharmony_ci BIND(&if_empty_fixed_array); 5841cb0ef41Sopenharmony_ci var_elements = boilerplate_elements; 5851cb0ef41Sopenharmony_ci Goto(&done); 5861cb0ef41Sopenharmony_ci 5871cb0ef41Sopenharmony_ci BIND(&if_copy_elements); 5881cb0ef41Sopenharmony_ci CSA_DCHECK(this, Word32BinaryNot( 5891cb0ef41Sopenharmony_ci IsFixedCOWArrayMap(LoadMap(boilerplate_elements)))); 5901cb0ef41Sopenharmony_ci auto flags = ExtractFixedArrayFlag::kAllFixedArrays; 5911cb0ef41Sopenharmony_ci var_elements = CloneFixedArray(boilerplate_elements, flags); 5921cb0ef41Sopenharmony_ci Goto(&done); 5931cb0ef41Sopenharmony_ci BIND(&done); 5941cb0ef41Sopenharmony_ci } 5951cb0ef41Sopenharmony_ci 5961cb0ef41Sopenharmony_ci // Ensure new-space allocation for a fresh JSObject so we can skip write 5971cb0ef41Sopenharmony_ci // barriers when copying all object fields. 5981cb0ef41Sopenharmony_ci STATIC_ASSERT(JSObject::kMaxInstanceSize < kMaxRegularHeapObjectSize); 5991cb0ef41Sopenharmony_ci TNode<IntPtrT> instance_size = 6001cb0ef41Sopenharmony_ci TimesTaggedSize(LoadMapInstanceSizeInWords(boilerplate_map)); 6011cb0ef41Sopenharmony_ci TNode<IntPtrT> allocation_size = instance_size; 6021cb0ef41Sopenharmony_ci bool needs_allocation_memento = FLAG_allocation_site_pretenuring; 6031cb0ef41Sopenharmony_ci if (needs_allocation_memento) { 6041cb0ef41Sopenharmony_ci DCHECK(V8_ALLOCATION_SITE_TRACKING_BOOL); 6051cb0ef41Sopenharmony_ci // Prepare for inner-allocating the AllocationMemento. 6061cb0ef41Sopenharmony_ci allocation_size = 6071cb0ef41Sopenharmony_ci IntPtrAdd(instance_size, IntPtrConstant(AllocationMemento::kSize)); 6081cb0ef41Sopenharmony_ci } 6091cb0ef41Sopenharmony_ci 6101cb0ef41Sopenharmony_ci TNode<HeapObject> copy = 6111cb0ef41Sopenharmony_ci UncheckedCast<HeapObject>(AllocateInNewSpace(allocation_size)); 6121cb0ef41Sopenharmony_ci { 6131cb0ef41Sopenharmony_ci Comment("Initialize Literal Copy"); 6141cb0ef41Sopenharmony_ci // Initialize Object fields. 6151cb0ef41Sopenharmony_ci StoreMapNoWriteBarrier(copy, boilerplate_map); 6161cb0ef41Sopenharmony_ci StoreObjectFieldNoWriteBarrier(copy, JSObject::kPropertiesOrHashOffset, 6171cb0ef41Sopenharmony_ci var_properties.value()); 6181cb0ef41Sopenharmony_ci StoreObjectFieldNoWriteBarrier(copy, JSObject::kElementsOffset, 6191cb0ef41Sopenharmony_ci var_elements.value()); 6201cb0ef41Sopenharmony_ci } 6211cb0ef41Sopenharmony_ci 6221cb0ef41Sopenharmony_ci // Initialize the AllocationMemento before potential GCs due to heap number 6231cb0ef41Sopenharmony_ci // allocation when copying the in-object properties. 6241cb0ef41Sopenharmony_ci if (needs_allocation_memento) { 6251cb0ef41Sopenharmony_ci InitializeAllocationMemento(copy, instance_size, allocation_site); 6261cb0ef41Sopenharmony_ci } 6271cb0ef41Sopenharmony_ci 6281cb0ef41Sopenharmony_ci { 6291cb0ef41Sopenharmony_ci // Copy over in-object properties. 6301cb0ef41Sopenharmony_ci Label continue_with_write_barrier(this), done_init(this); 6311cb0ef41Sopenharmony_ci TVARIABLE(IntPtrT, offset, IntPtrConstant(JSObject::kHeaderSize)); 6321cb0ef41Sopenharmony_ci { 6331cb0ef41Sopenharmony_ci Comment("Copy in-object properties fast"); 6341cb0ef41Sopenharmony_ci Label continue_fast(this, &offset); 6351cb0ef41Sopenharmony_ci Branch(IntPtrEqual(offset.value(), instance_size), &done_init, 6361cb0ef41Sopenharmony_ci &continue_fast); 6371cb0ef41Sopenharmony_ci BIND(&continue_fast); 6381cb0ef41Sopenharmony_ci TNode<Object> field = LoadObjectField(boilerplate, offset.value()); 6391cb0ef41Sopenharmony_ci Label store_field(this); 6401cb0ef41Sopenharmony_ci GotoIf(TaggedIsSmi(field), &store_field); 6411cb0ef41Sopenharmony_ci // TODO(leszeks): Read the field descriptor to decide if this heap 6421cb0ef41Sopenharmony_ci // number is mutable or not. 6431cb0ef41Sopenharmony_ci GotoIf(IsHeapNumber(CAST(field)), &continue_with_write_barrier); 6441cb0ef41Sopenharmony_ci Goto(&store_field); 6451cb0ef41Sopenharmony_ci BIND(&store_field); 6461cb0ef41Sopenharmony_ci StoreObjectFieldNoWriteBarrier(copy, offset.value(), field); 6471cb0ef41Sopenharmony_ci offset = IntPtrAdd(offset.value(), IntPtrConstant(kTaggedSize)); 6481cb0ef41Sopenharmony_ci Branch(WordNotEqual(offset.value(), instance_size), &continue_fast, 6491cb0ef41Sopenharmony_ci &done_init); 6501cb0ef41Sopenharmony_ci } 6511cb0ef41Sopenharmony_ci 6521cb0ef41Sopenharmony_ci // Continue initializing the literal after seeing the first sub-object 6531cb0ef41Sopenharmony_ci // potentially causing allocation. In this case we prepare the new literal 6541cb0ef41Sopenharmony_ci // by copying all pending fields over from the boilerplate and emit full 6551cb0ef41Sopenharmony_ci // write barriers from here on. 6561cb0ef41Sopenharmony_ci BIND(&continue_with_write_barrier); 6571cb0ef41Sopenharmony_ci { 6581cb0ef41Sopenharmony_ci Comment("Copy in-object properties slow"); 6591cb0ef41Sopenharmony_ci BuildFastLoop<IntPtrT>( 6601cb0ef41Sopenharmony_ci offset.value(), instance_size, 6611cb0ef41Sopenharmony_ci [=](TNode<IntPtrT> offset) { 6621cb0ef41Sopenharmony_ci // TODO(ishell): value decompression is not necessary here. 6631cb0ef41Sopenharmony_ci TNode<Object> field = LoadObjectField(boilerplate, offset); 6641cb0ef41Sopenharmony_ci StoreObjectFieldNoWriteBarrier(copy, offset, field); 6651cb0ef41Sopenharmony_ci }, 6661cb0ef41Sopenharmony_ci kTaggedSize, IndexAdvanceMode::kPost); 6671cb0ef41Sopenharmony_ci CopyMutableHeapNumbersInObject(copy, offset.value(), instance_size); 6681cb0ef41Sopenharmony_ci Goto(&done_init); 6691cb0ef41Sopenharmony_ci } 6701cb0ef41Sopenharmony_ci BIND(&done_init); 6711cb0ef41Sopenharmony_ci } 6721cb0ef41Sopenharmony_ci return copy; 6731cb0ef41Sopenharmony_ci} 6741cb0ef41Sopenharmony_ci 6751cb0ef41Sopenharmony_ci// Used by the CreateEmptyObjectLiteral bytecode and the Object constructor. 6761cb0ef41Sopenharmony_ciTNode<JSObject> ConstructorBuiltinsAssembler::CreateEmptyObjectLiteral( 6771cb0ef41Sopenharmony_ci TNode<Context> context) { 6781cb0ef41Sopenharmony_ci TNode<NativeContext> native_context = LoadNativeContext(context); 6791cb0ef41Sopenharmony_ci TNode<Map> map = LoadObjectFunctionInitialMap(native_context); 6801cb0ef41Sopenharmony_ci // Ensure that slack tracking is disabled for the map. 6811cb0ef41Sopenharmony_ci STATIC_ASSERT(Map::kNoSlackTracking == 0); 6821cb0ef41Sopenharmony_ci CSA_DCHECK(this, IsClearWord32<Map::Bits3::ConstructionCounterBits>( 6831cb0ef41Sopenharmony_ci LoadMapBitField3(map))); 6841cb0ef41Sopenharmony_ci TNode<FixedArray> empty_fixed_array = EmptyFixedArrayConstant(); 6851cb0ef41Sopenharmony_ci TNode<JSObject> result = 6861cb0ef41Sopenharmony_ci AllocateJSObjectFromMap(map, empty_fixed_array, empty_fixed_array); 6871cb0ef41Sopenharmony_ci return result; 6881cb0ef41Sopenharmony_ci} 6891cb0ef41Sopenharmony_ci 6901cb0ef41Sopenharmony_civoid ConstructorBuiltinsAssembler::CopyMutableHeapNumbersInObject( 6911cb0ef41Sopenharmony_ci TNode<HeapObject> copy, TNode<IntPtrT> start_offset, 6921cb0ef41Sopenharmony_ci TNode<IntPtrT> end_offset) { 6931cb0ef41Sopenharmony_ci // Iterate over all object properties of a freshly copied object and 6941cb0ef41Sopenharmony_ci // duplicate mutable heap numbers. 6951cb0ef41Sopenharmony_ci Comment("Copy mutable HeapNumber values"); 6961cb0ef41Sopenharmony_ci BuildFastLoop<IntPtrT>( 6971cb0ef41Sopenharmony_ci start_offset, end_offset, 6981cb0ef41Sopenharmony_ci [=](TNode<IntPtrT> offset) { 6991cb0ef41Sopenharmony_ci TNode<Object> field = LoadObjectField(copy, offset); 7001cb0ef41Sopenharmony_ci Label copy_heap_number(this, Label::kDeferred), continue_loop(this); 7011cb0ef41Sopenharmony_ci // We only have to clone complex field values. 7021cb0ef41Sopenharmony_ci GotoIf(TaggedIsSmi(field), &continue_loop); 7031cb0ef41Sopenharmony_ci // TODO(leszeks): Read the field descriptor to decide if this heap 7041cb0ef41Sopenharmony_ci // number is mutable or not. 7051cb0ef41Sopenharmony_ci Branch(IsHeapNumber(CAST(field)), ©_heap_number, &continue_loop); 7061cb0ef41Sopenharmony_ci BIND(©_heap_number); 7071cb0ef41Sopenharmony_ci { 7081cb0ef41Sopenharmony_ci TNode<Float64T> double_value = LoadHeapNumberValue(CAST(field)); 7091cb0ef41Sopenharmony_ci TNode<HeapNumber> heap_number = 7101cb0ef41Sopenharmony_ci AllocateHeapNumberWithValue(double_value); 7111cb0ef41Sopenharmony_ci StoreObjectField(copy, offset, heap_number); 7121cb0ef41Sopenharmony_ci Goto(&continue_loop); 7131cb0ef41Sopenharmony_ci } 7141cb0ef41Sopenharmony_ci BIND(&continue_loop); 7151cb0ef41Sopenharmony_ci }, 7161cb0ef41Sopenharmony_ci kTaggedSize, IndexAdvanceMode::kPost); 7171cb0ef41Sopenharmony_ci} 7181cb0ef41Sopenharmony_ci 7191cb0ef41Sopenharmony_ci} // namespace internal 7201cb0ef41Sopenharmony_ci} // namespace v8 721