11cb0ef41Sopenharmony_ci// Copyright 2015 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/compiler/code-assembler.h" 61cb0ef41Sopenharmony_ci 71cb0ef41Sopenharmony_ci#include <ostream> 81cb0ef41Sopenharmony_ci 91cb0ef41Sopenharmony_ci#include "src/base/bits.h" 101cb0ef41Sopenharmony_ci#include "src/codegen/code-factory.h" 111cb0ef41Sopenharmony_ci#include "src/codegen/interface-descriptors-inl.h" 121cb0ef41Sopenharmony_ci#include "src/codegen/machine-type.h" 131cb0ef41Sopenharmony_ci#include "src/codegen/macro-assembler.h" 141cb0ef41Sopenharmony_ci#include "src/compiler/backend/instruction-selector.h" 151cb0ef41Sopenharmony_ci#include "src/compiler/graph.h" 161cb0ef41Sopenharmony_ci#include "src/compiler/js-graph.h" 171cb0ef41Sopenharmony_ci#include "src/compiler/linkage.h" 181cb0ef41Sopenharmony_ci#include "src/compiler/node-matchers.h" 191cb0ef41Sopenharmony_ci#include "src/compiler/pipeline.h" 201cb0ef41Sopenharmony_ci#include "src/compiler/raw-machine-assembler.h" 211cb0ef41Sopenharmony_ci#include "src/compiler/schedule.h" 221cb0ef41Sopenharmony_ci#include "src/execution/frames.h" 231cb0ef41Sopenharmony_ci#include "src/handles/handles-inl.h" 241cb0ef41Sopenharmony_ci#include "src/heap/factory-inl.h" 251cb0ef41Sopenharmony_ci#include "src/interpreter/bytecodes.h" 261cb0ef41Sopenharmony_ci#include "src/numbers/conversions-inl.h" 271cb0ef41Sopenharmony_ci#include "src/objects/smi.h" 281cb0ef41Sopenharmony_ci#include "src/utils/memcopy.h" 291cb0ef41Sopenharmony_ci#include "src/zone/zone.h" 301cb0ef41Sopenharmony_ci 311cb0ef41Sopenharmony_cinamespace v8 { 321cb0ef41Sopenharmony_cinamespace internal { 331cb0ef41Sopenharmony_ci 341cb0ef41Sopenharmony_ciconstexpr MachineType MachineTypeOf<Smi>::value; 351cb0ef41Sopenharmony_ciconstexpr MachineType MachineTypeOf<Object>::value; 361cb0ef41Sopenharmony_ciconstexpr MachineType MachineTypeOf<MaybeObject>::value; 371cb0ef41Sopenharmony_ci 381cb0ef41Sopenharmony_cinamespace compiler { 391cb0ef41Sopenharmony_ci 401cb0ef41Sopenharmony_cistatic_assert(std::is_convertible<TNode<Number>, TNode<Object>>::value, 411cb0ef41Sopenharmony_ci "test subtyping"); 421cb0ef41Sopenharmony_cistatic_assert( 431cb0ef41Sopenharmony_ci std::is_convertible<TNode<Number>, TNode<UnionT<Smi, HeapObject>>>::value, 441cb0ef41Sopenharmony_ci "test subtyping"); 451cb0ef41Sopenharmony_cistatic_assert( 461cb0ef41Sopenharmony_ci !std::is_convertible<TNode<UnionT<Smi, HeapObject>>, TNode<Number>>::value, 471cb0ef41Sopenharmony_ci "test subtyping"); 481cb0ef41Sopenharmony_ci 491cb0ef41Sopenharmony_ciCodeAssemblerState::CodeAssemblerState( 501cb0ef41Sopenharmony_ci Isolate* isolate, Zone* zone, const CallInterfaceDescriptor& descriptor, 511cb0ef41Sopenharmony_ci CodeKind kind, const char* name, Builtin builtin) 521cb0ef41Sopenharmony_ci // TODO(rmcilroy): Should we use Linkage::GetBytecodeDispatchDescriptor for 531cb0ef41Sopenharmony_ci // bytecode handlers? 541cb0ef41Sopenharmony_ci : CodeAssemblerState( 551cb0ef41Sopenharmony_ci isolate, zone, 561cb0ef41Sopenharmony_ci Linkage::GetStubCallDescriptor( 571cb0ef41Sopenharmony_ci zone, descriptor, descriptor.GetStackParameterCount(), 581cb0ef41Sopenharmony_ci CallDescriptor::kNoFlags, Operator::kNoProperties), 591cb0ef41Sopenharmony_ci kind, name, builtin) {} 601cb0ef41Sopenharmony_ci 611cb0ef41Sopenharmony_ciCodeAssemblerState::CodeAssemblerState(Isolate* isolate, Zone* zone, 621cb0ef41Sopenharmony_ci int parameter_count, CodeKind kind, 631cb0ef41Sopenharmony_ci const char* name, Builtin builtin) 641cb0ef41Sopenharmony_ci : CodeAssemblerState( 651cb0ef41Sopenharmony_ci isolate, zone, 661cb0ef41Sopenharmony_ci Linkage::GetJSCallDescriptor(zone, false, parameter_count, 671cb0ef41Sopenharmony_ci CallDescriptor::kCanUseRoots), 681cb0ef41Sopenharmony_ci kind, name, builtin) {} 691cb0ef41Sopenharmony_ci 701cb0ef41Sopenharmony_ciCodeAssemblerState::CodeAssemblerState(Isolate* isolate, Zone* zone, 711cb0ef41Sopenharmony_ci CallDescriptor* call_descriptor, 721cb0ef41Sopenharmony_ci CodeKind kind, const char* name, 731cb0ef41Sopenharmony_ci Builtin builtin) 741cb0ef41Sopenharmony_ci : raw_assembler_(new RawMachineAssembler( 751cb0ef41Sopenharmony_ci isolate, zone->New<Graph>(zone), call_descriptor, 761cb0ef41Sopenharmony_ci MachineType::PointerRepresentation(), 771cb0ef41Sopenharmony_ci InstructionSelector::SupportedMachineOperatorFlags(), 781cb0ef41Sopenharmony_ci InstructionSelector::AlignmentRequirements())), 791cb0ef41Sopenharmony_ci kind_(kind), 801cb0ef41Sopenharmony_ci name_(name), 811cb0ef41Sopenharmony_ci builtin_(builtin), 821cb0ef41Sopenharmony_ci code_generated_(false), 831cb0ef41Sopenharmony_ci variables_(zone), 841cb0ef41Sopenharmony_ci jsgraph_(zone->New<JSGraph>( 851cb0ef41Sopenharmony_ci isolate, raw_assembler_->graph(), raw_assembler_->common(), 861cb0ef41Sopenharmony_ci zone->New<JSOperatorBuilder>(zone), raw_assembler_->simplified(), 871cb0ef41Sopenharmony_ci raw_assembler_->machine())) {} 881cb0ef41Sopenharmony_ci 891cb0ef41Sopenharmony_ciCodeAssemblerState::~CodeAssemblerState() = default; 901cb0ef41Sopenharmony_ci 911cb0ef41Sopenharmony_ciint CodeAssemblerState::parameter_count() const { 921cb0ef41Sopenharmony_ci return static_cast<int>(raw_assembler_->call_descriptor()->ParameterCount()); 931cb0ef41Sopenharmony_ci} 941cb0ef41Sopenharmony_ci 951cb0ef41Sopenharmony_ciCodeAssembler::~CodeAssembler() = default; 961cb0ef41Sopenharmony_ci 971cb0ef41Sopenharmony_ci#if DEBUG 981cb0ef41Sopenharmony_civoid CodeAssemblerState::PrintCurrentBlock(std::ostream& os) { 991cb0ef41Sopenharmony_ci raw_assembler_->PrintCurrentBlock(os); 1001cb0ef41Sopenharmony_ci} 1011cb0ef41Sopenharmony_ci#endif 1021cb0ef41Sopenharmony_ci 1031cb0ef41Sopenharmony_cibool CodeAssemblerState::InsideBlock() { return raw_assembler_->InsideBlock(); } 1041cb0ef41Sopenharmony_ci 1051cb0ef41Sopenharmony_civoid CodeAssemblerState::SetInitialDebugInformation(const char* msg, 1061cb0ef41Sopenharmony_ci const char* file, 1071cb0ef41Sopenharmony_ci int line) { 1081cb0ef41Sopenharmony_ci#if DEBUG 1091cb0ef41Sopenharmony_ci AssemblerDebugInfo debug_info = {msg, file, line}; 1101cb0ef41Sopenharmony_ci raw_assembler_->SetCurrentExternalSourcePosition({file, line}); 1111cb0ef41Sopenharmony_ci raw_assembler_->SetInitialDebugInformation(debug_info); 1121cb0ef41Sopenharmony_ci#endif // DEBUG 1131cb0ef41Sopenharmony_ci} 1141cb0ef41Sopenharmony_ci 1151cb0ef41Sopenharmony_ciclass BreakOnNodeDecorator final : public GraphDecorator { 1161cb0ef41Sopenharmony_ci public: 1171cb0ef41Sopenharmony_ci explicit BreakOnNodeDecorator(NodeId node_id) : node_id_(node_id) {} 1181cb0ef41Sopenharmony_ci 1191cb0ef41Sopenharmony_ci void Decorate(Node* node) final { 1201cb0ef41Sopenharmony_ci if (node->id() == node_id_) { 1211cb0ef41Sopenharmony_ci base::OS::DebugBreak(); 1221cb0ef41Sopenharmony_ci } 1231cb0ef41Sopenharmony_ci } 1241cb0ef41Sopenharmony_ci 1251cb0ef41Sopenharmony_ci private: 1261cb0ef41Sopenharmony_ci NodeId node_id_; 1271cb0ef41Sopenharmony_ci}; 1281cb0ef41Sopenharmony_ci 1291cb0ef41Sopenharmony_civoid CodeAssembler::BreakOnNode(int node_id) { 1301cb0ef41Sopenharmony_ci Graph* graph = raw_assembler()->graph(); 1311cb0ef41Sopenharmony_ci Zone* zone = graph->zone(); 1321cb0ef41Sopenharmony_ci GraphDecorator* decorator = 1331cb0ef41Sopenharmony_ci zone->New<BreakOnNodeDecorator>(static_cast<NodeId>(node_id)); 1341cb0ef41Sopenharmony_ci graph->AddDecorator(decorator); 1351cb0ef41Sopenharmony_ci} 1361cb0ef41Sopenharmony_ci 1371cb0ef41Sopenharmony_civoid CodeAssembler::RegisterCallGenerationCallbacks( 1381cb0ef41Sopenharmony_ci const CodeAssemblerCallback& call_prologue, 1391cb0ef41Sopenharmony_ci const CodeAssemblerCallback& call_epilogue) { 1401cb0ef41Sopenharmony_ci // The callback can be registered only once. 1411cb0ef41Sopenharmony_ci DCHECK(!state_->call_prologue_); 1421cb0ef41Sopenharmony_ci DCHECK(!state_->call_epilogue_); 1431cb0ef41Sopenharmony_ci state_->call_prologue_ = call_prologue; 1441cb0ef41Sopenharmony_ci state_->call_epilogue_ = call_epilogue; 1451cb0ef41Sopenharmony_ci} 1461cb0ef41Sopenharmony_ci 1471cb0ef41Sopenharmony_civoid CodeAssembler::UnregisterCallGenerationCallbacks() { 1481cb0ef41Sopenharmony_ci state_->call_prologue_ = nullptr; 1491cb0ef41Sopenharmony_ci state_->call_epilogue_ = nullptr; 1501cb0ef41Sopenharmony_ci} 1511cb0ef41Sopenharmony_ci 1521cb0ef41Sopenharmony_civoid CodeAssembler::CallPrologue() { 1531cb0ef41Sopenharmony_ci if (state_->call_prologue_) { 1541cb0ef41Sopenharmony_ci state_->call_prologue_(); 1551cb0ef41Sopenharmony_ci } 1561cb0ef41Sopenharmony_ci} 1571cb0ef41Sopenharmony_ci 1581cb0ef41Sopenharmony_civoid CodeAssembler::CallEpilogue() { 1591cb0ef41Sopenharmony_ci if (state_->call_epilogue_) { 1601cb0ef41Sopenharmony_ci state_->call_epilogue_(); 1611cb0ef41Sopenharmony_ci } 1621cb0ef41Sopenharmony_ci} 1631cb0ef41Sopenharmony_ci 1641cb0ef41Sopenharmony_cibool CodeAssembler::Word32ShiftIsSafe() const { 1651cb0ef41Sopenharmony_ci return raw_assembler()->machine()->Word32ShiftIsSafe(); 1661cb0ef41Sopenharmony_ci} 1671cb0ef41Sopenharmony_ci 1681cb0ef41Sopenharmony_ci// static 1691cb0ef41Sopenharmony_ciHandle<Code> CodeAssembler::GenerateCode( 1701cb0ef41Sopenharmony_ci CodeAssemblerState* state, const AssemblerOptions& options, 1711cb0ef41Sopenharmony_ci const ProfileDataFromFile* profile_data) { 1721cb0ef41Sopenharmony_ci DCHECK(!state->code_generated_); 1731cb0ef41Sopenharmony_ci 1741cb0ef41Sopenharmony_ci RawMachineAssembler* rasm = state->raw_assembler_.get(); 1751cb0ef41Sopenharmony_ci 1761cb0ef41Sopenharmony_ci Handle<Code> code; 1771cb0ef41Sopenharmony_ci Graph* graph = rasm->ExportForOptimization(); 1781cb0ef41Sopenharmony_ci 1791cb0ef41Sopenharmony_ci code = Pipeline::GenerateCodeForCodeStub( 1801cb0ef41Sopenharmony_ci rasm->isolate(), rasm->call_descriptor(), graph, state->jsgraph_, 1811cb0ef41Sopenharmony_ci rasm->source_positions(), state->kind_, state->name_, 1821cb0ef41Sopenharmony_ci state->builtin_, options, profile_data) 1831cb0ef41Sopenharmony_ci .ToHandleChecked(); 1841cb0ef41Sopenharmony_ci 1851cb0ef41Sopenharmony_ci state->code_generated_ = true; 1861cb0ef41Sopenharmony_ci return code; 1871cb0ef41Sopenharmony_ci} 1881cb0ef41Sopenharmony_ci 1891cb0ef41Sopenharmony_cibool CodeAssembler::Is64() const { return raw_assembler()->machine()->Is64(); } 1901cb0ef41Sopenharmony_cibool CodeAssembler::Is32() const { return raw_assembler()->machine()->Is32(); } 1911cb0ef41Sopenharmony_ci 1921cb0ef41Sopenharmony_cibool CodeAssembler::IsFloat64RoundUpSupported() const { 1931cb0ef41Sopenharmony_ci return raw_assembler()->machine()->Float64RoundUp().IsSupported(); 1941cb0ef41Sopenharmony_ci} 1951cb0ef41Sopenharmony_ci 1961cb0ef41Sopenharmony_cibool CodeAssembler::IsFloat64RoundDownSupported() const { 1971cb0ef41Sopenharmony_ci return raw_assembler()->machine()->Float64RoundDown().IsSupported(); 1981cb0ef41Sopenharmony_ci} 1991cb0ef41Sopenharmony_ci 2001cb0ef41Sopenharmony_cibool CodeAssembler::IsFloat64RoundTiesEvenSupported() const { 2011cb0ef41Sopenharmony_ci return raw_assembler()->machine()->Float64RoundTiesEven().IsSupported(); 2021cb0ef41Sopenharmony_ci} 2031cb0ef41Sopenharmony_ci 2041cb0ef41Sopenharmony_cibool CodeAssembler::IsFloat64RoundTruncateSupported() const { 2051cb0ef41Sopenharmony_ci return raw_assembler()->machine()->Float64RoundTruncate().IsSupported(); 2061cb0ef41Sopenharmony_ci} 2071cb0ef41Sopenharmony_ci 2081cb0ef41Sopenharmony_cibool CodeAssembler::IsInt32AbsWithOverflowSupported() const { 2091cb0ef41Sopenharmony_ci return raw_assembler()->machine()->Int32AbsWithOverflow().IsSupported(); 2101cb0ef41Sopenharmony_ci} 2111cb0ef41Sopenharmony_ci 2121cb0ef41Sopenharmony_cibool CodeAssembler::IsInt64AbsWithOverflowSupported() const { 2131cb0ef41Sopenharmony_ci return raw_assembler()->machine()->Int64AbsWithOverflow().IsSupported(); 2141cb0ef41Sopenharmony_ci} 2151cb0ef41Sopenharmony_ci 2161cb0ef41Sopenharmony_cibool CodeAssembler::IsIntPtrAbsWithOverflowSupported() const { 2171cb0ef41Sopenharmony_ci return Is64() ? IsInt64AbsWithOverflowSupported() 2181cb0ef41Sopenharmony_ci : IsInt32AbsWithOverflowSupported(); 2191cb0ef41Sopenharmony_ci} 2201cb0ef41Sopenharmony_ci 2211cb0ef41Sopenharmony_cibool CodeAssembler::IsWord32PopcntSupported() const { 2221cb0ef41Sopenharmony_ci return raw_assembler()->machine()->Word32Popcnt().IsSupported(); 2231cb0ef41Sopenharmony_ci} 2241cb0ef41Sopenharmony_ci 2251cb0ef41Sopenharmony_cibool CodeAssembler::IsWord64PopcntSupported() const { 2261cb0ef41Sopenharmony_ci return raw_assembler()->machine()->Word64Popcnt().IsSupported(); 2271cb0ef41Sopenharmony_ci} 2281cb0ef41Sopenharmony_ci 2291cb0ef41Sopenharmony_cibool CodeAssembler::IsWord32CtzSupported() const { 2301cb0ef41Sopenharmony_ci return raw_assembler()->machine()->Word32Ctz().IsSupported(); 2311cb0ef41Sopenharmony_ci} 2321cb0ef41Sopenharmony_ci 2331cb0ef41Sopenharmony_cibool CodeAssembler::IsWord64CtzSupported() const { 2341cb0ef41Sopenharmony_ci return raw_assembler()->machine()->Word64Ctz().IsSupported(); 2351cb0ef41Sopenharmony_ci} 2361cb0ef41Sopenharmony_ci 2371cb0ef41Sopenharmony_ci#ifdef DEBUG 2381cb0ef41Sopenharmony_civoid CodeAssembler::GenerateCheckMaybeObjectIsObject(TNode<MaybeObject> node, 2391cb0ef41Sopenharmony_ci const char* location) { 2401cb0ef41Sopenharmony_ci Label ok(this); 2411cb0ef41Sopenharmony_ci GotoIf(WordNotEqual(WordAnd(BitcastMaybeObjectToWord(node), 2421cb0ef41Sopenharmony_ci IntPtrConstant(kHeapObjectTagMask)), 2431cb0ef41Sopenharmony_ci IntPtrConstant(kWeakHeapObjectTag)), 2441cb0ef41Sopenharmony_ci &ok); 2451cb0ef41Sopenharmony_ci base::EmbeddedVector<char, 1024> message; 2461cb0ef41Sopenharmony_ci SNPrintF(message, "no Object: %s", location); 2471cb0ef41Sopenharmony_ci TNode<String> message_node = StringConstant(message.begin()); 2481cb0ef41Sopenharmony_ci // This somewhat misuses the AbortCSADcheck runtime function. This will print 2491cb0ef41Sopenharmony_ci // "abort: CSA_DCHECK failed: <message>", which is good enough. 2501cb0ef41Sopenharmony_ci AbortCSADcheck(message_node); 2511cb0ef41Sopenharmony_ci Unreachable(); 2521cb0ef41Sopenharmony_ci Bind(&ok); 2531cb0ef41Sopenharmony_ci} 2541cb0ef41Sopenharmony_ci#endif 2551cb0ef41Sopenharmony_ci 2561cb0ef41Sopenharmony_ciTNode<Int32T> CodeAssembler::Int32Constant(int32_t value) { 2571cb0ef41Sopenharmony_ci return UncheckedCast<Int32T>(jsgraph()->Int32Constant(value)); 2581cb0ef41Sopenharmony_ci} 2591cb0ef41Sopenharmony_ci 2601cb0ef41Sopenharmony_ciTNode<Int64T> CodeAssembler::Int64Constant(int64_t value) { 2611cb0ef41Sopenharmony_ci return UncheckedCast<Int64T>(jsgraph()->Int64Constant(value)); 2621cb0ef41Sopenharmony_ci} 2631cb0ef41Sopenharmony_ci 2641cb0ef41Sopenharmony_ciTNode<IntPtrT> CodeAssembler::IntPtrConstant(intptr_t value) { 2651cb0ef41Sopenharmony_ci return UncheckedCast<IntPtrT>(jsgraph()->IntPtrConstant(value)); 2661cb0ef41Sopenharmony_ci} 2671cb0ef41Sopenharmony_ci 2681cb0ef41Sopenharmony_ciTNode<TaggedIndex> CodeAssembler::TaggedIndexConstant(intptr_t value) { 2691cb0ef41Sopenharmony_ci DCHECK(TaggedIndex::IsValid(value)); 2701cb0ef41Sopenharmony_ci return UncheckedCast<TaggedIndex>(raw_assembler()->IntPtrConstant(value)); 2711cb0ef41Sopenharmony_ci} 2721cb0ef41Sopenharmony_ci 2731cb0ef41Sopenharmony_ciTNode<Number> CodeAssembler::NumberConstant(double value) { 2741cb0ef41Sopenharmony_ci int smi_value; 2751cb0ef41Sopenharmony_ci if (DoubleToSmiInteger(value, &smi_value)) { 2761cb0ef41Sopenharmony_ci return UncheckedCast<Number>(SmiConstant(smi_value)); 2771cb0ef41Sopenharmony_ci } else { 2781cb0ef41Sopenharmony_ci // We allocate the heap number constant eagerly at this point instead of 2791cb0ef41Sopenharmony_ci // deferring allocation to code generation 2801cb0ef41Sopenharmony_ci // (see AllocateAndInstallRequestedHeapObjects) since that makes it easier 2811cb0ef41Sopenharmony_ci // to generate constant lookups for embedded builtins. 2821cb0ef41Sopenharmony_ci return UncheckedCast<Number>(HeapConstant( 2831cb0ef41Sopenharmony_ci isolate()->factory()->NewHeapNumberForCodeAssembler(value))); 2841cb0ef41Sopenharmony_ci } 2851cb0ef41Sopenharmony_ci} 2861cb0ef41Sopenharmony_ci 2871cb0ef41Sopenharmony_ciTNode<Smi> CodeAssembler::SmiConstant(Smi value) { 2881cb0ef41Sopenharmony_ci return UncheckedCast<Smi>(BitcastWordToTaggedSigned( 2891cb0ef41Sopenharmony_ci IntPtrConstant(static_cast<intptr_t>(value.ptr())))); 2901cb0ef41Sopenharmony_ci} 2911cb0ef41Sopenharmony_ci 2921cb0ef41Sopenharmony_ciTNode<Smi> CodeAssembler::SmiConstant(int value) { 2931cb0ef41Sopenharmony_ci return SmiConstant(Smi::FromInt(value)); 2941cb0ef41Sopenharmony_ci} 2951cb0ef41Sopenharmony_ci 2961cb0ef41Sopenharmony_ciTNode<HeapObject> CodeAssembler::UntypedHeapConstant( 2971cb0ef41Sopenharmony_ci Handle<HeapObject> object) { 2981cb0ef41Sopenharmony_ci return UncheckedCast<HeapObject>(jsgraph()->HeapConstant(object)); 2991cb0ef41Sopenharmony_ci} 3001cb0ef41Sopenharmony_ci 3011cb0ef41Sopenharmony_ciTNode<String> CodeAssembler::StringConstant(const char* str) { 3021cb0ef41Sopenharmony_ci Handle<String> internalized_string = 3031cb0ef41Sopenharmony_ci factory()->InternalizeString(base::OneByteVector(str)); 3041cb0ef41Sopenharmony_ci return UncheckedCast<String>(HeapConstant(internalized_string)); 3051cb0ef41Sopenharmony_ci} 3061cb0ef41Sopenharmony_ci 3071cb0ef41Sopenharmony_ciTNode<Oddball> CodeAssembler::BooleanConstant(bool value) { 3081cb0ef41Sopenharmony_ci Handle<Object> object = isolate()->factory()->ToBoolean(value); 3091cb0ef41Sopenharmony_ci return UncheckedCast<Oddball>( 3101cb0ef41Sopenharmony_ci jsgraph()->HeapConstant(Handle<HeapObject>::cast(object))); 3111cb0ef41Sopenharmony_ci} 3121cb0ef41Sopenharmony_ci 3131cb0ef41Sopenharmony_ciTNode<ExternalReference> CodeAssembler::ExternalConstant( 3141cb0ef41Sopenharmony_ci ExternalReference address) { 3151cb0ef41Sopenharmony_ci return UncheckedCast<ExternalReference>( 3161cb0ef41Sopenharmony_ci raw_assembler()->ExternalConstant(address)); 3171cb0ef41Sopenharmony_ci} 3181cb0ef41Sopenharmony_ci 3191cb0ef41Sopenharmony_ciTNode<Float32T> CodeAssembler::Float32Constant(double value) { 3201cb0ef41Sopenharmony_ci return UncheckedCast<Float32T>(jsgraph()->Float32Constant(value)); 3211cb0ef41Sopenharmony_ci} 3221cb0ef41Sopenharmony_ci 3231cb0ef41Sopenharmony_ciTNode<Float64T> CodeAssembler::Float64Constant(double value) { 3241cb0ef41Sopenharmony_ci return UncheckedCast<Float64T>(jsgraph()->Float64Constant(value)); 3251cb0ef41Sopenharmony_ci} 3261cb0ef41Sopenharmony_ci 3271cb0ef41Sopenharmony_cibool CodeAssembler::IsMapOffsetConstant(Node* node) { 3281cb0ef41Sopenharmony_ci return raw_assembler()->IsMapOffsetConstant(node); 3291cb0ef41Sopenharmony_ci} 3301cb0ef41Sopenharmony_ci 3311cb0ef41Sopenharmony_cibool CodeAssembler::TryToInt32Constant(TNode<IntegralT> node, 3321cb0ef41Sopenharmony_ci int32_t* out_value) { 3331cb0ef41Sopenharmony_ci { 3341cb0ef41Sopenharmony_ci Int64Matcher m(node); 3351cb0ef41Sopenharmony_ci if (m.HasResolvedValue() && 3361cb0ef41Sopenharmony_ci m.IsInRange(std::numeric_limits<int32_t>::min(), 3371cb0ef41Sopenharmony_ci std::numeric_limits<int32_t>::max())) { 3381cb0ef41Sopenharmony_ci *out_value = static_cast<int32_t>(m.ResolvedValue()); 3391cb0ef41Sopenharmony_ci return true; 3401cb0ef41Sopenharmony_ci } 3411cb0ef41Sopenharmony_ci } 3421cb0ef41Sopenharmony_ci 3431cb0ef41Sopenharmony_ci { 3441cb0ef41Sopenharmony_ci Int32Matcher m(node); 3451cb0ef41Sopenharmony_ci if (m.HasResolvedValue()) { 3461cb0ef41Sopenharmony_ci *out_value = m.ResolvedValue(); 3471cb0ef41Sopenharmony_ci return true; 3481cb0ef41Sopenharmony_ci } 3491cb0ef41Sopenharmony_ci } 3501cb0ef41Sopenharmony_ci 3511cb0ef41Sopenharmony_ci return false; 3521cb0ef41Sopenharmony_ci} 3531cb0ef41Sopenharmony_ci 3541cb0ef41Sopenharmony_cibool CodeAssembler::TryToInt64Constant(TNode<IntegralT> node, 3551cb0ef41Sopenharmony_ci int64_t* out_value) { 3561cb0ef41Sopenharmony_ci Int64Matcher m(node); 3571cb0ef41Sopenharmony_ci if (m.HasResolvedValue()) *out_value = m.ResolvedValue(); 3581cb0ef41Sopenharmony_ci return m.HasResolvedValue(); 3591cb0ef41Sopenharmony_ci} 3601cb0ef41Sopenharmony_ci 3611cb0ef41Sopenharmony_cibool CodeAssembler::TryToSmiConstant(TNode<Smi> tnode, Smi* out_value) { 3621cb0ef41Sopenharmony_ci Node* node = tnode; 3631cb0ef41Sopenharmony_ci if (node->opcode() == IrOpcode::kBitcastWordToTaggedSigned) { 3641cb0ef41Sopenharmony_ci node = node->InputAt(0); 3651cb0ef41Sopenharmony_ci } 3661cb0ef41Sopenharmony_ci return TryToSmiConstant(ReinterpretCast<IntPtrT>(tnode), out_value); 3671cb0ef41Sopenharmony_ci} 3681cb0ef41Sopenharmony_ci 3691cb0ef41Sopenharmony_cibool CodeAssembler::TryToSmiConstant(TNode<IntegralT> node, Smi* out_value) { 3701cb0ef41Sopenharmony_ci IntPtrMatcher m(node); 3711cb0ef41Sopenharmony_ci if (m.HasResolvedValue()) { 3721cb0ef41Sopenharmony_ci intptr_t value = m.ResolvedValue(); 3731cb0ef41Sopenharmony_ci // Make sure that the value is actually a smi 3741cb0ef41Sopenharmony_ci CHECK_EQ(0, value & ((static_cast<intptr_t>(1) << kSmiShiftSize) - 1)); 3751cb0ef41Sopenharmony_ci *out_value = Smi(static_cast<Address>(value)); 3761cb0ef41Sopenharmony_ci return true; 3771cb0ef41Sopenharmony_ci } 3781cb0ef41Sopenharmony_ci return false; 3791cb0ef41Sopenharmony_ci} 3801cb0ef41Sopenharmony_ci 3811cb0ef41Sopenharmony_cibool CodeAssembler::TryToIntPtrConstant(TNode<Smi> tnode, intptr_t* out_value) { 3821cb0ef41Sopenharmony_ci Node* node = tnode; 3831cb0ef41Sopenharmony_ci if (node->opcode() == IrOpcode::kBitcastWordToTaggedSigned || 3841cb0ef41Sopenharmony_ci node->opcode() == IrOpcode::kBitcastWordToTagged) { 3851cb0ef41Sopenharmony_ci node = node->InputAt(0); 3861cb0ef41Sopenharmony_ci } 3871cb0ef41Sopenharmony_ci return TryToIntPtrConstant(ReinterpretCast<IntPtrT>(tnode), out_value); 3881cb0ef41Sopenharmony_ci} 3891cb0ef41Sopenharmony_ci 3901cb0ef41Sopenharmony_cibool CodeAssembler::TryToIntPtrConstant(TNode<IntegralT> node, 3911cb0ef41Sopenharmony_ci intptr_t* out_value) { 3921cb0ef41Sopenharmony_ci IntPtrMatcher m(node); 3931cb0ef41Sopenharmony_ci if (m.HasResolvedValue()) *out_value = m.ResolvedValue(); 3941cb0ef41Sopenharmony_ci return m.HasResolvedValue(); 3951cb0ef41Sopenharmony_ci} 3961cb0ef41Sopenharmony_ci 3971cb0ef41Sopenharmony_cibool CodeAssembler::IsUndefinedConstant(TNode<Object> node) { 3981cb0ef41Sopenharmony_ci compiler::HeapObjectMatcher m(node); 3991cb0ef41Sopenharmony_ci return m.Is(isolate()->factory()->undefined_value()); 4001cb0ef41Sopenharmony_ci} 4011cb0ef41Sopenharmony_ci 4021cb0ef41Sopenharmony_cibool CodeAssembler::IsNullConstant(TNode<Object> node) { 4031cb0ef41Sopenharmony_ci compiler::HeapObjectMatcher m(node); 4041cb0ef41Sopenharmony_ci return m.Is(isolate()->factory()->null_value()); 4051cb0ef41Sopenharmony_ci} 4061cb0ef41Sopenharmony_ci 4071cb0ef41Sopenharmony_ciNode* CodeAssembler::UntypedParameter(int index) { 4081cb0ef41Sopenharmony_ci if (index == kTargetParameterIndex) return raw_assembler()->TargetParameter(); 4091cb0ef41Sopenharmony_ci return raw_assembler()->Parameter(index); 4101cb0ef41Sopenharmony_ci} 4111cb0ef41Sopenharmony_ci 4121cb0ef41Sopenharmony_cibool CodeAssembler::IsJSFunctionCall() const { 4131cb0ef41Sopenharmony_ci auto call_descriptor = raw_assembler()->call_descriptor(); 4141cb0ef41Sopenharmony_ci return call_descriptor->IsJSFunctionCall(); 4151cb0ef41Sopenharmony_ci} 4161cb0ef41Sopenharmony_ci 4171cb0ef41Sopenharmony_ciTNode<Context> CodeAssembler::GetJSContextParameter() { 4181cb0ef41Sopenharmony_ci auto call_descriptor = raw_assembler()->call_descriptor(); 4191cb0ef41Sopenharmony_ci DCHECK(call_descriptor->IsJSFunctionCall()); 4201cb0ef41Sopenharmony_ci return Parameter<Context>(Linkage::GetJSCallContextParamIndex( 4211cb0ef41Sopenharmony_ci static_cast<int>(call_descriptor->JSParameterCount()))); 4221cb0ef41Sopenharmony_ci} 4231cb0ef41Sopenharmony_ci 4241cb0ef41Sopenharmony_civoid CodeAssembler::Return(TNode<Object> value) { 4251cb0ef41Sopenharmony_ci DCHECK_EQ(1, raw_assembler()->call_descriptor()->ReturnCount()); 4261cb0ef41Sopenharmony_ci DCHECK(raw_assembler()->call_descriptor()->GetReturnType(0).IsTagged()); 4271cb0ef41Sopenharmony_ci return raw_assembler()->Return(value); 4281cb0ef41Sopenharmony_ci} 4291cb0ef41Sopenharmony_ci 4301cb0ef41Sopenharmony_civoid CodeAssembler::Return(TNode<Object> value1, TNode<Object> value2) { 4311cb0ef41Sopenharmony_ci DCHECK_EQ(2, raw_assembler()->call_descriptor()->ReturnCount()); 4321cb0ef41Sopenharmony_ci DCHECK(raw_assembler()->call_descriptor()->GetReturnType(0).IsTagged()); 4331cb0ef41Sopenharmony_ci DCHECK(raw_assembler()->call_descriptor()->GetReturnType(1).IsTagged()); 4341cb0ef41Sopenharmony_ci return raw_assembler()->Return(value1, value2); 4351cb0ef41Sopenharmony_ci} 4361cb0ef41Sopenharmony_ci 4371cb0ef41Sopenharmony_civoid CodeAssembler::Return(TNode<Object> value1, TNode<Object> value2, 4381cb0ef41Sopenharmony_ci TNode<Object> value3) { 4391cb0ef41Sopenharmony_ci DCHECK_EQ(3, raw_assembler()->call_descriptor()->ReturnCount()); 4401cb0ef41Sopenharmony_ci DCHECK(raw_assembler()->call_descriptor()->GetReturnType(0).IsTagged()); 4411cb0ef41Sopenharmony_ci DCHECK(raw_assembler()->call_descriptor()->GetReturnType(1).IsTagged()); 4421cb0ef41Sopenharmony_ci DCHECK(raw_assembler()->call_descriptor()->GetReturnType(2).IsTagged()); 4431cb0ef41Sopenharmony_ci return raw_assembler()->Return(value1, value2, value3); 4441cb0ef41Sopenharmony_ci} 4451cb0ef41Sopenharmony_ci 4461cb0ef41Sopenharmony_civoid CodeAssembler::Return(TNode<Int32T> value) { 4471cb0ef41Sopenharmony_ci DCHECK_EQ(1, raw_assembler()->call_descriptor()->ReturnCount()); 4481cb0ef41Sopenharmony_ci DCHECK_EQ(MachineType::Int32(), 4491cb0ef41Sopenharmony_ci raw_assembler()->call_descriptor()->GetReturnType(0)); 4501cb0ef41Sopenharmony_ci return raw_assembler()->Return(value); 4511cb0ef41Sopenharmony_ci} 4521cb0ef41Sopenharmony_ci 4531cb0ef41Sopenharmony_civoid CodeAssembler::Return(TNode<Uint32T> value) { 4541cb0ef41Sopenharmony_ci DCHECK_EQ(1, raw_assembler()->call_descriptor()->ReturnCount()); 4551cb0ef41Sopenharmony_ci DCHECK_EQ(MachineType::Uint32(), 4561cb0ef41Sopenharmony_ci raw_assembler()->call_descriptor()->GetReturnType(0)); 4571cb0ef41Sopenharmony_ci return raw_assembler()->Return(value); 4581cb0ef41Sopenharmony_ci} 4591cb0ef41Sopenharmony_ci 4601cb0ef41Sopenharmony_civoid CodeAssembler::Return(TNode<WordT> value) { 4611cb0ef41Sopenharmony_ci DCHECK_EQ(1, raw_assembler()->call_descriptor()->ReturnCount()); 4621cb0ef41Sopenharmony_ci DCHECK_EQ( 4631cb0ef41Sopenharmony_ci MachineType::PointerRepresentation(), 4641cb0ef41Sopenharmony_ci raw_assembler()->call_descriptor()->GetReturnType(0).representation()); 4651cb0ef41Sopenharmony_ci return raw_assembler()->Return(value); 4661cb0ef41Sopenharmony_ci} 4671cb0ef41Sopenharmony_ci 4681cb0ef41Sopenharmony_civoid CodeAssembler::Return(TNode<Float32T> value) { 4691cb0ef41Sopenharmony_ci DCHECK_EQ(1, raw_assembler()->call_descriptor()->ReturnCount()); 4701cb0ef41Sopenharmony_ci DCHECK_EQ(MachineType::Float32(), 4711cb0ef41Sopenharmony_ci raw_assembler()->call_descriptor()->GetReturnType(0)); 4721cb0ef41Sopenharmony_ci return raw_assembler()->Return(value); 4731cb0ef41Sopenharmony_ci} 4741cb0ef41Sopenharmony_ci 4751cb0ef41Sopenharmony_civoid CodeAssembler::Return(TNode<Float64T> value) { 4761cb0ef41Sopenharmony_ci DCHECK_EQ(1, raw_assembler()->call_descriptor()->ReturnCount()); 4771cb0ef41Sopenharmony_ci DCHECK_EQ(MachineType::Float64(), 4781cb0ef41Sopenharmony_ci raw_assembler()->call_descriptor()->GetReturnType(0)); 4791cb0ef41Sopenharmony_ci return raw_assembler()->Return(value); 4801cb0ef41Sopenharmony_ci} 4811cb0ef41Sopenharmony_ci 4821cb0ef41Sopenharmony_civoid CodeAssembler::Return(TNode<WordT> value1, TNode<WordT> value2) { 4831cb0ef41Sopenharmony_ci DCHECK_EQ(2, raw_assembler()->call_descriptor()->ReturnCount()); 4841cb0ef41Sopenharmony_ci DCHECK_EQ( 4851cb0ef41Sopenharmony_ci MachineType::PointerRepresentation(), 4861cb0ef41Sopenharmony_ci raw_assembler()->call_descriptor()->GetReturnType(0).representation()); 4871cb0ef41Sopenharmony_ci DCHECK_EQ( 4881cb0ef41Sopenharmony_ci MachineType::PointerRepresentation(), 4891cb0ef41Sopenharmony_ci raw_assembler()->call_descriptor()->GetReturnType(1).representation()); 4901cb0ef41Sopenharmony_ci return raw_assembler()->Return(value1, value2); 4911cb0ef41Sopenharmony_ci} 4921cb0ef41Sopenharmony_ci 4931cb0ef41Sopenharmony_civoid CodeAssembler::Return(TNode<WordT> value1, TNode<Object> value2) { 4941cb0ef41Sopenharmony_ci DCHECK_EQ(2, raw_assembler()->call_descriptor()->ReturnCount()); 4951cb0ef41Sopenharmony_ci DCHECK_EQ( 4961cb0ef41Sopenharmony_ci MachineType::PointerRepresentation(), 4971cb0ef41Sopenharmony_ci raw_assembler()->call_descriptor()->GetReturnType(0).representation()); 4981cb0ef41Sopenharmony_ci DCHECK(raw_assembler()->call_descriptor()->GetReturnType(1).IsTagged()); 4991cb0ef41Sopenharmony_ci return raw_assembler()->Return(value1, value2); 5001cb0ef41Sopenharmony_ci} 5011cb0ef41Sopenharmony_ci 5021cb0ef41Sopenharmony_civoid CodeAssembler::PopAndReturn(Node* pop, Node* value) { 5031cb0ef41Sopenharmony_ci DCHECK_EQ(1, raw_assembler()->call_descriptor()->ReturnCount()); 5041cb0ef41Sopenharmony_ci return raw_assembler()->PopAndReturn(pop, value); 5051cb0ef41Sopenharmony_ci} 5061cb0ef41Sopenharmony_ci 5071cb0ef41Sopenharmony_civoid CodeAssembler::ReturnIf(TNode<BoolT> condition, TNode<Object> value) { 5081cb0ef41Sopenharmony_ci Label if_return(this), if_continue(this); 5091cb0ef41Sopenharmony_ci Branch(condition, &if_return, &if_continue); 5101cb0ef41Sopenharmony_ci Bind(&if_return); 5111cb0ef41Sopenharmony_ci Return(value); 5121cb0ef41Sopenharmony_ci Bind(&if_continue); 5131cb0ef41Sopenharmony_ci} 5141cb0ef41Sopenharmony_ci 5151cb0ef41Sopenharmony_civoid CodeAssembler::AbortCSADcheck(Node* message) { 5161cb0ef41Sopenharmony_ci raw_assembler()->AbortCSADcheck(message); 5171cb0ef41Sopenharmony_ci} 5181cb0ef41Sopenharmony_ci 5191cb0ef41Sopenharmony_civoid CodeAssembler::DebugBreak() { raw_assembler()->DebugBreak(); } 5201cb0ef41Sopenharmony_ci 5211cb0ef41Sopenharmony_civoid CodeAssembler::Unreachable() { 5221cb0ef41Sopenharmony_ci DebugBreak(); 5231cb0ef41Sopenharmony_ci raw_assembler()->Unreachable(); 5241cb0ef41Sopenharmony_ci} 5251cb0ef41Sopenharmony_ci 5261cb0ef41Sopenharmony_civoid CodeAssembler::Comment(std::string str) { 5271cb0ef41Sopenharmony_ci if (!FLAG_code_comments) return; 5281cb0ef41Sopenharmony_ci raw_assembler()->Comment(str); 5291cb0ef41Sopenharmony_ci} 5301cb0ef41Sopenharmony_ci 5311cb0ef41Sopenharmony_civoid CodeAssembler::StaticAssert(TNode<BoolT> value, const char* source) { 5321cb0ef41Sopenharmony_ci raw_assembler()->StaticAssert(value, source); 5331cb0ef41Sopenharmony_ci} 5341cb0ef41Sopenharmony_ci 5351cb0ef41Sopenharmony_civoid CodeAssembler::SetSourcePosition(const char* file, int line) { 5361cb0ef41Sopenharmony_ci raw_assembler()->SetCurrentExternalSourcePosition({file, line}); 5371cb0ef41Sopenharmony_ci} 5381cb0ef41Sopenharmony_ci 5391cb0ef41Sopenharmony_civoid CodeAssembler::PushSourcePosition() { 5401cb0ef41Sopenharmony_ci auto position = raw_assembler()->GetCurrentExternalSourcePosition(); 5411cb0ef41Sopenharmony_ci state_->macro_call_stack_.push_back(position); 5421cb0ef41Sopenharmony_ci} 5431cb0ef41Sopenharmony_ci 5441cb0ef41Sopenharmony_civoid CodeAssembler::PopSourcePosition() { 5451cb0ef41Sopenharmony_ci state_->macro_call_stack_.pop_back(); 5461cb0ef41Sopenharmony_ci} 5471cb0ef41Sopenharmony_ci 5481cb0ef41Sopenharmony_ciconst std::vector<FileAndLine>& CodeAssembler::GetMacroSourcePositionStack() 5491cb0ef41Sopenharmony_ci const { 5501cb0ef41Sopenharmony_ci return state_->macro_call_stack_; 5511cb0ef41Sopenharmony_ci} 5521cb0ef41Sopenharmony_ci 5531cb0ef41Sopenharmony_civoid CodeAssembler::Bind(Label* label) { return label->Bind(); } 5541cb0ef41Sopenharmony_ci 5551cb0ef41Sopenharmony_ci#if DEBUG 5561cb0ef41Sopenharmony_civoid CodeAssembler::Bind(Label* label, AssemblerDebugInfo debug_info) { 5571cb0ef41Sopenharmony_ci return label->Bind(debug_info); 5581cb0ef41Sopenharmony_ci} 5591cb0ef41Sopenharmony_ci#endif // DEBUG 5601cb0ef41Sopenharmony_ci 5611cb0ef41Sopenharmony_ciTNode<RawPtrT> CodeAssembler::LoadFramePointer() { 5621cb0ef41Sopenharmony_ci return UncheckedCast<RawPtrT>(raw_assembler()->LoadFramePointer()); 5631cb0ef41Sopenharmony_ci} 5641cb0ef41Sopenharmony_ci 5651cb0ef41Sopenharmony_ciTNode<RawPtrT> CodeAssembler::LoadParentFramePointer() { 5661cb0ef41Sopenharmony_ci return UncheckedCast<RawPtrT>(raw_assembler()->LoadParentFramePointer()); 5671cb0ef41Sopenharmony_ci} 5681cb0ef41Sopenharmony_ci 5691cb0ef41Sopenharmony_ci#define DEFINE_CODE_ASSEMBLER_BINARY_OP(name, ResType, Arg1Type, Arg2Type) \ 5701cb0ef41Sopenharmony_ci TNode<ResType> CodeAssembler::name(TNode<Arg1Type> a, TNode<Arg2Type> b) { \ 5711cb0ef41Sopenharmony_ci return UncheckedCast<ResType>(raw_assembler()->name(a, b)); \ 5721cb0ef41Sopenharmony_ci } 5731cb0ef41Sopenharmony_ciCODE_ASSEMBLER_BINARY_OP_LIST(DEFINE_CODE_ASSEMBLER_BINARY_OP) 5741cb0ef41Sopenharmony_ci#undef DEFINE_CODE_ASSEMBLER_BINARY_OP 5751cb0ef41Sopenharmony_ci 5761cb0ef41Sopenharmony_ciTNode<WordT> CodeAssembler::WordShl(TNode<WordT> value, int shift) { 5771cb0ef41Sopenharmony_ci return (shift != 0) ? WordShl(value, IntPtrConstant(shift)) : value; 5781cb0ef41Sopenharmony_ci} 5791cb0ef41Sopenharmony_ci 5801cb0ef41Sopenharmony_ciTNode<WordT> CodeAssembler::WordShr(TNode<WordT> value, int shift) { 5811cb0ef41Sopenharmony_ci return (shift != 0) ? WordShr(value, IntPtrConstant(shift)) : value; 5821cb0ef41Sopenharmony_ci} 5831cb0ef41Sopenharmony_ci 5841cb0ef41Sopenharmony_ciTNode<WordT> CodeAssembler::WordSar(TNode<WordT> value, int shift) { 5851cb0ef41Sopenharmony_ci return (shift != 0) ? WordSar(value, IntPtrConstant(shift)) : value; 5861cb0ef41Sopenharmony_ci} 5871cb0ef41Sopenharmony_ci 5881cb0ef41Sopenharmony_ciTNode<Word32T> CodeAssembler::Word32Shr(TNode<Word32T> value, int shift) { 5891cb0ef41Sopenharmony_ci return (shift != 0) ? Word32Shr(value, Int32Constant(shift)) : value; 5901cb0ef41Sopenharmony_ci} 5911cb0ef41Sopenharmony_ci 5921cb0ef41Sopenharmony_ciTNode<Word32T> CodeAssembler::Word32Sar(TNode<Word32T> value, int shift) { 5931cb0ef41Sopenharmony_ci return (shift != 0) ? Word32Sar(value, Int32Constant(shift)) : value; 5941cb0ef41Sopenharmony_ci} 5951cb0ef41Sopenharmony_ci 5961cb0ef41Sopenharmony_ci#define CODE_ASSEMBLER_COMPARE(Name, ArgT, VarT, ToConstant, op) \ 5971cb0ef41Sopenharmony_ci TNode<BoolT> CodeAssembler::Name(TNode<ArgT> left, TNode<ArgT> right) { \ 5981cb0ef41Sopenharmony_ci VarT lhs, rhs; \ 5991cb0ef41Sopenharmony_ci if (ToConstant(left, &lhs) && ToConstant(right, &rhs)) { \ 6001cb0ef41Sopenharmony_ci return BoolConstant(lhs op rhs); \ 6011cb0ef41Sopenharmony_ci } \ 6021cb0ef41Sopenharmony_ci return UncheckedCast<BoolT>(raw_assembler()->Name(left, right)); \ 6031cb0ef41Sopenharmony_ci } 6041cb0ef41Sopenharmony_ci 6051cb0ef41Sopenharmony_ciCODE_ASSEMBLER_COMPARE(IntPtrEqual, WordT, intptr_t, TryToIntPtrConstant, ==) 6061cb0ef41Sopenharmony_ciCODE_ASSEMBLER_COMPARE(WordEqual, WordT, intptr_t, TryToIntPtrConstant, ==) 6071cb0ef41Sopenharmony_ciCODE_ASSEMBLER_COMPARE(WordNotEqual, WordT, intptr_t, TryToIntPtrConstant, !=) 6081cb0ef41Sopenharmony_ciCODE_ASSEMBLER_COMPARE(Word32Equal, Word32T, int32_t, TryToInt32Constant, ==) 6091cb0ef41Sopenharmony_ciCODE_ASSEMBLER_COMPARE(Word32NotEqual, Word32T, int32_t, TryToInt32Constant, !=) 6101cb0ef41Sopenharmony_ciCODE_ASSEMBLER_COMPARE(Word64Equal, Word64T, int64_t, TryToInt64Constant, ==) 6111cb0ef41Sopenharmony_ciCODE_ASSEMBLER_COMPARE(Word64NotEqual, Word64T, int64_t, TryToInt64Constant, !=) 6121cb0ef41Sopenharmony_ci#undef CODE_ASSEMBLER_COMPARE 6131cb0ef41Sopenharmony_ci 6141cb0ef41Sopenharmony_ciTNode<UintPtrT> CodeAssembler::ChangeUint32ToWord(TNode<Word32T> value) { 6151cb0ef41Sopenharmony_ci if (raw_assembler()->machine()->Is64()) { 6161cb0ef41Sopenharmony_ci return UncheckedCast<UintPtrT>( 6171cb0ef41Sopenharmony_ci raw_assembler()->ChangeUint32ToUint64(value)); 6181cb0ef41Sopenharmony_ci } 6191cb0ef41Sopenharmony_ci return ReinterpretCast<UintPtrT>(value); 6201cb0ef41Sopenharmony_ci} 6211cb0ef41Sopenharmony_ci 6221cb0ef41Sopenharmony_ciTNode<IntPtrT> CodeAssembler::ChangeInt32ToIntPtr(TNode<Word32T> value) { 6231cb0ef41Sopenharmony_ci if (raw_assembler()->machine()->Is64()) { 6241cb0ef41Sopenharmony_ci return UncheckedCast<IntPtrT>(raw_assembler()->ChangeInt32ToInt64(value)); 6251cb0ef41Sopenharmony_ci } 6261cb0ef41Sopenharmony_ci return ReinterpretCast<IntPtrT>(value); 6271cb0ef41Sopenharmony_ci} 6281cb0ef41Sopenharmony_ci 6291cb0ef41Sopenharmony_ciTNode<IntPtrT> CodeAssembler::ChangeFloat64ToIntPtr(TNode<Float64T> value) { 6301cb0ef41Sopenharmony_ci if (raw_assembler()->machine()->Is64()) { 6311cb0ef41Sopenharmony_ci return UncheckedCast<IntPtrT>(raw_assembler()->ChangeFloat64ToInt64(value)); 6321cb0ef41Sopenharmony_ci } 6331cb0ef41Sopenharmony_ci return UncheckedCast<IntPtrT>(raw_assembler()->ChangeFloat64ToInt32(value)); 6341cb0ef41Sopenharmony_ci} 6351cb0ef41Sopenharmony_ci 6361cb0ef41Sopenharmony_ciTNode<UintPtrT> CodeAssembler::ChangeFloat64ToUintPtr(TNode<Float64T> value) { 6371cb0ef41Sopenharmony_ci if (raw_assembler()->machine()->Is64()) { 6381cb0ef41Sopenharmony_ci return UncheckedCast<UintPtrT>( 6391cb0ef41Sopenharmony_ci raw_assembler()->ChangeFloat64ToUint64(value)); 6401cb0ef41Sopenharmony_ci } 6411cb0ef41Sopenharmony_ci return UncheckedCast<UintPtrT>(raw_assembler()->ChangeFloat64ToUint32(value)); 6421cb0ef41Sopenharmony_ci} 6431cb0ef41Sopenharmony_ci 6441cb0ef41Sopenharmony_ciTNode<Float64T> CodeAssembler::ChangeUintPtrToFloat64(TNode<UintPtrT> value) { 6451cb0ef41Sopenharmony_ci if (raw_assembler()->machine()->Is64()) { 6461cb0ef41Sopenharmony_ci // TODO(turbofan): Maybe we should introduce a ChangeUint64ToFloat64 6471cb0ef41Sopenharmony_ci // machine operator to TurboFan here? 6481cb0ef41Sopenharmony_ci return UncheckedCast<Float64T>( 6491cb0ef41Sopenharmony_ci raw_assembler()->RoundUint64ToFloat64(value)); 6501cb0ef41Sopenharmony_ci } 6511cb0ef41Sopenharmony_ci return UncheckedCast<Float64T>(raw_assembler()->ChangeUint32ToFloat64(value)); 6521cb0ef41Sopenharmony_ci} 6531cb0ef41Sopenharmony_ci 6541cb0ef41Sopenharmony_ciTNode<Float64T> CodeAssembler::RoundIntPtrToFloat64(Node* value) { 6551cb0ef41Sopenharmony_ci if (raw_assembler()->machine()->Is64()) { 6561cb0ef41Sopenharmony_ci return UncheckedCast<Float64T>(raw_assembler()->RoundInt64ToFloat64(value)); 6571cb0ef41Sopenharmony_ci } 6581cb0ef41Sopenharmony_ci return UncheckedCast<Float64T>(raw_assembler()->ChangeInt32ToFloat64(value)); 6591cb0ef41Sopenharmony_ci} 6601cb0ef41Sopenharmony_ci 6611cb0ef41Sopenharmony_ciTNode<Int32T> CodeAssembler::TruncateFloat32ToInt32(TNode<Float32T> value) { 6621cb0ef41Sopenharmony_ci return UncheckedCast<Int32T>(raw_assembler()->TruncateFloat32ToInt32( 6631cb0ef41Sopenharmony_ci value, TruncateKind::kSetOverflowToMin)); 6641cb0ef41Sopenharmony_ci} 6651cb0ef41Sopenharmony_ci#define DEFINE_CODE_ASSEMBLER_UNARY_OP(name, ResType, ArgType) \ 6661cb0ef41Sopenharmony_ci TNode<ResType> CodeAssembler::name(TNode<ArgType> a) { \ 6671cb0ef41Sopenharmony_ci return UncheckedCast<ResType>(raw_assembler()->name(a)); \ 6681cb0ef41Sopenharmony_ci } 6691cb0ef41Sopenharmony_ciCODE_ASSEMBLER_UNARY_OP_LIST(DEFINE_CODE_ASSEMBLER_UNARY_OP) 6701cb0ef41Sopenharmony_ci#undef DEFINE_CODE_ASSEMBLER_UNARY_OP 6711cb0ef41Sopenharmony_ci 6721cb0ef41Sopenharmony_ciNode* CodeAssembler::Load(MachineType type, Node* base) { 6731cb0ef41Sopenharmony_ci return raw_assembler()->Load(type, base); 6741cb0ef41Sopenharmony_ci} 6751cb0ef41Sopenharmony_ci 6761cb0ef41Sopenharmony_ciNode* CodeAssembler::Load(MachineType type, Node* base, Node* offset) { 6771cb0ef41Sopenharmony_ci return raw_assembler()->Load(type, base, offset); 6781cb0ef41Sopenharmony_ci} 6791cb0ef41Sopenharmony_ci 6801cb0ef41Sopenharmony_ciTNode<Object> CodeAssembler::LoadFullTagged(Node* base) { 6811cb0ef41Sopenharmony_ci return BitcastWordToTagged(Load<RawPtrT>(base)); 6821cb0ef41Sopenharmony_ci} 6831cb0ef41Sopenharmony_ci 6841cb0ef41Sopenharmony_ciTNode<Object> CodeAssembler::LoadFullTagged(Node* base, TNode<IntPtrT> offset) { 6851cb0ef41Sopenharmony_ci // Please use LoadFromObject(MachineType::MapInHeader(), object, 6861cb0ef41Sopenharmony_ci // IntPtrConstant(-kHeapObjectTag)) instead. 6871cb0ef41Sopenharmony_ci DCHECK(!raw_assembler()->IsMapOffsetConstantMinusTag(offset)); 6881cb0ef41Sopenharmony_ci return BitcastWordToTagged(Load<RawPtrT>(base, offset)); 6891cb0ef41Sopenharmony_ci} 6901cb0ef41Sopenharmony_ci 6911cb0ef41Sopenharmony_ciNode* CodeAssembler::AtomicLoad(MachineType type, AtomicMemoryOrder order, 6921cb0ef41Sopenharmony_ci TNode<RawPtrT> base, TNode<WordT> offset) { 6931cb0ef41Sopenharmony_ci DCHECK(!raw_assembler()->IsMapOffsetConstantMinusTag(offset)); 6941cb0ef41Sopenharmony_ci return raw_assembler()->AtomicLoad(AtomicLoadParameters(type, order), base, 6951cb0ef41Sopenharmony_ci offset); 6961cb0ef41Sopenharmony_ci} 6971cb0ef41Sopenharmony_ci 6981cb0ef41Sopenharmony_citemplate <class Type> 6991cb0ef41Sopenharmony_ciTNode<Type> CodeAssembler::AtomicLoad64(AtomicMemoryOrder order, 7001cb0ef41Sopenharmony_ci TNode<RawPtrT> base, 7011cb0ef41Sopenharmony_ci TNode<WordT> offset) { 7021cb0ef41Sopenharmony_ci return UncheckedCast<Type>(raw_assembler()->AtomicLoad64( 7031cb0ef41Sopenharmony_ci AtomicLoadParameters(MachineType::Uint64(), order), base, offset)); 7041cb0ef41Sopenharmony_ci} 7051cb0ef41Sopenharmony_ci 7061cb0ef41Sopenharmony_citemplate TNode<AtomicInt64> CodeAssembler::AtomicLoad64<AtomicInt64>( 7071cb0ef41Sopenharmony_ci AtomicMemoryOrder order, TNode<RawPtrT> base, TNode<WordT> offset); 7081cb0ef41Sopenharmony_citemplate TNode<AtomicUint64> CodeAssembler::AtomicLoad64<AtomicUint64>( 7091cb0ef41Sopenharmony_ci AtomicMemoryOrder order, TNode<RawPtrT> base, TNode<WordT> offset); 7101cb0ef41Sopenharmony_ci 7111cb0ef41Sopenharmony_ciNode* CodeAssembler::LoadFromObject(MachineType type, TNode<Object> object, 7121cb0ef41Sopenharmony_ci TNode<IntPtrT> offset) { 7131cb0ef41Sopenharmony_ci return raw_assembler()->LoadFromObject(type, object, offset); 7141cb0ef41Sopenharmony_ci} 7151cb0ef41Sopenharmony_ci 7161cb0ef41Sopenharmony_ci#ifdef V8_MAP_PACKING 7171cb0ef41Sopenharmony_ciNode* CodeAssembler::PackMapWord(Node* value) { 7181cb0ef41Sopenharmony_ci TNode<IntPtrT> map_word = 7191cb0ef41Sopenharmony_ci BitcastTaggedToWordForTagAndSmiBits(UncheckedCast<AnyTaggedT>(value)); 7201cb0ef41Sopenharmony_ci TNode<WordT> packed = WordXor(UncheckedCast<WordT>(map_word), 7211cb0ef41Sopenharmony_ci IntPtrConstant(Internals::kMapWordXorMask)); 7221cb0ef41Sopenharmony_ci return BitcastWordToTaggedSigned(packed); 7231cb0ef41Sopenharmony_ci} 7241cb0ef41Sopenharmony_ci#endif 7251cb0ef41Sopenharmony_ci 7261cb0ef41Sopenharmony_ciTNode<AnyTaggedT> CodeAssembler::LoadRootMapWord(RootIndex root_index) { 7271cb0ef41Sopenharmony_ci#ifdef V8_MAP_PACKING 7281cb0ef41Sopenharmony_ci Handle<Object> root = isolate()->root_handle(root_index); 7291cb0ef41Sopenharmony_ci Node* map = HeapConstant(Handle<Map>::cast(root)); 7301cb0ef41Sopenharmony_ci map = PackMapWord(map); 7311cb0ef41Sopenharmony_ci return ReinterpretCast<AnyTaggedT>(map); 7321cb0ef41Sopenharmony_ci#else 7331cb0ef41Sopenharmony_ci return LoadRoot(root_index); 7341cb0ef41Sopenharmony_ci#endif 7351cb0ef41Sopenharmony_ci} 7361cb0ef41Sopenharmony_ci 7371cb0ef41Sopenharmony_ciTNode<Object> CodeAssembler::LoadRoot(RootIndex root_index) { 7381cb0ef41Sopenharmony_ci if (RootsTable::IsImmortalImmovable(root_index)) { 7391cb0ef41Sopenharmony_ci Handle<Object> root = isolate()->root_handle(root_index); 7401cb0ef41Sopenharmony_ci if (root->IsSmi()) { 7411cb0ef41Sopenharmony_ci return SmiConstant(Smi::cast(*root)); 7421cb0ef41Sopenharmony_ci } else { 7431cb0ef41Sopenharmony_ci return HeapConstant(Handle<HeapObject>::cast(root)); 7441cb0ef41Sopenharmony_ci } 7451cb0ef41Sopenharmony_ci } 7461cb0ef41Sopenharmony_ci 7471cb0ef41Sopenharmony_ci // TODO(jgruber): In theory we could generate better code for this by 7481cb0ef41Sopenharmony_ci // letting the macro assembler decide how to load from the roots list. In most 7491cb0ef41Sopenharmony_ci // cases, it would boil down to loading from a fixed kRootRegister offset. 7501cb0ef41Sopenharmony_ci TNode<ExternalReference> isolate_root = 7511cb0ef41Sopenharmony_ci ExternalConstant(ExternalReference::isolate_root(isolate())); 7521cb0ef41Sopenharmony_ci int offset = IsolateData::root_slot_offset(root_index); 7531cb0ef41Sopenharmony_ci return UncheckedCast<Object>( 7541cb0ef41Sopenharmony_ci LoadFullTagged(isolate_root, IntPtrConstant(offset))); 7551cb0ef41Sopenharmony_ci} 7561cb0ef41Sopenharmony_ci 7571cb0ef41Sopenharmony_ciNode* CodeAssembler::UnalignedLoad(MachineType type, TNode<RawPtrT> base, 7581cb0ef41Sopenharmony_ci TNode<WordT> offset) { 7591cb0ef41Sopenharmony_ci return raw_assembler()->UnalignedLoad(type, static_cast<Node*>(base), offset); 7601cb0ef41Sopenharmony_ci} 7611cb0ef41Sopenharmony_ci 7621cb0ef41Sopenharmony_civoid CodeAssembler::Store(Node* base, Node* value) { 7631cb0ef41Sopenharmony_ci raw_assembler()->Store(MachineRepresentation::kTagged, base, value, 7641cb0ef41Sopenharmony_ci kFullWriteBarrier); 7651cb0ef41Sopenharmony_ci} 7661cb0ef41Sopenharmony_ci 7671cb0ef41Sopenharmony_civoid CodeAssembler::StoreToObject(MachineRepresentation rep, 7681cb0ef41Sopenharmony_ci TNode<Object> object, TNode<IntPtrT> offset, 7691cb0ef41Sopenharmony_ci Node* value, 7701cb0ef41Sopenharmony_ci StoreToObjectWriteBarrier write_barrier) { 7711cb0ef41Sopenharmony_ci WriteBarrierKind write_barrier_kind; 7721cb0ef41Sopenharmony_ci switch (write_barrier) { 7731cb0ef41Sopenharmony_ci case StoreToObjectWriteBarrier::kFull: 7741cb0ef41Sopenharmony_ci write_barrier_kind = WriteBarrierKind::kFullWriteBarrier; 7751cb0ef41Sopenharmony_ci break; 7761cb0ef41Sopenharmony_ci case StoreToObjectWriteBarrier::kMap: 7771cb0ef41Sopenharmony_ci write_barrier_kind = WriteBarrierKind::kMapWriteBarrier; 7781cb0ef41Sopenharmony_ci break; 7791cb0ef41Sopenharmony_ci case StoreToObjectWriteBarrier::kNone: 7801cb0ef41Sopenharmony_ci if (CanBeTaggedPointer(rep)) { 7811cb0ef41Sopenharmony_ci write_barrier_kind = WriteBarrierKind::kAssertNoWriteBarrier; 7821cb0ef41Sopenharmony_ci } else { 7831cb0ef41Sopenharmony_ci write_barrier_kind = WriteBarrierKind::kNoWriteBarrier; 7841cb0ef41Sopenharmony_ci } 7851cb0ef41Sopenharmony_ci break; 7861cb0ef41Sopenharmony_ci } 7871cb0ef41Sopenharmony_ci raw_assembler()->StoreToObject(rep, object, offset, value, 7881cb0ef41Sopenharmony_ci write_barrier_kind); 7891cb0ef41Sopenharmony_ci} 7901cb0ef41Sopenharmony_ci 7911cb0ef41Sopenharmony_civoid CodeAssembler::OptimizedStoreField(MachineRepresentation rep, 7921cb0ef41Sopenharmony_ci TNode<HeapObject> object, int offset, 7931cb0ef41Sopenharmony_ci Node* value) { 7941cb0ef41Sopenharmony_ci raw_assembler()->OptimizedStoreField(rep, object, offset, value, 7951cb0ef41Sopenharmony_ci WriteBarrierKind::kFullWriteBarrier); 7961cb0ef41Sopenharmony_ci} 7971cb0ef41Sopenharmony_ci 7981cb0ef41Sopenharmony_civoid CodeAssembler::OptimizedStoreFieldAssertNoWriteBarrier( 7991cb0ef41Sopenharmony_ci MachineRepresentation rep, TNode<HeapObject> object, int offset, 8001cb0ef41Sopenharmony_ci Node* value) { 8011cb0ef41Sopenharmony_ci raw_assembler()->OptimizedStoreField(rep, object, offset, value, 8021cb0ef41Sopenharmony_ci WriteBarrierKind::kAssertNoWriteBarrier); 8031cb0ef41Sopenharmony_ci} 8041cb0ef41Sopenharmony_ci 8051cb0ef41Sopenharmony_civoid CodeAssembler::OptimizedStoreFieldUnsafeNoWriteBarrier( 8061cb0ef41Sopenharmony_ci MachineRepresentation rep, TNode<HeapObject> object, int offset, 8071cb0ef41Sopenharmony_ci Node* value) { 8081cb0ef41Sopenharmony_ci raw_assembler()->OptimizedStoreField(rep, object, offset, value, 8091cb0ef41Sopenharmony_ci WriteBarrierKind::kNoWriteBarrier); 8101cb0ef41Sopenharmony_ci} 8111cb0ef41Sopenharmony_ci 8121cb0ef41Sopenharmony_civoid CodeAssembler::OptimizedStoreMap(TNode<HeapObject> object, 8131cb0ef41Sopenharmony_ci TNode<Map> map) { 8141cb0ef41Sopenharmony_ci raw_assembler()->OptimizedStoreMap(object, map); 8151cb0ef41Sopenharmony_ci} 8161cb0ef41Sopenharmony_ci 8171cb0ef41Sopenharmony_civoid CodeAssembler::Store(Node* base, Node* offset, Node* value) { 8181cb0ef41Sopenharmony_ci // Please use OptimizedStoreMap(base, value) instead. 8191cb0ef41Sopenharmony_ci DCHECK(!raw_assembler()->IsMapOffsetConstantMinusTag(offset)); 8201cb0ef41Sopenharmony_ci raw_assembler()->Store(MachineRepresentation::kTagged, base, offset, value, 8211cb0ef41Sopenharmony_ci kFullWriteBarrier); 8221cb0ef41Sopenharmony_ci} 8231cb0ef41Sopenharmony_ci 8241cb0ef41Sopenharmony_civoid CodeAssembler::StoreEphemeronKey(Node* base, Node* offset, Node* value) { 8251cb0ef41Sopenharmony_ci DCHECK(!raw_assembler()->IsMapOffsetConstantMinusTag(offset)); 8261cb0ef41Sopenharmony_ci raw_assembler()->Store(MachineRepresentation::kTagged, base, offset, value, 8271cb0ef41Sopenharmony_ci kEphemeronKeyWriteBarrier); 8281cb0ef41Sopenharmony_ci} 8291cb0ef41Sopenharmony_ci 8301cb0ef41Sopenharmony_civoid CodeAssembler::StoreNoWriteBarrier(MachineRepresentation rep, Node* base, 8311cb0ef41Sopenharmony_ci Node* value) { 8321cb0ef41Sopenharmony_ci raw_assembler()->Store( 8331cb0ef41Sopenharmony_ci rep, base, value, 8341cb0ef41Sopenharmony_ci CanBeTaggedPointer(rep) ? kAssertNoWriteBarrier : kNoWriteBarrier); 8351cb0ef41Sopenharmony_ci} 8361cb0ef41Sopenharmony_ci 8371cb0ef41Sopenharmony_civoid CodeAssembler::StoreNoWriteBarrier(MachineRepresentation rep, Node* base, 8381cb0ef41Sopenharmony_ci Node* offset, Node* value) { 8391cb0ef41Sopenharmony_ci // Please use OptimizedStoreMap(base, value) instead. 8401cb0ef41Sopenharmony_ci DCHECK(!raw_assembler()->IsMapOffsetConstantMinusTag(offset)); 8411cb0ef41Sopenharmony_ci raw_assembler()->Store( 8421cb0ef41Sopenharmony_ci rep, base, offset, value, 8431cb0ef41Sopenharmony_ci CanBeTaggedPointer(rep) ? kAssertNoWriteBarrier : kNoWriteBarrier); 8441cb0ef41Sopenharmony_ci} 8451cb0ef41Sopenharmony_ci 8461cb0ef41Sopenharmony_civoid CodeAssembler::UnsafeStoreNoWriteBarrier(MachineRepresentation rep, 8471cb0ef41Sopenharmony_ci Node* base, Node* value) { 8481cb0ef41Sopenharmony_ci raw_assembler()->Store(rep, base, value, kNoWriteBarrier); 8491cb0ef41Sopenharmony_ci} 8501cb0ef41Sopenharmony_ci 8511cb0ef41Sopenharmony_civoid CodeAssembler::UnsafeStoreNoWriteBarrier(MachineRepresentation rep, 8521cb0ef41Sopenharmony_ci Node* base, Node* offset, 8531cb0ef41Sopenharmony_ci Node* value) { 8541cb0ef41Sopenharmony_ci // Please use OptimizedStoreMap(base, value) instead. 8551cb0ef41Sopenharmony_ci DCHECK(!raw_assembler()->IsMapOffsetConstantMinusTag(offset)); 8561cb0ef41Sopenharmony_ci raw_assembler()->Store(rep, base, offset, value, kNoWriteBarrier); 8571cb0ef41Sopenharmony_ci} 8581cb0ef41Sopenharmony_ci 8591cb0ef41Sopenharmony_civoid CodeAssembler::StoreFullTaggedNoWriteBarrier(TNode<RawPtrT> base, 8601cb0ef41Sopenharmony_ci TNode<Object> tagged_value) { 8611cb0ef41Sopenharmony_ci StoreNoWriteBarrier(MachineType::PointerRepresentation(), base, 8621cb0ef41Sopenharmony_ci BitcastTaggedToWord(tagged_value)); 8631cb0ef41Sopenharmony_ci} 8641cb0ef41Sopenharmony_ci 8651cb0ef41Sopenharmony_civoid CodeAssembler::StoreFullTaggedNoWriteBarrier(TNode<RawPtrT> base, 8661cb0ef41Sopenharmony_ci TNode<IntPtrT> offset, 8671cb0ef41Sopenharmony_ci TNode<Object> tagged_value) { 8681cb0ef41Sopenharmony_ci // Please use OptimizedStoreMap(base, tagged_value) instead. 8691cb0ef41Sopenharmony_ci DCHECK(!raw_assembler()->IsMapOffsetConstantMinusTag(offset)); 8701cb0ef41Sopenharmony_ci StoreNoWriteBarrier(MachineType::PointerRepresentation(), base, offset, 8711cb0ef41Sopenharmony_ci BitcastTaggedToWord(tagged_value)); 8721cb0ef41Sopenharmony_ci} 8731cb0ef41Sopenharmony_ci 8741cb0ef41Sopenharmony_civoid CodeAssembler::AtomicStore(MachineRepresentation rep, 8751cb0ef41Sopenharmony_ci AtomicMemoryOrder order, TNode<RawPtrT> base, 8761cb0ef41Sopenharmony_ci TNode<WordT> offset, TNode<Word32T> value) { 8771cb0ef41Sopenharmony_ci DCHECK(!raw_assembler()->IsMapOffsetConstantMinusTag(offset)); 8781cb0ef41Sopenharmony_ci raw_assembler()->AtomicStore( 8791cb0ef41Sopenharmony_ci AtomicStoreParameters(rep, WriteBarrierKind::kNoWriteBarrier, order), 8801cb0ef41Sopenharmony_ci base, offset, value); 8811cb0ef41Sopenharmony_ci} 8821cb0ef41Sopenharmony_ci 8831cb0ef41Sopenharmony_civoid CodeAssembler::AtomicStore64(AtomicMemoryOrder order, TNode<RawPtrT> base, 8841cb0ef41Sopenharmony_ci TNode<WordT> offset, TNode<UintPtrT> value, 8851cb0ef41Sopenharmony_ci TNode<UintPtrT> value_high) { 8861cb0ef41Sopenharmony_ci raw_assembler()->AtomicStore64( 8871cb0ef41Sopenharmony_ci AtomicStoreParameters(MachineRepresentation::kWord64, 8881cb0ef41Sopenharmony_ci WriteBarrierKind::kNoWriteBarrier, order), 8891cb0ef41Sopenharmony_ci base, offset, value, value_high); 8901cb0ef41Sopenharmony_ci} 8911cb0ef41Sopenharmony_ci 8921cb0ef41Sopenharmony_ci#define ATOMIC_FUNCTION(name) \ 8931cb0ef41Sopenharmony_ci TNode<Word32T> CodeAssembler::Atomic##name( \ 8941cb0ef41Sopenharmony_ci MachineType type, TNode<RawPtrT> base, TNode<UintPtrT> offset, \ 8951cb0ef41Sopenharmony_ci TNode<Word32T> value) { \ 8961cb0ef41Sopenharmony_ci return UncheckedCast<Word32T>( \ 8971cb0ef41Sopenharmony_ci raw_assembler()->Atomic##name(type, base, offset, value)); \ 8981cb0ef41Sopenharmony_ci } \ 8991cb0ef41Sopenharmony_ci template <class Type> \ 9001cb0ef41Sopenharmony_ci TNode<Type> CodeAssembler::Atomic##name##64( \ 9011cb0ef41Sopenharmony_ci TNode<RawPtrT> base, TNode<UintPtrT> offset, TNode<UintPtrT> value, \ 9021cb0ef41Sopenharmony_ci TNode<UintPtrT> value_high) { \ 9031cb0ef41Sopenharmony_ci return UncheckedCast<Type>( \ 9041cb0ef41Sopenharmony_ci raw_assembler()->Atomic##name##64(base, offset, value, value_high)); \ 9051cb0ef41Sopenharmony_ci } \ 9061cb0ef41Sopenharmony_ci template TNode<AtomicInt64> CodeAssembler::Atomic##name##64 < AtomicInt64 > \ 9071cb0ef41Sopenharmony_ci (TNode<RawPtrT> base, TNode<UintPtrT> offset, TNode<UintPtrT> value, \ 9081cb0ef41Sopenharmony_ci TNode<UintPtrT> value_high); \ 9091cb0ef41Sopenharmony_ci template TNode<AtomicUint64> CodeAssembler::Atomic##name##64 < \ 9101cb0ef41Sopenharmony_ci AtomicUint64 > (TNode<RawPtrT> base, TNode<UintPtrT> offset, \ 9111cb0ef41Sopenharmony_ci TNode<UintPtrT> value, TNode<UintPtrT> value_high); 9121cb0ef41Sopenharmony_ciATOMIC_FUNCTION(Add) 9131cb0ef41Sopenharmony_ciATOMIC_FUNCTION(Sub) 9141cb0ef41Sopenharmony_ciATOMIC_FUNCTION(And) 9151cb0ef41Sopenharmony_ciATOMIC_FUNCTION(Or) 9161cb0ef41Sopenharmony_ciATOMIC_FUNCTION(Xor) 9171cb0ef41Sopenharmony_ciATOMIC_FUNCTION(Exchange) 9181cb0ef41Sopenharmony_ci#undef ATOMIC_FUNCTION 9191cb0ef41Sopenharmony_ci 9201cb0ef41Sopenharmony_ciTNode<Word32T> CodeAssembler::AtomicCompareExchange(MachineType type, 9211cb0ef41Sopenharmony_ci TNode<RawPtrT> base, 9221cb0ef41Sopenharmony_ci TNode<WordT> offset, 9231cb0ef41Sopenharmony_ci TNode<Word32T> old_value, 9241cb0ef41Sopenharmony_ci TNode<Word32T> new_value) { 9251cb0ef41Sopenharmony_ci return UncheckedCast<Word32T>(raw_assembler()->AtomicCompareExchange( 9261cb0ef41Sopenharmony_ci type, base, offset, old_value, new_value)); 9271cb0ef41Sopenharmony_ci} 9281cb0ef41Sopenharmony_ci 9291cb0ef41Sopenharmony_citemplate <class Type> 9301cb0ef41Sopenharmony_ciTNode<Type> CodeAssembler::AtomicCompareExchange64( 9311cb0ef41Sopenharmony_ci TNode<RawPtrT> base, TNode<WordT> offset, TNode<UintPtrT> old_value, 9321cb0ef41Sopenharmony_ci TNode<UintPtrT> new_value, TNode<UintPtrT> old_value_high, 9331cb0ef41Sopenharmony_ci TNode<UintPtrT> new_value_high) { 9341cb0ef41Sopenharmony_ci // This uses Uint64() intentionally: AtomicCompareExchange is not implemented 9351cb0ef41Sopenharmony_ci // for Int64(), which is fine because the machine instruction only cares 9361cb0ef41Sopenharmony_ci // about words. 9371cb0ef41Sopenharmony_ci return UncheckedCast<Type>(raw_assembler()->AtomicCompareExchange64( 9381cb0ef41Sopenharmony_ci base, offset, old_value, old_value_high, new_value, new_value_high)); 9391cb0ef41Sopenharmony_ci} 9401cb0ef41Sopenharmony_ci 9411cb0ef41Sopenharmony_citemplate TNode<AtomicInt64> CodeAssembler::AtomicCompareExchange64<AtomicInt64>( 9421cb0ef41Sopenharmony_ci TNode<RawPtrT> base, TNode<WordT> offset, TNode<UintPtrT> old_value, 9431cb0ef41Sopenharmony_ci TNode<UintPtrT> new_value, TNode<UintPtrT> old_value_high, 9441cb0ef41Sopenharmony_ci TNode<UintPtrT> new_value_high); 9451cb0ef41Sopenharmony_citemplate TNode<AtomicUint64> 9461cb0ef41Sopenharmony_ciCodeAssembler::AtomicCompareExchange64<AtomicUint64>( 9471cb0ef41Sopenharmony_ci TNode<RawPtrT> base, TNode<WordT> offset, TNode<UintPtrT> old_value, 9481cb0ef41Sopenharmony_ci TNode<UintPtrT> new_value, TNode<UintPtrT> old_value_high, 9491cb0ef41Sopenharmony_ci TNode<UintPtrT> new_value_high); 9501cb0ef41Sopenharmony_ci 9511cb0ef41Sopenharmony_civoid CodeAssembler::StoreRoot(RootIndex root_index, TNode<Object> value) { 9521cb0ef41Sopenharmony_ci DCHECK(!RootsTable::IsImmortalImmovable(root_index)); 9531cb0ef41Sopenharmony_ci TNode<ExternalReference> isolate_root = 9541cb0ef41Sopenharmony_ci ExternalConstant(ExternalReference::isolate_root(isolate())); 9551cb0ef41Sopenharmony_ci int offset = IsolateData::root_slot_offset(root_index); 9561cb0ef41Sopenharmony_ci StoreFullTaggedNoWriteBarrier(isolate_root, IntPtrConstant(offset), value); 9571cb0ef41Sopenharmony_ci} 9581cb0ef41Sopenharmony_ci 9591cb0ef41Sopenharmony_ciNode* CodeAssembler::Projection(int index, Node* value) { 9601cb0ef41Sopenharmony_ci DCHECK_LT(index, value->op()->ValueOutputCount()); 9611cb0ef41Sopenharmony_ci return raw_assembler()->Projection(index, value); 9621cb0ef41Sopenharmony_ci} 9631cb0ef41Sopenharmony_ci 9641cb0ef41Sopenharmony_ciTNode<HeapObject> CodeAssembler::OptimizedAllocate( 9651cb0ef41Sopenharmony_ci TNode<IntPtrT> size, AllocationType allocation, 9661cb0ef41Sopenharmony_ci AllowLargeObjects allow_large_objects) { 9671cb0ef41Sopenharmony_ci return UncheckedCast<HeapObject>(raw_assembler()->OptimizedAllocate( 9681cb0ef41Sopenharmony_ci size, allocation, allow_large_objects)); 9691cb0ef41Sopenharmony_ci} 9701cb0ef41Sopenharmony_ci 9711cb0ef41Sopenharmony_civoid CodeAssembler::HandleException(Node* node) { 9721cb0ef41Sopenharmony_ci if (state_->exception_handler_labels_.size() == 0) return; 9731cb0ef41Sopenharmony_ci CodeAssemblerExceptionHandlerLabel* label = 9741cb0ef41Sopenharmony_ci state_->exception_handler_labels_.back(); 9751cb0ef41Sopenharmony_ci 9761cb0ef41Sopenharmony_ci if (node->op()->HasProperty(Operator::kNoThrow)) { 9771cb0ef41Sopenharmony_ci return; 9781cb0ef41Sopenharmony_ci } 9791cb0ef41Sopenharmony_ci 9801cb0ef41Sopenharmony_ci Label success(this), exception(this, Label::kDeferred); 9811cb0ef41Sopenharmony_ci success.MergeVariables(); 9821cb0ef41Sopenharmony_ci exception.MergeVariables(); 9831cb0ef41Sopenharmony_ci 9841cb0ef41Sopenharmony_ci raw_assembler()->Continuations(node, success.label_, exception.label_); 9851cb0ef41Sopenharmony_ci 9861cb0ef41Sopenharmony_ci Bind(&exception); 9871cb0ef41Sopenharmony_ci const Operator* op = raw_assembler()->common()->IfException(); 9881cb0ef41Sopenharmony_ci Node* exception_value = raw_assembler()->AddNode(op, node, node); 9891cb0ef41Sopenharmony_ci label->AddInputs({UncheckedCast<Object>(exception_value)}); 9901cb0ef41Sopenharmony_ci Goto(label->plain_label()); 9911cb0ef41Sopenharmony_ci 9921cb0ef41Sopenharmony_ci Bind(&success); 9931cb0ef41Sopenharmony_ci raw_assembler()->AddNode(raw_assembler()->common()->IfSuccess(), node); 9941cb0ef41Sopenharmony_ci} 9951cb0ef41Sopenharmony_ci 9961cb0ef41Sopenharmony_cinamespace { 9971cb0ef41Sopenharmony_citemplate <size_t kMaxSize> 9981cb0ef41Sopenharmony_ciclass NodeArray { 9991cb0ef41Sopenharmony_ci public: 10001cb0ef41Sopenharmony_ci void Add(Node* node) { 10011cb0ef41Sopenharmony_ci DCHECK_GT(kMaxSize, size()); 10021cb0ef41Sopenharmony_ci *ptr_++ = node; 10031cb0ef41Sopenharmony_ci } 10041cb0ef41Sopenharmony_ci 10051cb0ef41Sopenharmony_ci Node* const* data() const { return arr_; } 10061cb0ef41Sopenharmony_ci int size() const { return static_cast<int>(ptr_ - arr_); } 10071cb0ef41Sopenharmony_ci 10081cb0ef41Sopenharmony_ci private: 10091cb0ef41Sopenharmony_ci Node* arr_[kMaxSize]; 10101cb0ef41Sopenharmony_ci Node** ptr_ = arr_; 10111cb0ef41Sopenharmony_ci}; 10121cb0ef41Sopenharmony_ci} // namespace 10131cb0ef41Sopenharmony_ci 10141cb0ef41Sopenharmony_ciNode* CodeAssembler::CallRuntimeImpl( 10151cb0ef41Sopenharmony_ci Runtime::FunctionId function, TNode<Object> context, 10161cb0ef41Sopenharmony_ci std::initializer_list<TNode<Object>> args) { 10171cb0ef41Sopenharmony_ci int result_size = Runtime::FunctionForId(function)->result_size; 10181cb0ef41Sopenharmony_ci TNode<CodeT> centry = 10191cb0ef41Sopenharmony_ci HeapConstant(CodeFactory::RuntimeCEntry(isolate(), result_size)); 10201cb0ef41Sopenharmony_ci constexpr size_t kMaxNumArgs = 6; 10211cb0ef41Sopenharmony_ci DCHECK_GE(kMaxNumArgs, args.size()); 10221cb0ef41Sopenharmony_ci int argc = static_cast<int>(args.size()); 10231cb0ef41Sopenharmony_ci auto call_descriptor = Linkage::GetRuntimeCallDescriptor( 10241cb0ef41Sopenharmony_ci zone(), function, argc, Operator::kNoProperties, 10251cb0ef41Sopenharmony_ci Runtime::MayAllocate(function) ? CallDescriptor::kNoFlags 10261cb0ef41Sopenharmony_ci : CallDescriptor::kNoAllocate); 10271cb0ef41Sopenharmony_ci 10281cb0ef41Sopenharmony_ci TNode<ExternalReference> ref = 10291cb0ef41Sopenharmony_ci ExternalConstant(ExternalReference::Create(function)); 10301cb0ef41Sopenharmony_ci TNode<Int32T> arity = Int32Constant(argc); 10311cb0ef41Sopenharmony_ci 10321cb0ef41Sopenharmony_ci NodeArray<kMaxNumArgs + 4> inputs; 10331cb0ef41Sopenharmony_ci inputs.Add(centry); 10341cb0ef41Sopenharmony_ci for (auto arg : args) inputs.Add(arg); 10351cb0ef41Sopenharmony_ci inputs.Add(ref); 10361cb0ef41Sopenharmony_ci inputs.Add(arity); 10371cb0ef41Sopenharmony_ci inputs.Add(context); 10381cb0ef41Sopenharmony_ci 10391cb0ef41Sopenharmony_ci CallPrologue(); 10401cb0ef41Sopenharmony_ci Node* return_value = 10411cb0ef41Sopenharmony_ci raw_assembler()->CallN(call_descriptor, inputs.size(), inputs.data()); 10421cb0ef41Sopenharmony_ci HandleException(return_value); 10431cb0ef41Sopenharmony_ci CallEpilogue(); 10441cb0ef41Sopenharmony_ci return return_value; 10451cb0ef41Sopenharmony_ci} 10461cb0ef41Sopenharmony_ci 10471cb0ef41Sopenharmony_civoid CodeAssembler::TailCallRuntimeImpl( 10481cb0ef41Sopenharmony_ci Runtime::FunctionId function, TNode<Int32T> arity, TNode<Object> context, 10491cb0ef41Sopenharmony_ci std::initializer_list<TNode<Object>> args) { 10501cb0ef41Sopenharmony_ci int result_size = Runtime::FunctionForId(function)->result_size; 10511cb0ef41Sopenharmony_ci TNode<CodeT> centry = 10521cb0ef41Sopenharmony_ci HeapConstant(CodeFactory::RuntimeCEntry(isolate(), result_size)); 10531cb0ef41Sopenharmony_ci constexpr size_t kMaxNumArgs = 6; 10541cb0ef41Sopenharmony_ci DCHECK_GE(kMaxNumArgs, args.size()); 10551cb0ef41Sopenharmony_ci int argc = static_cast<int>(args.size()); 10561cb0ef41Sopenharmony_ci auto call_descriptor = Linkage::GetRuntimeCallDescriptor( 10571cb0ef41Sopenharmony_ci zone(), function, argc, Operator::kNoProperties, 10581cb0ef41Sopenharmony_ci CallDescriptor::kNoFlags); 10591cb0ef41Sopenharmony_ci 10601cb0ef41Sopenharmony_ci TNode<ExternalReference> ref = 10611cb0ef41Sopenharmony_ci ExternalConstant(ExternalReference::Create(function)); 10621cb0ef41Sopenharmony_ci 10631cb0ef41Sopenharmony_ci NodeArray<kMaxNumArgs + 4> inputs; 10641cb0ef41Sopenharmony_ci inputs.Add(centry); 10651cb0ef41Sopenharmony_ci for (auto arg : args) inputs.Add(arg); 10661cb0ef41Sopenharmony_ci inputs.Add(ref); 10671cb0ef41Sopenharmony_ci inputs.Add(arity); 10681cb0ef41Sopenharmony_ci inputs.Add(context); 10691cb0ef41Sopenharmony_ci 10701cb0ef41Sopenharmony_ci raw_assembler()->TailCallN(call_descriptor, inputs.size(), inputs.data()); 10711cb0ef41Sopenharmony_ci} 10721cb0ef41Sopenharmony_ci 10731cb0ef41Sopenharmony_ciNode* CodeAssembler::CallStubN(StubCallMode call_mode, 10741cb0ef41Sopenharmony_ci const CallInterfaceDescriptor& descriptor, 10751cb0ef41Sopenharmony_ci int input_count, Node* const* inputs) { 10761cb0ef41Sopenharmony_ci DCHECK(call_mode == StubCallMode::kCallCodeObject || 10771cb0ef41Sopenharmony_ci call_mode == StubCallMode::kCallBuiltinPointer); 10781cb0ef41Sopenharmony_ci 10791cb0ef41Sopenharmony_ci // implicit nodes are target and optionally context. 10801cb0ef41Sopenharmony_ci int implicit_nodes = descriptor.HasContextParameter() ? 2 : 1; 10811cb0ef41Sopenharmony_ci DCHECK_LE(implicit_nodes, input_count); 10821cb0ef41Sopenharmony_ci int argc = input_count - implicit_nodes; 10831cb0ef41Sopenharmony_ci#ifdef DEBUG 10841cb0ef41Sopenharmony_ci if (descriptor.AllowVarArgs()) { 10851cb0ef41Sopenharmony_ci DCHECK_LE(descriptor.GetParameterCount(), argc); 10861cb0ef41Sopenharmony_ci } else { 10871cb0ef41Sopenharmony_ci DCHECK_EQ(descriptor.GetParameterCount(), argc); 10881cb0ef41Sopenharmony_ci } 10891cb0ef41Sopenharmony_ci#endif 10901cb0ef41Sopenharmony_ci // Extra arguments not mentioned in the descriptor are passed on the stack. 10911cb0ef41Sopenharmony_ci int stack_parameter_count = argc - descriptor.GetRegisterParameterCount(); 10921cb0ef41Sopenharmony_ci DCHECK_LE(descriptor.GetStackParameterCount(), stack_parameter_count); 10931cb0ef41Sopenharmony_ci 10941cb0ef41Sopenharmony_ci auto call_descriptor = Linkage::GetStubCallDescriptor( 10951cb0ef41Sopenharmony_ci zone(), descriptor, stack_parameter_count, CallDescriptor::kNoFlags, 10961cb0ef41Sopenharmony_ci Operator::kNoProperties, call_mode); 10971cb0ef41Sopenharmony_ci 10981cb0ef41Sopenharmony_ci CallPrologue(); 10991cb0ef41Sopenharmony_ci Node* return_value = 11001cb0ef41Sopenharmony_ci raw_assembler()->CallN(call_descriptor, input_count, inputs); 11011cb0ef41Sopenharmony_ci HandleException(return_value); 11021cb0ef41Sopenharmony_ci CallEpilogue(); 11031cb0ef41Sopenharmony_ci return return_value; 11041cb0ef41Sopenharmony_ci} 11051cb0ef41Sopenharmony_ci 11061cb0ef41Sopenharmony_civoid CodeAssembler::TailCallStubImpl(const CallInterfaceDescriptor& descriptor, 11071cb0ef41Sopenharmony_ci TNode<CodeT> target, TNode<Object> context, 11081cb0ef41Sopenharmony_ci std::initializer_list<Node*> args) { 11091cb0ef41Sopenharmony_ci constexpr size_t kMaxNumArgs = 11; 11101cb0ef41Sopenharmony_ci DCHECK_GE(kMaxNumArgs, args.size()); 11111cb0ef41Sopenharmony_ci DCHECK_EQ(descriptor.GetParameterCount(), args.size()); 11121cb0ef41Sopenharmony_ci auto call_descriptor = Linkage::GetStubCallDescriptor( 11131cb0ef41Sopenharmony_ci zone(), descriptor, descriptor.GetStackParameterCount(), 11141cb0ef41Sopenharmony_ci CallDescriptor::kNoFlags, Operator::kNoProperties); 11151cb0ef41Sopenharmony_ci 11161cb0ef41Sopenharmony_ci NodeArray<kMaxNumArgs + 2> inputs; 11171cb0ef41Sopenharmony_ci inputs.Add(target); 11181cb0ef41Sopenharmony_ci for (auto arg : args) inputs.Add(arg); 11191cb0ef41Sopenharmony_ci if (descriptor.HasContextParameter()) { 11201cb0ef41Sopenharmony_ci inputs.Add(context); 11211cb0ef41Sopenharmony_ci } 11221cb0ef41Sopenharmony_ci 11231cb0ef41Sopenharmony_ci raw_assembler()->TailCallN(call_descriptor, inputs.size(), inputs.data()); 11241cb0ef41Sopenharmony_ci} 11251cb0ef41Sopenharmony_ci 11261cb0ef41Sopenharmony_ciNode* CodeAssembler::CallStubRImpl(StubCallMode call_mode, 11271cb0ef41Sopenharmony_ci const CallInterfaceDescriptor& descriptor, 11281cb0ef41Sopenharmony_ci TNode<Object> target, TNode<Object> context, 11291cb0ef41Sopenharmony_ci std::initializer_list<Node*> args) { 11301cb0ef41Sopenharmony_ci DCHECK(call_mode == StubCallMode::kCallCodeObject || 11311cb0ef41Sopenharmony_ci call_mode == StubCallMode::kCallBuiltinPointer); 11321cb0ef41Sopenharmony_ci 11331cb0ef41Sopenharmony_ci constexpr size_t kMaxNumArgs = 10; 11341cb0ef41Sopenharmony_ci DCHECK_GE(kMaxNumArgs, args.size()); 11351cb0ef41Sopenharmony_ci 11361cb0ef41Sopenharmony_ci NodeArray<kMaxNumArgs + 2> inputs; 11371cb0ef41Sopenharmony_ci inputs.Add(target); 11381cb0ef41Sopenharmony_ci for (auto arg : args) inputs.Add(arg); 11391cb0ef41Sopenharmony_ci if (descriptor.HasContextParameter()) { 11401cb0ef41Sopenharmony_ci inputs.Add(context); 11411cb0ef41Sopenharmony_ci } 11421cb0ef41Sopenharmony_ci 11431cb0ef41Sopenharmony_ci return CallStubN(call_mode, descriptor, inputs.size(), inputs.data()); 11441cb0ef41Sopenharmony_ci} 11451cb0ef41Sopenharmony_ci 11461cb0ef41Sopenharmony_ciNode* CodeAssembler::CallJSStubImpl(const CallInterfaceDescriptor& descriptor, 11471cb0ef41Sopenharmony_ci TNode<Object> target, TNode<Object> context, 11481cb0ef41Sopenharmony_ci TNode<Object> function, 11491cb0ef41Sopenharmony_ci base::Optional<TNode<Object>> new_target, 11501cb0ef41Sopenharmony_ci TNode<Int32T> arity, 11511cb0ef41Sopenharmony_ci std::initializer_list<Node*> args) { 11521cb0ef41Sopenharmony_ci constexpr size_t kMaxNumArgs = 10; 11531cb0ef41Sopenharmony_ci DCHECK_GE(kMaxNumArgs, args.size()); 11541cb0ef41Sopenharmony_ci NodeArray<kMaxNumArgs + 5> inputs; 11551cb0ef41Sopenharmony_ci inputs.Add(target); 11561cb0ef41Sopenharmony_ci inputs.Add(function); 11571cb0ef41Sopenharmony_ci if (new_target) { 11581cb0ef41Sopenharmony_ci inputs.Add(*new_target); 11591cb0ef41Sopenharmony_ci } 11601cb0ef41Sopenharmony_ci inputs.Add(arity); 11611cb0ef41Sopenharmony_ci for (auto arg : args) inputs.Add(arg); 11621cb0ef41Sopenharmony_ci if (descriptor.HasContextParameter()) { 11631cb0ef41Sopenharmony_ci inputs.Add(context); 11641cb0ef41Sopenharmony_ci } 11651cb0ef41Sopenharmony_ci return CallStubN(StubCallMode::kCallCodeObject, descriptor, inputs.size(), 11661cb0ef41Sopenharmony_ci inputs.data()); 11671cb0ef41Sopenharmony_ci} 11681cb0ef41Sopenharmony_ci 11691cb0ef41Sopenharmony_civoid CodeAssembler::TailCallStubThenBytecodeDispatchImpl( 11701cb0ef41Sopenharmony_ci const CallInterfaceDescriptor& descriptor, Node* target, Node* context, 11711cb0ef41Sopenharmony_ci std::initializer_list<Node*> args) { 11721cb0ef41Sopenharmony_ci constexpr size_t kMaxNumArgs = 6; 11731cb0ef41Sopenharmony_ci DCHECK_GE(kMaxNumArgs, args.size()); 11741cb0ef41Sopenharmony_ci 11751cb0ef41Sopenharmony_ci DCHECK_LE(descriptor.GetParameterCount(), args.size()); 11761cb0ef41Sopenharmony_ci int argc = static_cast<int>(args.size()); 11771cb0ef41Sopenharmony_ci // Extra arguments not mentioned in the descriptor are passed on the stack. 11781cb0ef41Sopenharmony_ci int stack_parameter_count = argc - descriptor.GetRegisterParameterCount(); 11791cb0ef41Sopenharmony_ci DCHECK_LE(descriptor.GetStackParameterCount(), stack_parameter_count); 11801cb0ef41Sopenharmony_ci auto call_descriptor = Linkage::GetStubCallDescriptor( 11811cb0ef41Sopenharmony_ci zone(), descriptor, stack_parameter_count, CallDescriptor::kNoFlags, 11821cb0ef41Sopenharmony_ci Operator::kNoProperties); 11831cb0ef41Sopenharmony_ci 11841cb0ef41Sopenharmony_ci NodeArray<kMaxNumArgs + 2> inputs; 11851cb0ef41Sopenharmony_ci inputs.Add(target); 11861cb0ef41Sopenharmony_ci for (auto arg : args) inputs.Add(arg); 11871cb0ef41Sopenharmony_ci inputs.Add(context); 11881cb0ef41Sopenharmony_ci 11891cb0ef41Sopenharmony_ci raw_assembler()->TailCallN(call_descriptor, inputs.size(), inputs.data()); 11901cb0ef41Sopenharmony_ci} 11911cb0ef41Sopenharmony_ci 11921cb0ef41Sopenharmony_citemplate <class... TArgs> 11931cb0ef41Sopenharmony_civoid CodeAssembler::TailCallBytecodeDispatch( 11941cb0ef41Sopenharmony_ci const CallInterfaceDescriptor& descriptor, TNode<RawPtrT> target, 11951cb0ef41Sopenharmony_ci TArgs... args) { 11961cb0ef41Sopenharmony_ci DCHECK_EQ(descriptor.GetParameterCount(), sizeof...(args)); 11971cb0ef41Sopenharmony_ci auto call_descriptor = Linkage::GetBytecodeDispatchCallDescriptor( 11981cb0ef41Sopenharmony_ci zone(), descriptor, descriptor.GetStackParameterCount()); 11991cb0ef41Sopenharmony_ci 12001cb0ef41Sopenharmony_ci Node* nodes[] = {target, args...}; 12011cb0ef41Sopenharmony_ci CHECK_EQ(descriptor.GetParameterCount() + 1, arraysize(nodes)); 12021cb0ef41Sopenharmony_ci raw_assembler()->TailCallN(call_descriptor, arraysize(nodes), nodes); 12031cb0ef41Sopenharmony_ci} 12041cb0ef41Sopenharmony_ci 12051cb0ef41Sopenharmony_ci// Instantiate TailCallBytecodeDispatch() for argument counts used by 12061cb0ef41Sopenharmony_ci// CSA-generated code 12071cb0ef41Sopenharmony_citemplate V8_EXPORT_PRIVATE void CodeAssembler::TailCallBytecodeDispatch( 12081cb0ef41Sopenharmony_ci const CallInterfaceDescriptor& descriptor, TNode<RawPtrT> target, 12091cb0ef41Sopenharmony_ci TNode<Object>, TNode<IntPtrT>, TNode<BytecodeArray>, 12101cb0ef41Sopenharmony_ci TNode<ExternalReference>); 12111cb0ef41Sopenharmony_ci 12121cb0ef41Sopenharmony_civoid CodeAssembler::TailCallJSCode(TNode<CodeT> code, TNode<Context> context, 12131cb0ef41Sopenharmony_ci TNode<JSFunction> function, 12141cb0ef41Sopenharmony_ci TNode<Object> new_target, 12151cb0ef41Sopenharmony_ci TNode<Int32T> arg_count) { 12161cb0ef41Sopenharmony_ci JSTrampolineDescriptor descriptor; 12171cb0ef41Sopenharmony_ci auto call_descriptor = Linkage::GetStubCallDescriptor( 12181cb0ef41Sopenharmony_ci zone(), descriptor, descriptor.GetStackParameterCount(), 12191cb0ef41Sopenharmony_ci CallDescriptor::kFixedTargetRegister, Operator::kNoProperties); 12201cb0ef41Sopenharmony_ci 12211cb0ef41Sopenharmony_ci Node* nodes[] = {code, function, new_target, arg_count, context}; 12221cb0ef41Sopenharmony_ci CHECK_EQ(descriptor.GetParameterCount() + 2, arraysize(nodes)); 12231cb0ef41Sopenharmony_ci raw_assembler()->TailCallN(call_descriptor, arraysize(nodes), nodes); 12241cb0ef41Sopenharmony_ci} 12251cb0ef41Sopenharmony_ci 12261cb0ef41Sopenharmony_ciNode* CodeAssembler::CallCFunctionN(Signature<MachineType>* signature, 12271cb0ef41Sopenharmony_ci int input_count, Node* const* inputs) { 12281cb0ef41Sopenharmony_ci auto call_descriptor = Linkage::GetSimplifiedCDescriptor(zone(), signature); 12291cb0ef41Sopenharmony_ci return raw_assembler()->CallN(call_descriptor, input_count, inputs); 12301cb0ef41Sopenharmony_ci} 12311cb0ef41Sopenharmony_ci 12321cb0ef41Sopenharmony_ciNode* CodeAssembler::CallCFunction( 12331cb0ef41Sopenharmony_ci Node* function, base::Optional<MachineType> return_type, 12341cb0ef41Sopenharmony_ci std::initializer_list<CodeAssembler::CFunctionArg> args) { 12351cb0ef41Sopenharmony_ci return raw_assembler()->CallCFunction(function, return_type, args); 12361cb0ef41Sopenharmony_ci} 12371cb0ef41Sopenharmony_ci 12381cb0ef41Sopenharmony_ciNode* CodeAssembler::CallCFunctionWithoutFunctionDescriptor( 12391cb0ef41Sopenharmony_ci Node* function, MachineType return_type, 12401cb0ef41Sopenharmony_ci std::initializer_list<CodeAssembler::CFunctionArg> args) { 12411cb0ef41Sopenharmony_ci return raw_assembler()->CallCFunctionWithoutFunctionDescriptor( 12421cb0ef41Sopenharmony_ci function, return_type, args); 12431cb0ef41Sopenharmony_ci} 12441cb0ef41Sopenharmony_ci 12451cb0ef41Sopenharmony_ciNode* CodeAssembler::CallCFunctionWithCallerSavedRegisters( 12461cb0ef41Sopenharmony_ci Node* function, MachineType return_type, SaveFPRegsMode mode, 12471cb0ef41Sopenharmony_ci std::initializer_list<CodeAssembler::CFunctionArg> args) { 12481cb0ef41Sopenharmony_ci DCHECK(return_type.LessThanOrEqualPointerSize()); 12491cb0ef41Sopenharmony_ci return raw_assembler()->CallCFunctionWithCallerSavedRegisters( 12501cb0ef41Sopenharmony_ci function, return_type, mode, args); 12511cb0ef41Sopenharmony_ci} 12521cb0ef41Sopenharmony_ci 12531cb0ef41Sopenharmony_civoid CodeAssembler::Goto(Label* label) { 12541cb0ef41Sopenharmony_ci label->MergeVariables(); 12551cb0ef41Sopenharmony_ci raw_assembler()->Goto(label->label_); 12561cb0ef41Sopenharmony_ci} 12571cb0ef41Sopenharmony_ci 12581cb0ef41Sopenharmony_civoid CodeAssembler::GotoIf(TNode<IntegralT> condition, Label* true_label) { 12591cb0ef41Sopenharmony_ci Label false_label(this); 12601cb0ef41Sopenharmony_ci Branch(condition, true_label, &false_label); 12611cb0ef41Sopenharmony_ci Bind(&false_label); 12621cb0ef41Sopenharmony_ci} 12631cb0ef41Sopenharmony_ci 12641cb0ef41Sopenharmony_civoid CodeAssembler::GotoIfNot(TNode<IntegralT> condition, Label* false_label) { 12651cb0ef41Sopenharmony_ci Label true_label(this); 12661cb0ef41Sopenharmony_ci Branch(condition, &true_label, false_label); 12671cb0ef41Sopenharmony_ci Bind(&true_label); 12681cb0ef41Sopenharmony_ci} 12691cb0ef41Sopenharmony_ci 12701cb0ef41Sopenharmony_civoid CodeAssembler::Branch(TNode<IntegralT> condition, Label* true_label, 12711cb0ef41Sopenharmony_ci Label* false_label) { 12721cb0ef41Sopenharmony_ci int32_t constant; 12731cb0ef41Sopenharmony_ci if (TryToInt32Constant(condition, &constant)) { 12741cb0ef41Sopenharmony_ci if ((true_label->is_used() || true_label->is_bound()) && 12751cb0ef41Sopenharmony_ci (false_label->is_used() || false_label->is_bound())) { 12761cb0ef41Sopenharmony_ci return Goto(constant ? true_label : false_label); 12771cb0ef41Sopenharmony_ci } 12781cb0ef41Sopenharmony_ci } 12791cb0ef41Sopenharmony_ci true_label->MergeVariables(); 12801cb0ef41Sopenharmony_ci false_label->MergeVariables(); 12811cb0ef41Sopenharmony_ci return raw_assembler()->Branch(condition, true_label->label_, 12821cb0ef41Sopenharmony_ci false_label->label_); 12831cb0ef41Sopenharmony_ci} 12841cb0ef41Sopenharmony_ci 12851cb0ef41Sopenharmony_civoid CodeAssembler::Branch(TNode<BoolT> condition, 12861cb0ef41Sopenharmony_ci const std::function<void()>& true_body, 12871cb0ef41Sopenharmony_ci const std::function<void()>& false_body) { 12881cb0ef41Sopenharmony_ci int32_t constant; 12891cb0ef41Sopenharmony_ci if (TryToInt32Constant(condition, &constant)) { 12901cb0ef41Sopenharmony_ci return constant ? true_body() : false_body(); 12911cb0ef41Sopenharmony_ci } 12921cb0ef41Sopenharmony_ci 12931cb0ef41Sopenharmony_ci Label vtrue(this), vfalse(this); 12941cb0ef41Sopenharmony_ci Branch(condition, &vtrue, &vfalse); 12951cb0ef41Sopenharmony_ci 12961cb0ef41Sopenharmony_ci Bind(&vtrue); 12971cb0ef41Sopenharmony_ci true_body(); 12981cb0ef41Sopenharmony_ci 12991cb0ef41Sopenharmony_ci Bind(&vfalse); 13001cb0ef41Sopenharmony_ci false_body(); 13011cb0ef41Sopenharmony_ci} 13021cb0ef41Sopenharmony_ci 13031cb0ef41Sopenharmony_civoid CodeAssembler::Branch(TNode<BoolT> condition, Label* true_label, 13041cb0ef41Sopenharmony_ci const std::function<void()>& false_body) { 13051cb0ef41Sopenharmony_ci int32_t constant; 13061cb0ef41Sopenharmony_ci if (TryToInt32Constant(condition, &constant)) { 13071cb0ef41Sopenharmony_ci return constant ? Goto(true_label) : false_body(); 13081cb0ef41Sopenharmony_ci } 13091cb0ef41Sopenharmony_ci 13101cb0ef41Sopenharmony_ci Label vfalse(this); 13111cb0ef41Sopenharmony_ci Branch(condition, true_label, &vfalse); 13121cb0ef41Sopenharmony_ci Bind(&vfalse); 13131cb0ef41Sopenharmony_ci false_body(); 13141cb0ef41Sopenharmony_ci} 13151cb0ef41Sopenharmony_ci 13161cb0ef41Sopenharmony_civoid CodeAssembler::Branch(TNode<BoolT> condition, 13171cb0ef41Sopenharmony_ci const std::function<void()>& true_body, 13181cb0ef41Sopenharmony_ci Label* false_label) { 13191cb0ef41Sopenharmony_ci int32_t constant; 13201cb0ef41Sopenharmony_ci if (TryToInt32Constant(condition, &constant)) { 13211cb0ef41Sopenharmony_ci return constant ? true_body() : Goto(false_label); 13221cb0ef41Sopenharmony_ci } 13231cb0ef41Sopenharmony_ci 13241cb0ef41Sopenharmony_ci Label vtrue(this); 13251cb0ef41Sopenharmony_ci Branch(condition, &vtrue, false_label); 13261cb0ef41Sopenharmony_ci Bind(&vtrue); 13271cb0ef41Sopenharmony_ci true_body(); 13281cb0ef41Sopenharmony_ci} 13291cb0ef41Sopenharmony_ci 13301cb0ef41Sopenharmony_civoid CodeAssembler::Switch(Node* index, Label* default_label, 13311cb0ef41Sopenharmony_ci const int32_t* case_values, Label** case_labels, 13321cb0ef41Sopenharmony_ci size_t case_count) { 13331cb0ef41Sopenharmony_ci RawMachineLabel** labels = zone()->NewArray<RawMachineLabel*>(case_count); 13341cb0ef41Sopenharmony_ci for (size_t i = 0; i < case_count; ++i) { 13351cb0ef41Sopenharmony_ci labels[i] = case_labels[i]->label_; 13361cb0ef41Sopenharmony_ci case_labels[i]->MergeVariables(); 13371cb0ef41Sopenharmony_ci } 13381cb0ef41Sopenharmony_ci default_label->MergeVariables(); 13391cb0ef41Sopenharmony_ci return raw_assembler()->Switch(index, default_label->label_, case_values, 13401cb0ef41Sopenharmony_ci labels, case_count); 13411cb0ef41Sopenharmony_ci} 13421cb0ef41Sopenharmony_ci 13431cb0ef41Sopenharmony_cibool CodeAssembler::UnalignedLoadSupported(MachineRepresentation rep) const { 13441cb0ef41Sopenharmony_ci return raw_assembler()->machine()->UnalignedLoadSupported(rep); 13451cb0ef41Sopenharmony_ci} 13461cb0ef41Sopenharmony_cibool CodeAssembler::UnalignedStoreSupported(MachineRepresentation rep) const { 13471cb0ef41Sopenharmony_ci return raw_assembler()->machine()->UnalignedStoreSupported(rep); 13481cb0ef41Sopenharmony_ci} 13491cb0ef41Sopenharmony_ci 13501cb0ef41Sopenharmony_ci// RawMachineAssembler delegate helpers: 13511cb0ef41Sopenharmony_ciIsolate* CodeAssembler::isolate() const { return raw_assembler()->isolate(); } 13521cb0ef41Sopenharmony_ci 13531cb0ef41Sopenharmony_ciFactory* CodeAssembler::factory() const { return isolate()->factory(); } 13541cb0ef41Sopenharmony_ci 13551cb0ef41Sopenharmony_ciZone* CodeAssembler::zone() const { return raw_assembler()->zone(); } 13561cb0ef41Sopenharmony_ci 13571cb0ef41Sopenharmony_cibool CodeAssembler::IsExceptionHandlerActive() const { 13581cb0ef41Sopenharmony_ci return state_->exception_handler_labels_.size() != 0; 13591cb0ef41Sopenharmony_ci} 13601cb0ef41Sopenharmony_ci 13611cb0ef41Sopenharmony_ciRawMachineAssembler* CodeAssembler::raw_assembler() const { 13621cb0ef41Sopenharmony_ci return state_->raw_assembler_.get(); 13631cb0ef41Sopenharmony_ci} 13641cb0ef41Sopenharmony_ci 13651cb0ef41Sopenharmony_ciJSGraph* CodeAssembler::jsgraph() const { return state_->jsgraph_; } 13661cb0ef41Sopenharmony_ci 13671cb0ef41Sopenharmony_ci// The core implementation of Variable is stored through an indirection so 13681cb0ef41Sopenharmony_ci// that it can outlive the often block-scoped Variable declarations. This is 13691cb0ef41Sopenharmony_ci// needed to ensure that variable binding and merging through phis can 13701cb0ef41Sopenharmony_ci// properly be verified. 13711cb0ef41Sopenharmony_ciclass CodeAssemblerVariable::Impl : public ZoneObject { 13721cb0ef41Sopenharmony_ci public: 13731cb0ef41Sopenharmony_ci explicit Impl(MachineRepresentation rep, CodeAssemblerState::VariableId id) 13741cb0ef41Sopenharmony_ci : 13751cb0ef41Sopenharmony_ci#if DEBUG 13761cb0ef41Sopenharmony_ci debug_info_(AssemblerDebugInfo(nullptr, nullptr, -1)), 13771cb0ef41Sopenharmony_ci#endif 13781cb0ef41Sopenharmony_ci value_(nullptr), 13791cb0ef41Sopenharmony_ci rep_(rep), 13801cb0ef41Sopenharmony_ci var_id_(id) { 13811cb0ef41Sopenharmony_ci } 13821cb0ef41Sopenharmony_ci 13831cb0ef41Sopenharmony_ci#if DEBUG 13841cb0ef41Sopenharmony_ci AssemblerDebugInfo debug_info() const { return debug_info_; } 13851cb0ef41Sopenharmony_ci void set_debug_info(AssemblerDebugInfo debug_info) { 13861cb0ef41Sopenharmony_ci debug_info_ = debug_info; 13871cb0ef41Sopenharmony_ci } 13881cb0ef41Sopenharmony_ci 13891cb0ef41Sopenharmony_ci AssemblerDebugInfo debug_info_; 13901cb0ef41Sopenharmony_ci#endif // DEBUG 13911cb0ef41Sopenharmony_ci bool operator<(const CodeAssemblerVariable::Impl& other) const { 13921cb0ef41Sopenharmony_ci return var_id_ < other.var_id_; 13931cb0ef41Sopenharmony_ci } 13941cb0ef41Sopenharmony_ci Node* value_; 13951cb0ef41Sopenharmony_ci MachineRepresentation rep_; 13961cb0ef41Sopenharmony_ci CodeAssemblerState::VariableId var_id_; 13971cb0ef41Sopenharmony_ci}; 13981cb0ef41Sopenharmony_ci 13991cb0ef41Sopenharmony_cibool CodeAssemblerVariable::ImplComparator::operator()( 14001cb0ef41Sopenharmony_ci const CodeAssemblerVariable::Impl* a, 14011cb0ef41Sopenharmony_ci const CodeAssemblerVariable::Impl* b) const { 14021cb0ef41Sopenharmony_ci return *a < *b; 14031cb0ef41Sopenharmony_ci} 14041cb0ef41Sopenharmony_ci 14051cb0ef41Sopenharmony_ciCodeAssemblerVariable::CodeAssemblerVariable(CodeAssembler* assembler, 14061cb0ef41Sopenharmony_ci MachineRepresentation rep) 14071cb0ef41Sopenharmony_ci : impl_(assembler->zone()->New<Impl>(rep, 14081cb0ef41Sopenharmony_ci assembler->state()->NextVariableId())), 14091cb0ef41Sopenharmony_ci state_(assembler->state()) { 14101cb0ef41Sopenharmony_ci state_->variables_.insert(impl_); 14111cb0ef41Sopenharmony_ci} 14121cb0ef41Sopenharmony_ci 14131cb0ef41Sopenharmony_ciCodeAssemblerVariable::CodeAssemblerVariable(CodeAssembler* assembler, 14141cb0ef41Sopenharmony_ci MachineRepresentation rep, 14151cb0ef41Sopenharmony_ci Node* initial_value) 14161cb0ef41Sopenharmony_ci : CodeAssemblerVariable(assembler, rep) { 14171cb0ef41Sopenharmony_ci Bind(initial_value); 14181cb0ef41Sopenharmony_ci} 14191cb0ef41Sopenharmony_ci 14201cb0ef41Sopenharmony_ci#if DEBUG 14211cb0ef41Sopenharmony_ciCodeAssemblerVariable::CodeAssemblerVariable(CodeAssembler* assembler, 14221cb0ef41Sopenharmony_ci AssemblerDebugInfo debug_info, 14231cb0ef41Sopenharmony_ci MachineRepresentation rep) 14241cb0ef41Sopenharmony_ci : impl_(assembler->zone()->New<Impl>(rep, 14251cb0ef41Sopenharmony_ci assembler->state()->NextVariableId())), 14261cb0ef41Sopenharmony_ci state_(assembler->state()) { 14271cb0ef41Sopenharmony_ci impl_->set_debug_info(debug_info); 14281cb0ef41Sopenharmony_ci state_->variables_.insert(impl_); 14291cb0ef41Sopenharmony_ci} 14301cb0ef41Sopenharmony_ci 14311cb0ef41Sopenharmony_ciCodeAssemblerVariable::CodeAssemblerVariable(CodeAssembler* assembler, 14321cb0ef41Sopenharmony_ci AssemblerDebugInfo debug_info, 14331cb0ef41Sopenharmony_ci MachineRepresentation rep, 14341cb0ef41Sopenharmony_ci Node* initial_value) 14351cb0ef41Sopenharmony_ci : CodeAssemblerVariable(assembler, debug_info, rep) { 14361cb0ef41Sopenharmony_ci impl_->set_debug_info(debug_info); 14371cb0ef41Sopenharmony_ci Bind(initial_value); 14381cb0ef41Sopenharmony_ci} 14391cb0ef41Sopenharmony_ci#endif // DEBUG 14401cb0ef41Sopenharmony_ci 14411cb0ef41Sopenharmony_ciCodeAssemblerVariable::~CodeAssemblerVariable() { 14421cb0ef41Sopenharmony_ci state_->variables_.erase(impl_); 14431cb0ef41Sopenharmony_ci} 14441cb0ef41Sopenharmony_ci 14451cb0ef41Sopenharmony_civoid CodeAssemblerVariable::Bind(Node* value) { impl_->value_ = value; } 14461cb0ef41Sopenharmony_ci 14471cb0ef41Sopenharmony_ciNode* CodeAssemblerVariable::value() const { 14481cb0ef41Sopenharmony_ci#if DEBUG 14491cb0ef41Sopenharmony_ci if (!IsBound()) { 14501cb0ef41Sopenharmony_ci std::stringstream str; 14511cb0ef41Sopenharmony_ci str << "#Use of unbound variable:" 14521cb0ef41Sopenharmony_ci << "#\n Variable: " << *this << "#\n Current Block: "; 14531cb0ef41Sopenharmony_ci state_->PrintCurrentBlock(str); 14541cb0ef41Sopenharmony_ci FATAL("%s", str.str().c_str()); 14551cb0ef41Sopenharmony_ci } 14561cb0ef41Sopenharmony_ci if (!state_->InsideBlock()) { 14571cb0ef41Sopenharmony_ci std::stringstream str; 14581cb0ef41Sopenharmony_ci str << "#Accessing variable value outside a block:" 14591cb0ef41Sopenharmony_ci << "#\n Variable: " << *this; 14601cb0ef41Sopenharmony_ci FATAL("%s", str.str().c_str()); 14611cb0ef41Sopenharmony_ci } 14621cb0ef41Sopenharmony_ci#endif // DEBUG 14631cb0ef41Sopenharmony_ci return impl_->value_; 14641cb0ef41Sopenharmony_ci} 14651cb0ef41Sopenharmony_ci 14661cb0ef41Sopenharmony_ciMachineRepresentation CodeAssemblerVariable::rep() const { return impl_->rep_; } 14671cb0ef41Sopenharmony_ci 14681cb0ef41Sopenharmony_cibool CodeAssemblerVariable::IsBound() const { return impl_->value_ != nullptr; } 14691cb0ef41Sopenharmony_ci 14701cb0ef41Sopenharmony_cistd::ostream& operator<<(std::ostream& os, 14711cb0ef41Sopenharmony_ci const CodeAssemblerVariable::Impl& impl) { 14721cb0ef41Sopenharmony_ci#if DEBUG 14731cb0ef41Sopenharmony_ci AssemblerDebugInfo info = impl.debug_info(); 14741cb0ef41Sopenharmony_ci if (info.name) os << "V" << info; 14751cb0ef41Sopenharmony_ci#endif // DEBUG 14761cb0ef41Sopenharmony_ci return os; 14771cb0ef41Sopenharmony_ci} 14781cb0ef41Sopenharmony_ci 14791cb0ef41Sopenharmony_cistd::ostream& operator<<(std::ostream& os, 14801cb0ef41Sopenharmony_ci const CodeAssemblerVariable& variable) { 14811cb0ef41Sopenharmony_ci os << *variable.impl_; 14821cb0ef41Sopenharmony_ci return os; 14831cb0ef41Sopenharmony_ci} 14841cb0ef41Sopenharmony_ci 14851cb0ef41Sopenharmony_ciCodeAssemblerLabel::CodeAssemblerLabel(CodeAssembler* assembler, 14861cb0ef41Sopenharmony_ci size_t vars_count, 14871cb0ef41Sopenharmony_ci CodeAssemblerVariable* const* vars, 14881cb0ef41Sopenharmony_ci CodeAssemblerLabel::Type type) 14891cb0ef41Sopenharmony_ci : bound_(false), 14901cb0ef41Sopenharmony_ci merge_count_(0), 14911cb0ef41Sopenharmony_ci state_(assembler->state()), 14921cb0ef41Sopenharmony_ci label_(nullptr) { 14931cb0ef41Sopenharmony_ci label_ = assembler->zone()->New<RawMachineLabel>( 14941cb0ef41Sopenharmony_ci type == kDeferred ? RawMachineLabel::kDeferred 14951cb0ef41Sopenharmony_ci : RawMachineLabel::kNonDeferred); 14961cb0ef41Sopenharmony_ci for (size_t i = 0; i < vars_count; ++i) { 14971cb0ef41Sopenharmony_ci variable_phis_[vars[i]->impl_] = nullptr; 14981cb0ef41Sopenharmony_ci } 14991cb0ef41Sopenharmony_ci} 15001cb0ef41Sopenharmony_ci 15011cb0ef41Sopenharmony_ciCodeAssemblerLabel::~CodeAssemblerLabel() { label_->~RawMachineLabel(); } 15021cb0ef41Sopenharmony_ci 15031cb0ef41Sopenharmony_civoid CodeAssemblerLabel::MergeVariables() { 15041cb0ef41Sopenharmony_ci ++merge_count_; 15051cb0ef41Sopenharmony_ci for (CodeAssemblerVariable::Impl* var : state_->variables_) { 15061cb0ef41Sopenharmony_ci size_t count = 0; 15071cb0ef41Sopenharmony_ci Node* node = var->value_; 15081cb0ef41Sopenharmony_ci if (node != nullptr) { 15091cb0ef41Sopenharmony_ci auto i = variable_merges_.find(var); 15101cb0ef41Sopenharmony_ci if (i != variable_merges_.end()) { 15111cb0ef41Sopenharmony_ci i->second.push_back(node); 15121cb0ef41Sopenharmony_ci count = i->second.size(); 15131cb0ef41Sopenharmony_ci } else { 15141cb0ef41Sopenharmony_ci count = 1; 15151cb0ef41Sopenharmony_ci variable_merges_[var] = std::vector<Node*>(1, node); 15161cb0ef41Sopenharmony_ci } 15171cb0ef41Sopenharmony_ci } 15181cb0ef41Sopenharmony_ci // If the following asserts, then you've jumped to a label without a bound 15191cb0ef41Sopenharmony_ci // variable along that path that expects to merge its value into a phi. 15201cb0ef41Sopenharmony_ci // This can also occur if a label is bound that is never jumped to. 15211cb0ef41Sopenharmony_ci DCHECK(variable_phis_.find(var) == variable_phis_.end() || 15221cb0ef41Sopenharmony_ci count == merge_count_); 15231cb0ef41Sopenharmony_ci USE(count); 15241cb0ef41Sopenharmony_ci 15251cb0ef41Sopenharmony_ci // If the label is already bound, we already know the set of variables to 15261cb0ef41Sopenharmony_ci // merge and phi nodes have already been created. 15271cb0ef41Sopenharmony_ci if (bound_) { 15281cb0ef41Sopenharmony_ci auto phi = variable_phis_.find(var); 15291cb0ef41Sopenharmony_ci if (phi != variable_phis_.end()) { 15301cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(phi->second); 15311cb0ef41Sopenharmony_ci state_->raw_assembler_->AppendPhiInput(phi->second, node); 15321cb0ef41Sopenharmony_ci } else { 15331cb0ef41Sopenharmony_ci auto i = variable_merges_.find(var); 15341cb0ef41Sopenharmony_ci if (i != variable_merges_.end()) { 15351cb0ef41Sopenharmony_ci // If the following assert fires, then you've declared a variable that 15361cb0ef41Sopenharmony_ci // has the same bound value along all paths up until the point you 15371cb0ef41Sopenharmony_ci // bound this label, but then later merged a path with a new value for 15381cb0ef41Sopenharmony_ci // the variable after the label bind (it's not possible to add phis to 15391cb0ef41Sopenharmony_ci // the bound label after the fact, just make sure to list the variable 15401cb0ef41Sopenharmony_ci // in the label's constructor's list of merged variables). 15411cb0ef41Sopenharmony_ci#if DEBUG 15421cb0ef41Sopenharmony_ci if (find_if(i->second.begin(), i->second.end(), 15431cb0ef41Sopenharmony_ci [node](Node* e) -> bool { return node != e; }) != 15441cb0ef41Sopenharmony_ci i->second.end()) { 15451cb0ef41Sopenharmony_ci std::stringstream str; 15461cb0ef41Sopenharmony_ci str << "Unmerged variable found when jumping to block. \n" 15471cb0ef41Sopenharmony_ci << "# Variable: " << *var; 15481cb0ef41Sopenharmony_ci if (bound_) { 15491cb0ef41Sopenharmony_ci str << "\n# Target block: " << *label_->block(); 15501cb0ef41Sopenharmony_ci } 15511cb0ef41Sopenharmony_ci str << "\n# Current Block: "; 15521cb0ef41Sopenharmony_ci state_->PrintCurrentBlock(str); 15531cb0ef41Sopenharmony_ci FATAL("%s", str.str().c_str()); 15541cb0ef41Sopenharmony_ci } 15551cb0ef41Sopenharmony_ci#endif // DEBUG 15561cb0ef41Sopenharmony_ci } 15571cb0ef41Sopenharmony_ci } 15581cb0ef41Sopenharmony_ci } 15591cb0ef41Sopenharmony_ci } 15601cb0ef41Sopenharmony_ci} 15611cb0ef41Sopenharmony_ci 15621cb0ef41Sopenharmony_ci#if DEBUG 15631cb0ef41Sopenharmony_civoid CodeAssemblerLabel::Bind(AssemblerDebugInfo debug_info) { 15641cb0ef41Sopenharmony_ci if (bound_) { 15651cb0ef41Sopenharmony_ci std::stringstream str; 15661cb0ef41Sopenharmony_ci str << "Cannot bind the same label twice:" 15671cb0ef41Sopenharmony_ci << "\n# current: " << debug_info 15681cb0ef41Sopenharmony_ci << "\n# previous: " << *label_->block(); 15691cb0ef41Sopenharmony_ci FATAL("%s", str.str().c_str()); 15701cb0ef41Sopenharmony_ci } 15711cb0ef41Sopenharmony_ci if (FLAG_enable_source_at_csa_bind) { 15721cb0ef41Sopenharmony_ci state_->raw_assembler_->SetCurrentExternalSourcePosition( 15731cb0ef41Sopenharmony_ci {debug_info.file, debug_info.line}); 15741cb0ef41Sopenharmony_ci } 15751cb0ef41Sopenharmony_ci state_->raw_assembler_->Bind(label_, debug_info); 15761cb0ef41Sopenharmony_ci UpdateVariablesAfterBind(); 15771cb0ef41Sopenharmony_ci} 15781cb0ef41Sopenharmony_ci#endif // DEBUG 15791cb0ef41Sopenharmony_ci 15801cb0ef41Sopenharmony_civoid CodeAssemblerLabel::Bind() { 15811cb0ef41Sopenharmony_ci DCHECK(!bound_); 15821cb0ef41Sopenharmony_ci state_->raw_assembler_->Bind(label_); 15831cb0ef41Sopenharmony_ci UpdateVariablesAfterBind(); 15841cb0ef41Sopenharmony_ci} 15851cb0ef41Sopenharmony_ci 15861cb0ef41Sopenharmony_civoid CodeAssemblerLabel::UpdateVariablesAfterBind() { 15871cb0ef41Sopenharmony_ci // Make sure that all variables that have changed along any path up to this 15881cb0ef41Sopenharmony_ci // point are marked as merge variables. 15891cb0ef41Sopenharmony_ci for (auto var : state_->variables_) { 15901cb0ef41Sopenharmony_ci Node* shared_value = nullptr; 15911cb0ef41Sopenharmony_ci auto i = variable_merges_.find(var); 15921cb0ef41Sopenharmony_ci if (i != variable_merges_.end()) { 15931cb0ef41Sopenharmony_ci for (auto value : i->second) { 15941cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(value); 15951cb0ef41Sopenharmony_ci if (value != shared_value) { 15961cb0ef41Sopenharmony_ci if (shared_value == nullptr) { 15971cb0ef41Sopenharmony_ci shared_value = value; 15981cb0ef41Sopenharmony_ci } else { 15991cb0ef41Sopenharmony_ci variable_phis_[var] = nullptr; 16001cb0ef41Sopenharmony_ci } 16011cb0ef41Sopenharmony_ci } 16021cb0ef41Sopenharmony_ci } 16031cb0ef41Sopenharmony_ci } 16041cb0ef41Sopenharmony_ci } 16051cb0ef41Sopenharmony_ci 16061cb0ef41Sopenharmony_ci for (auto var : variable_phis_) { 16071cb0ef41Sopenharmony_ci CodeAssemblerVariable::Impl* var_impl = var.first; 16081cb0ef41Sopenharmony_ci auto i = variable_merges_.find(var_impl); 16091cb0ef41Sopenharmony_ci#if DEBUG 16101cb0ef41Sopenharmony_ci bool not_found = i == variable_merges_.end(); 16111cb0ef41Sopenharmony_ci if (not_found || i->second.size() != merge_count_) { 16121cb0ef41Sopenharmony_ci std::stringstream str; 16131cb0ef41Sopenharmony_ci str << "A variable that has been marked as beeing merged at the label" 16141cb0ef41Sopenharmony_ci << "\n# doesn't have a bound value along all of the paths that " 16151cb0ef41Sopenharmony_ci << "\n# have been merged into the label up to this point." 16161cb0ef41Sopenharmony_ci << "\n#" 16171cb0ef41Sopenharmony_ci << "\n# This can happen in the following cases:" 16181cb0ef41Sopenharmony_ci << "\n# - By explicitly marking it so in the label constructor" 16191cb0ef41Sopenharmony_ci << "\n# - By having seen different bound values at branches" 16201cb0ef41Sopenharmony_ci << "\n#" 16211cb0ef41Sopenharmony_ci << "\n# Merge count: expected=" << merge_count_ 16221cb0ef41Sopenharmony_ci << " vs. found=" << (not_found ? 0 : i->second.size()) 16231cb0ef41Sopenharmony_ci << "\n# Variable: " << *var_impl 16241cb0ef41Sopenharmony_ci << "\n# Current Block: " << *label_->block(); 16251cb0ef41Sopenharmony_ci FATAL("%s", str.str().c_str()); 16261cb0ef41Sopenharmony_ci } 16271cb0ef41Sopenharmony_ci#endif // DEBUG 16281cb0ef41Sopenharmony_ci Node* phi = state_->raw_assembler_->Phi( 16291cb0ef41Sopenharmony_ci var.first->rep_, static_cast<int>(merge_count_), &(i->second[0])); 16301cb0ef41Sopenharmony_ci variable_phis_[var_impl] = phi; 16311cb0ef41Sopenharmony_ci } 16321cb0ef41Sopenharmony_ci 16331cb0ef41Sopenharmony_ci // Bind all variables to a merge phi, the common value along all paths or 16341cb0ef41Sopenharmony_ci // null. 16351cb0ef41Sopenharmony_ci for (auto var : state_->variables_) { 16361cb0ef41Sopenharmony_ci auto i = variable_phis_.find(var); 16371cb0ef41Sopenharmony_ci if (i != variable_phis_.end()) { 16381cb0ef41Sopenharmony_ci var->value_ = i->second; 16391cb0ef41Sopenharmony_ci } else { 16401cb0ef41Sopenharmony_ci auto j = variable_merges_.find(var); 16411cb0ef41Sopenharmony_ci if (j != variable_merges_.end() && j->second.size() == merge_count_) { 16421cb0ef41Sopenharmony_ci var->value_ = j->second.back(); 16431cb0ef41Sopenharmony_ci } else { 16441cb0ef41Sopenharmony_ci var->value_ = nullptr; 16451cb0ef41Sopenharmony_ci } 16461cb0ef41Sopenharmony_ci } 16471cb0ef41Sopenharmony_ci } 16481cb0ef41Sopenharmony_ci 16491cb0ef41Sopenharmony_ci bound_ = true; 16501cb0ef41Sopenharmony_ci} 16511cb0ef41Sopenharmony_ci 16521cb0ef41Sopenharmony_civoid CodeAssemblerParameterizedLabelBase::AddInputs(std::vector<Node*> inputs) { 16531cb0ef41Sopenharmony_ci if (!phi_nodes_.empty()) { 16541cb0ef41Sopenharmony_ci DCHECK_EQ(inputs.size(), phi_nodes_.size()); 16551cb0ef41Sopenharmony_ci for (size_t i = 0; i < inputs.size(); ++i) { 16561cb0ef41Sopenharmony_ci // We use {nullptr} as a sentinel for an uninitialized value. 16571cb0ef41Sopenharmony_ci if (phi_nodes_[i] == nullptr) continue; 16581cb0ef41Sopenharmony_ci state_->raw_assembler_->AppendPhiInput(phi_nodes_[i], inputs[i]); 16591cb0ef41Sopenharmony_ci } 16601cb0ef41Sopenharmony_ci } else { 16611cb0ef41Sopenharmony_ci DCHECK_EQ(inputs.size(), phi_inputs_.size()); 16621cb0ef41Sopenharmony_ci for (size_t i = 0; i < inputs.size(); ++i) { 16631cb0ef41Sopenharmony_ci phi_inputs_[i].push_back(inputs[i]); 16641cb0ef41Sopenharmony_ci } 16651cb0ef41Sopenharmony_ci } 16661cb0ef41Sopenharmony_ci} 16671cb0ef41Sopenharmony_ci 16681cb0ef41Sopenharmony_ciNode* CodeAssemblerParameterizedLabelBase::CreatePhi( 16691cb0ef41Sopenharmony_ci MachineRepresentation rep, const std::vector<Node*>& inputs) { 16701cb0ef41Sopenharmony_ci for (Node* input : inputs) { 16711cb0ef41Sopenharmony_ci // We use {nullptr} as a sentinel for an uninitialized value. We must not 16721cb0ef41Sopenharmony_ci // create phi nodes for these. 16731cb0ef41Sopenharmony_ci if (input == nullptr) return nullptr; 16741cb0ef41Sopenharmony_ci } 16751cb0ef41Sopenharmony_ci return state_->raw_assembler_->Phi(rep, static_cast<int>(inputs.size()), 16761cb0ef41Sopenharmony_ci &inputs.front()); 16771cb0ef41Sopenharmony_ci} 16781cb0ef41Sopenharmony_ci 16791cb0ef41Sopenharmony_ciconst std::vector<Node*>& CodeAssemblerParameterizedLabelBase::CreatePhis( 16801cb0ef41Sopenharmony_ci std::vector<MachineRepresentation> representations) { 16811cb0ef41Sopenharmony_ci DCHECK(is_used()); 16821cb0ef41Sopenharmony_ci DCHECK(phi_nodes_.empty()); 16831cb0ef41Sopenharmony_ci phi_nodes_.reserve(phi_inputs_.size()); 16841cb0ef41Sopenharmony_ci DCHECK_EQ(representations.size(), phi_inputs_.size()); 16851cb0ef41Sopenharmony_ci for (size_t i = 0; i < phi_inputs_.size(); ++i) { 16861cb0ef41Sopenharmony_ci phi_nodes_.push_back(CreatePhi(representations[i], phi_inputs_[i])); 16871cb0ef41Sopenharmony_ci } 16881cb0ef41Sopenharmony_ci return phi_nodes_; 16891cb0ef41Sopenharmony_ci} 16901cb0ef41Sopenharmony_ci 16911cb0ef41Sopenharmony_civoid CodeAssemblerState::PushExceptionHandler( 16921cb0ef41Sopenharmony_ci CodeAssemblerExceptionHandlerLabel* label) { 16931cb0ef41Sopenharmony_ci exception_handler_labels_.push_back(label); 16941cb0ef41Sopenharmony_ci} 16951cb0ef41Sopenharmony_ci 16961cb0ef41Sopenharmony_civoid CodeAssemblerState::PopExceptionHandler() { 16971cb0ef41Sopenharmony_ci exception_handler_labels_.pop_back(); 16981cb0ef41Sopenharmony_ci} 16991cb0ef41Sopenharmony_ci 17001cb0ef41Sopenharmony_ciScopedExceptionHandler::ScopedExceptionHandler( 17011cb0ef41Sopenharmony_ci CodeAssembler* assembler, CodeAssemblerExceptionHandlerLabel* label) 17021cb0ef41Sopenharmony_ci : has_handler_(label != nullptr), 17031cb0ef41Sopenharmony_ci assembler_(assembler), 17041cb0ef41Sopenharmony_ci compatibility_label_(nullptr), 17051cb0ef41Sopenharmony_ci exception_(nullptr) { 17061cb0ef41Sopenharmony_ci if (has_handler_) { 17071cb0ef41Sopenharmony_ci assembler_->state()->PushExceptionHandler(label); 17081cb0ef41Sopenharmony_ci } 17091cb0ef41Sopenharmony_ci} 17101cb0ef41Sopenharmony_ci 17111cb0ef41Sopenharmony_ciScopedExceptionHandler::ScopedExceptionHandler( 17121cb0ef41Sopenharmony_ci CodeAssembler* assembler, CodeAssemblerLabel* label, 17131cb0ef41Sopenharmony_ci TypedCodeAssemblerVariable<Object>* exception) 17141cb0ef41Sopenharmony_ci : has_handler_(label != nullptr), 17151cb0ef41Sopenharmony_ci assembler_(assembler), 17161cb0ef41Sopenharmony_ci compatibility_label_(label), 17171cb0ef41Sopenharmony_ci exception_(exception) { 17181cb0ef41Sopenharmony_ci if (has_handler_) { 17191cb0ef41Sopenharmony_ci label_ = std::make_unique<CodeAssemblerExceptionHandlerLabel>( 17201cb0ef41Sopenharmony_ci assembler, CodeAssemblerLabel::kDeferred); 17211cb0ef41Sopenharmony_ci assembler_->state()->PushExceptionHandler(label_.get()); 17221cb0ef41Sopenharmony_ci } 17231cb0ef41Sopenharmony_ci} 17241cb0ef41Sopenharmony_ci 17251cb0ef41Sopenharmony_ciScopedExceptionHandler::~ScopedExceptionHandler() { 17261cb0ef41Sopenharmony_ci if (has_handler_) { 17271cb0ef41Sopenharmony_ci assembler_->state()->PopExceptionHandler(); 17281cb0ef41Sopenharmony_ci } 17291cb0ef41Sopenharmony_ci if (label_ && label_->is_used()) { 17301cb0ef41Sopenharmony_ci CodeAssembler::Label skip(assembler_); 17311cb0ef41Sopenharmony_ci bool inside_block = assembler_->state()->InsideBlock(); 17321cb0ef41Sopenharmony_ci if (inside_block) { 17331cb0ef41Sopenharmony_ci assembler_->Goto(&skip); 17341cb0ef41Sopenharmony_ci } 17351cb0ef41Sopenharmony_ci TNode<Object> e; 17361cb0ef41Sopenharmony_ci assembler_->Bind(label_.get(), &e); 17371cb0ef41Sopenharmony_ci if (exception_ != nullptr) *exception_ = e; 17381cb0ef41Sopenharmony_ci assembler_->Goto(compatibility_label_); 17391cb0ef41Sopenharmony_ci if (inside_block) { 17401cb0ef41Sopenharmony_ci assembler_->Bind(&skip); 17411cb0ef41Sopenharmony_ci } 17421cb0ef41Sopenharmony_ci } 17431cb0ef41Sopenharmony_ci} 17441cb0ef41Sopenharmony_ci 17451cb0ef41Sopenharmony_ci} // namespace compiler 17461cb0ef41Sopenharmony_ci 17471cb0ef41Sopenharmony_ci} // namespace internal 17481cb0ef41Sopenharmony_ci} // namespace v8 1749