11cb0ef41Sopenharmony_ci// Copyright 2018 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/api/api.h"
61cb0ef41Sopenharmony_ci#include "src/builtins/builtins-utils-gen.h"
71cb0ef41Sopenharmony_ci#include "src/codegen/code-stub-assembler.h"
81cb0ef41Sopenharmony_ci#include "src/execution/microtask-queue.h"
91cb0ef41Sopenharmony_ci#include "src/objects/js-weak-refs.h"
101cb0ef41Sopenharmony_ci#include "src/objects/microtask-inl.h"
111cb0ef41Sopenharmony_ci#include "src/objects/promise.h"
121cb0ef41Sopenharmony_ci#include "src/objects/smi-inl.h"
131cb0ef41Sopenharmony_ci
141cb0ef41Sopenharmony_cinamespace v8 {
151cb0ef41Sopenharmony_cinamespace internal {
161cb0ef41Sopenharmony_ci
171cb0ef41Sopenharmony_ciusing compiler::ScopedExceptionHandler;
181cb0ef41Sopenharmony_ci
191cb0ef41Sopenharmony_ciclass MicrotaskQueueBuiltinsAssembler : public CodeStubAssembler {
201cb0ef41Sopenharmony_ci public:
211cb0ef41Sopenharmony_ci  explicit MicrotaskQueueBuiltinsAssembler(compiler::CodeAssemblerState* state)
221cb0ef41Sopenharmony_ci      : CodeStubAssembler(state) {}
231cb0ef41Sopenharmony_ci
241cb0ef41Sopenharmony_ci  TNode<RawPtrT> GetMicrotaskQueue(TNode<Context> context);
251cb0ef41Sopenharmony_ci  TNode<RawPtrT> GetMicrotaskRingBuffer(TNode<RawPtrT> microtask_queue);
261cb0ef41Sopenharmony_ci  TNode<IntPtrT> GetMicrotaskQueueCapacity(TNode<RawPtrT> microtask_queue);
271cb0ef41Sopenharmony_ci  TNode<IntPtrT> GetMicrotaskQueueSize(TNode<RawPtrT> microtask_queue);
281cb0ef41Sopenharmony_ci  void SetMicrotaskQueueSize(TNode<RawPtrT> microtask_queue,
291cb0ef41Sopenharmony_ci                             TNode<IntPtrT> new_size);
301cb0ef41Sopenharmony_ci  TNode<IntPtrT> GetMicrotaskQueueStart(TNode<RawPtrT> microtask_queue);
311cb0ef41Sopenharmony_ci  void SetMicrotaskQueueStart(TNode<RawPtrT> microtask_queue,
321cb0ef41Sopenharmony_ci                              TNode<IntPtrT> new_start);
331cb0ef41Sopenharmony_ci  TNode<IntPtrT> CalculateRingBufferOffset(TNode<IntPtrT> capacity,
341cb0ef41Sopenharmony_ci                                           TNode<IntPtrT> start,
351cb0ef41Sopenharmony_ci                                           TNode<IntPtrT> index);
361cb0ef41Sopenharmony_ci
371cb0ef41Sopenharmony_ci  void PrepareForContext(TNode<Context> microtask_context, Label* bailout);
381cb0ef41Sopenharmony_ci  void RunSingleMicrotask(TNode<Context> current_context,
391cb0ef41Sopenharmony_ci                          TNode<Microtask> microtask);
401cb0ef41Sopenharmony_ci  void IncrementFinishedMicrotaskCount(TNode<RawPtrT> microtask_queue);
411cb0ef41Sopenharmony_ci
421cb0ef41Sopenharmony_ci  TNode<Context> GetCurrentContext();
431cb0ef41Sopenharmony_ci  void SetCurrentContext(TNode<Context> context);
441cb0ef41Sopenharmony_ci
451cb0ef41Sopenharmony_ci  TNode<IntPtrT> GetEnteredContextCount();
461cb0ef41Sopenharmony_ci  void EnterMicrotaskContext(TNode<Context> native_context);
471cb0ef41Sopenharmony_ci  void RewindEnteredContext(TNode<IntPtrT> saved_entered_context_count);
481cb0ef41Sopenharmony_ci
491cb0ef41Sopenharmony_ci  void RunAllPromiseHooks(PromiseHookType type, TNode<Context> context,
501cb0ef41Sopenharmony_ci                          TNode<HeapObject> promise_or_capability);
511cb0ef41Sopenharmony_ci  void RunPromiseHook(Runtime::FunctionId id, TNode<Context> context,
521cb0ef41Sopenharmony_ci                      TNode<HeapObject> promise_or_capability,
531cb0ef41Sopenharmony_ci                      TNode<Uint32T> promiseHookFlags);
541cb0ef41Sopenharmony_ci};
551cb0ef41Sopenharmony_ci
561cb0ef41Sopenharmony_ciTNode<RawPtrT> MicrotaskQueueBuiltinsAssembler::GetMicrotaskQueue(
571cb0ef41Sopenharmony_ci    TNode<Context> native_context) {
581cb0ef41Sopenharmony_ci  CSA_DCHECK(this, IsNativeContext(native_context));
591cb0ef41Sopenharmony_ci  return LoadExternalPointerFromObject(native_context,
601cb0ef41Sopenharmony_ci                                       NativeContext::kMicrotaskQueueOffset,
611cb0ef41Sopenharmony_ci                                       kNativeContextMicrotaskQueueTag);
621cb0ef41Sopenharmony_ci}
631cb0ef41Sopenharmony_ci
641cb0ef41Sopenharmony_ciTNode<RawPtrT> MicrotaskQueueBuiltinsAssembler::GetMicrotaskRingBuffer(
651cb0ef41Sopenharmony_ci    TNode<RawPtrT> microtask_queue) {
661cb0ef41Sopenharmony_ci  return Load<RawPtrT>(microtask_queue,
671cb0ef41Sopenharmony_ci                       IntPtrConstant(MicrotaskQueue::kRingBufferOffset));
681cb0ef41Sopenharmony_ci}
691cb0ef41Sopenharmony_ci
701cb0ef41Sopenharmony_ciTNode<IntPtrT> MicrotaskQueueBuiltinsAssembler::GetMicrotaskQueueCapacity(
711cb0ef41Sopenharmony_ci    TNode<RawPtrT> microtask_queue) {
721cb0ef41Sopenharmony_ci  return Load<IntPtrT>(microtask_queue,
731cb0ef41Sopenharmony_ci                       IntPtrConstant(MicrotaskQueue::kCapacityOffset));
741cb0ef41Sopenharmony_ci}
751cb0ef41Sopenharmony_ci
761cb0ef41Sopenharmony_ciTNode<IntPtrT> MicrotaskQueueBuiltinsAssembler::GetMicrotaskQueueSize(
771cb0ef41Sopenharmony_ci    TNode<RawPtrT> microtask_queue) {
781cb0ef41Sopenharmony_ci  return Load<IntPtrT>(microtask_queue,
791cb0ef41Sopenharmony_ci                       IntPtrConstant(MicrotaskQueue::kSizeOffset));
801cb0ef41Sopenharmony_ci}
811cb0ef41Sopenharmony_ci
821cb0ef41Sopenharmony_civoid MicrotaskQueueBuiltinsAssembler::SetMicrotaskQueueSize(
831cb0ef41Sopenharmony_ci    TNode<RawPtrT> microtask_queue, TNode<IntPtrT> new_size) {
841cb0ef41Sopenharmony_ci  StoreNoWriteBarrier(MachineType::PointerRepresentation(), microtask_queue,
851cb0ef41Sopenharmony_ci                      IntPtrConstant(MicrotaskQueue::kSizeOffset), new_size);
861cb0ef41Sopenharmony_ci}
871cb0ef41Sopenharmony_ci
881cb0ef41Sopenharmony_ciTNode<IntPtrT> MicrotaskQueueBuiltinsAssembler::GetMicrotaskQueueStart(
891cb0ef41Sopenharmony_ci    TNode<RawPtrT> microtask_queue) {
901cb0ef41Sopenharmony_ci  return Load<IntPtrT>(microtask_queue,
911cb0ef41Sopenharmony_ci                       IntPtrConstant(MicrotaskQueue::kStartOffset));
921cb0ef41Sopenharmony_ci}
931cb0ef41Sopenharmony_ci
941cb0ef41Sopenharmony_civoid MicrotaskQueueBuiltinsAssembler::SetMicrotaskQueueStart(
951cb0ef41Sopenharmony_ci    TNode<RawPtrT> microtask_queue, TNode<IntPtrT> new_start) {
961cb0ef41Sopenharmony_ci  StoreNoWriteBarrier(MachineType::PointerRepresentation(), microtask_queue,
971cb0ef41Sopenharmony_ci                      IntPtrConstant(MicrotaskQueue::kStartOffset), new_start);
981cb0ef41Sopenharmony_ci}
991cb0ef41Sopenharmony_ci
1001cb0ef41Sopenharmony_ciTNode<IntPtrT> MicrotaskQueueBuiltinsAssembler::CalculateRingBufferOffset(
1011cb0ef41Sopenharmony_ci    TNode<IntPtrT> capacity, TNode<IntPtrT> start, TNode<IntPtrT> index) {
1021cb0ef41Sopenharmony_ci  return TimesSystemPointerSize(
1031cb0ef41Sopenharmony_ci      WordAnd(IntPtrAdd(start, index), IntPtrSub(capacity, IntPtrConstant(1))));
1041cb0ef41Sopenharmony_ci}
1051cb0ef41Sopenharmony_ci
1061cb0ef41Sopenharmony_civoid MicrotaskQueueBuiltinsAssembler::PrepareForContext(
1071cb0ef41Sopenharmony_ci    TNode<Context> native_context, Label* bailout) {
1081cb0ef41Sopenharmony_ci  CSA_DCHECK(this, IsNativeContext(native_context));
1091cb0ef41Sopenharmony_ci
1101cb0ef41Sopenharmony_ci  // Skip the microtask execution if the associated context is shutdown.
1111cb0ef41Sopenharmony_ci  GotoIf(WordEqual(GetMicrotaskQueue(native_context), IntPtrConstant(0)),
1121cb0ef41Sopenharmony_ci         bailout);
1131cb0ef41Sopenharmony_ci
1141cb0ef41Sopenharmony_ci  EnterMicrotaskContext(native_context);
1151cb0ef41Sopenharmony_ci  SetCurrentContext(native_context);
1161cb0ef41Sopenharmony_ci}
1171cb0ef41Sopenharmony_ci
1181cb0ef41Sopenharmony_civoid MicrotaskQueueBuiltinsAssembler::RunSingleMicrotask(
1191cb0ef41Sopenharmony_ci    TNode<Context> current_context, TNode<Microtask> microtask) {
1201cb0ef41Sopenharmony_ci  CSA_DCHECK(this, TaggedIsNotSmi(microtask));
1211cb0ef41Sopenharmony_ci
1221cb0ef41Sopenharmony_ci  StoreRoot(RootIndex::kCurrentMicrotask, microtask);
1231cb0ef41Sopenharmony_ci  TNode<IntPtrT> saved_entered_context_count = GetEnteredContextCount();
1241cb0ef41Sopenharmony_ci  TNode<Map> microtask_map = LoadMap(microtask);
1251cb0ef41Sopenharmony_ci  TNode<Uint16T> microtask_type = LoadMapInstanceType(microtask_map);
1261cb0ef41Sopenharmony_ci
1271cb0ef41Sopenharmony_ci  TVARIABLE(Object, var_exception);
1281cb0ef41Sopenharmony_ci  Label if_exception(this, Label::kDeferred);
1291cb0ef41Sopenharmony_ci  Label is_callable(this), is_callback(this),
1301cb0ef41Sopenharmony_ci      is_promise_fulfill_reaction_job(this),
1311cb0ef41Sopenharmony_ci      is_promise_reject_reaction_job(this),
1321cb0ef41Sopenharmony_ci      is_promise_resolve_thenable_job(this),
1331cb0ef41Sopenharmony_ci      is_unreachable(this, Label::kDeferred), done(this);
1341cb0ef41Sopenharmony_ci
1351cb0ef41Sopenharmony_ci  int32_t case_values[] = {CALLABLE_TASK_TYPE, CALLBACK_TASK_TYPE,
1361cb0ef41Sopenharmony_ci                           PROMISE_FULFILL_REACTION_JOB_TASK_TYPE,
1371cb0ef41Sopenharmony_ci                           PROMISE_REJECT_REACTION_JOB_TASK_TYPE,
1381cb0ef41Sopenharmony_ci                           PROMISE_RESOLVE_THENABLE_JOB_TASK_TYPE};
1391cb0ef41Sopenharmony_ci  Label* case_labels[] = {
1401cb0ef41Sopenharmony_ci      &is_callable, &is_callback, &is_promise_fulfill_reaction_job,
1411cb0ef41Sopenharmony_ci      &is_promise_reject_reaction_job, &is_promise_resolve_thenable_job};
1421cb0ef41Sopenharmony_ci  static_assert(arraysize(case_values) == arraysize(case_labels), "");
1431cb0ef41Sopenharmony_ci  Switch(microtask_type, &is_unreachable, case_values, case_labels,
1441cb0ef41Sopenharmony_ci         arraysize(case_labels));
1451cb0ef41Sopenharmony_ci
1461cb0ef41Sopenharmony_ci  BIND(&is_callable);
1471cb0ef41Sopenharmony_ci  {
1481cb0ef41Sopenharmony_ci    // Enter the context of the {microtask}.
1491cb0ef41Sopenharmony_ci    TNode<Context> microtask_context =
1501cb0ef41Sopenharmony_ci        LoadObjectField<Context>(microtask, CallableTask::kContextOffset);
1511cb0ef41Sopenharmony_ci    TNode<NativeContext> native_context = LoadNativeContext(microtask_context);
1521cb0ef41Sopenharmony_ci    PrepareForContext(native_context, &done);
1531cb0ef41Sopenharmony_ci
1541cb0ef41Sopenharmony_ci    TNode<JSReceiver> callable =
1551cb0ef41Sopenharmony_ci        LoadObjectField<JSReceiver>(microtask, CallableTask::kCallableOffset);
1561cb0ef41Sopenharmony_ci    {
1571cb0ef41Sopenharmony_ci      ScopedExceptionHandler handler(this, &if_exception, &var_exception);
1581cb0ef41Sopenharmony_ci      Call(microtask_context, callable, UndefinedConstant());
1591cb0ef41Sopenharmony_ci    }
1601cb0ef41Sopenharmony_ci    RewindEnteredContext(saved_entered_context_count);
1611cb0ef41Sopenharmony_ci    SetCurrentContext(current_context);
1621cb0ef41Sopenharmony_ci    Goto(&done);
1631cb0ef41Sopenharmony_ci  }
1641cb0ef41Sopenharmony_ci
1651cb0ef41Sopenharmony_ci  BIND(&is_callback);
1661cb0ef41Sopenharmony_ci  {
1671cb0ef41Sopenharmony_ci    const TNode<Object> microtask_callback =
1681cb0ef41Sopenharmony_ci        LoadObjectField(microtask, CallbackTask::kCallbackOffset);
1691cb0ef41Sopenharmony_ci    const TNode<Object> microtask_data =
1701cb0ef41Sopenharmony_ci        LoadObjectField(microtask, CallbackTask::kDataOffset);
1711cb0ef41Sopenharmony_ci
1721cb0ef41Sopenharmony_ci    // If this turns out to become a bottleneck because of the calls
1731cb0ef41Sopenharmony_ci    // to C++ via CEntry, we can choose to speed them up using a
1741cb0ef41Sopenharmony_ci    // similar mechanism that we use for the CallApiFunction stub,
1751cb0ef41Sopenharmony_ci    // except that calling the MicrotaskCallback is even easier, since
1761cb0ef41Sopenharmony_ci    // it doesn't accept any tagged parameters, doesn't return a value
1771cb0ef41Sopenharmony_ci    // and ignores exceptions.
1781cb0ef41Sopenharmony_ci    //
1791cb0ef41Sopenharmony_ci    // But from our current measurements it doesn't seem to be a
1801cb0ef41Sopenharmony_ci    // serious performance problem, even if the microtask is full
1811cb0ef41Sopenharmony_ci    // of CallHandlerTasks (which is not a realistic use case anyways).
1821cb0ef41Sopenharmony_ci    {
1831cb0ef41Sopenharmony_ci      ScopedExceptionHandler handler(this, &if_exception, &var_exception);
1841cb0ef41Sopenharmony_ci      CallRuntime(Runtime::kRunMicrotaskCallback, current_context,
1851cb0ef41Sopenharmony_ci                  microtask_callback, microtask_data);
1861cb0ef41Sopenharmony_ci    }
1871cb0ef41Sopenharmony_ci    Goto(&done);
1881cb0ef41Sopenharmony_ci  }
1891cb0ef41Sopenharmony_ci
1901cb0ef41Sopenharmony_ci  BIND(&is_promise_resolve_thenable_job);
1911cb0ef41Sopenharmony_ci  {
1921cb0ef41Sopenharmony_ci    // Enter the context of the {microtask}.
1931cb0ef41Sopenharmony_ci    TNode<Context> microtask_context = LoadObjectField<Context>(
1941cb0ef41Sopenharmony_ci        microtask, PromiseResolveThenableJobTask::kContextOffset);
1951cb0ef41Sopenharmony_ci    TNode<NativeContext> native_context = LoadNativeContext(microtask_context);
1961cb0ef41Sopenharmony_ci    PrepareForContext(native_context, &done);
1971cb0ef41Sopenharmony_ci
1981cb0ef41Sopenharmony_ci    const TNode<Object> promise_to_resolve = LoadObjectField(
1991cb0ef41Sopenharmony_ci        microtask, PromiseResolveThenableJobTask::kPromiseToResolveOffset);
2001cb0ef41Sopenharmony_ci    const TNode<Object> then =
2011cb0ef41Sopenharmony_ci        LoadObjectField(microtask, PromiseResolveThenableJobTask::kThenOffset);
2021cb0ef41Sopenharmony_ci    const TNode<Object> thenable = LoadObjectField(
2031cb0ef41Sopenharmony_ci        microtask, PromiseResolveThenableJobTask::kThenableOffset);
2041cb0ef41Sopenharmony_ci
2051cb0ef41Sopenharmony_ci    RunAllPromiseHooks(PromiseHookType::kBefore, microtask_context,
2061cb0ef41Sopenharmony_ci                   CAST(promise_to_resolve));
2071cb0ef41Sopenharmony_ci
2081cb0ef41Sopenharmony_ci    {
2091cb0ef41Sopenharmony_ci      ScopedExceptionHandler handler(this, &if_exception, &var_exception);
2101cb0ef41Sopenharmony_ci      CallBuiltin(Builtin::kPromiseResolveThenableJob, native_context,
2111cb0ef41Sopenharmony_ci                  promise_to_resolve, thenable, then);
2121cb0ef41Sopenharmony_ci    }
2131cb0ef41Sopenharmony_ci
2141cb0ef41Sopenharmony_ci    RunAllPromiseHooks(PromiseHookType::kAfter, microtask_context,
2151cb0ef41Sopenharmony_ci                   CAST(promise_to_resolve));
2161cb0ef41Sopenharmony_ci
2171cb0ef41Sopenharmony_ci    RewindEnteredContext(saved_entered_context_count);
2181cb0ef41Sopenharmony_ci    SetCurrentContext(current_context);
2191cb0ef41Sopenharmony_ci    Goto(&done);
2201cb0ef41Sopenharmony_ci  }
2211cb0ef41Sopenharmony_ci
2221cb0ef41Sopenharmony_ci  BIND(&is_promise_fulfill_reaction_job);
2231cb0ef41Sopenharmony_ci  {
2241cb0ef41Sopenharmony_ci    // Enter the context of the {microtask}.
2251cb0ef41Sopenharmony_ci    TNode<Context> microtask_context = LoadObjectField<Context>(
2261cb0ef41Sopenharmony_ci        microtask, PromiseReactionJobTask::kContextOffset);
2271cb0ef41Sopenharmony_ci    TNode<NativeContext> native_context = LoadNativeContext(microtask_context);
2281cb0ef41Sopenharmony_ci    PrepareForContext(native_context, &done);
2291cb0ef41Sopenharmony_ci
2301cb0ef41Sopenharmony_ci    const TNode<Object> argument =
2311cb0ef41Sopenharmony_ci        LoadObjectField(microtask, PromiseReactionJobTask::kArgumentOffset);
2321cb0ef41Sopenharmony_ci    const TNode<Object> job_handler =
2331cb0ef41Sopenharmony_ci        LoadObjectField(microtask, PromiseReactionJobTask::kHandlerOffset);
2341cb0ef41Sopenharmony_ci    const TNode<HeapObject> promise_or_capability = CAST(LoadObjectField(
2351cb0ef41Sopenharmony_ci        microtask, PromiseReactionJobTask::kPromiseOrCapabilityOffset));
2361cb0ef41Sopenharmony_ci
2371cb0ef41Sopenharmony_ci    TNode<Object> preserved_embedder_data = LoadObjectField(
2381cb0ef41Sopenharmony_ci        microtask,
2391cb0ef41Sopenharmony_ci        PromiseReactionJobTask::kContinuationPreservedEmbedderDataOffset);
2401cb0ef41Sopenharmony_ci    Label preserved_data_done(this);
2411cb0ef41Sopenharmony_ci    GotoIf(IsUndefined(preserved_embedder_data), &preserved_data_done);
2421cb0ef41Sopenharmony_ci    StoreContextElement(native_context,
2431cb0ef41Sopenharmony_ci                        Context::CONTINUATION_PRESERVED_EMBEDDER_DATA_INDEX,
2441cb0ef41Sopenharmony_ci                        preserved_embedder_data);
2451cb0ef41Sopenharmony_ci    Goto(&preserved_data_done);
2461cb0ef41Sopenharmony_ci    BIND(&preserved_data_done);
2471cb0ef41Sopenharmony_ci
2481cb0ef41Sopenharmony_ci    // Run the promise before/debug hook if enabled.
2491cb0ef41Sopenharmony_ci    RunAllPromiseHooks(PromiseHookType::kBefore, microtask_context,
2501cb0ef41Sopenharmony_ci                       promise_or_capability);
2511cb0ef41Sopenharmony_ci
2521cb0ef41Sopenharmony_ci    {
2531cb0ef41Sopenharmony_ci      ScopedExceptionHandler handler(this, &if_exception, &var_exception);
2541cb0ef41Sopenharmony_ci      CallBuiltin(Builtin::kPromiseFulfillReactionJob, microtask_context,
2551cb0ef41Sopenharmony_ci                  argument, job_handler, promise_or_capability);
2561cb0ef41Sopenharmony_ci    }
2571cb0ef41Sopenharmony_ci
2581cb0ef41Sopenharmony_ci    // Run the promise after/debug hook if enabled.
2591cb0ef41Sopenharmony_ci    RunAllPromiseHooks(PromiseHookType::kAfter, microtask_context,
2601cb0ef41Sopenharmony_ci                       promise_or_capability);
2611cb0ef41Sopenharmony_ci
2621cb0ef41Sopenharmony_ci    Label preserved_data_reset_done(this);
2631cb0ef41Sopenharmony_ci    GotoIf(IsUndefined(preserved_embedder_data), &preserved_data_reset_done);
2641cb0ef41Sopenharmony_ci    StoreContextElement(native_context,
2651cb0ef41Sopenharmony_ci                        Context::CONTINUATION_PRESERVED_EMBEDDER_DATA_INDEX,
2661cb0ef41Sopenharmony_ci                        UndefinedConstant());
2671cb0ef41Sopenharmony_ci    Goto(&preserved_data_reset_done);
2681cb0ef41Sopenharmony_ci    BIND(&preserved_data_reset_done);
2691cb0ef41Sopenharmony_ci
2701cb0ef41Sopenharmony_ci    RewindEnteredContext(saved_entered_context_count);
2711cb0ef41Sopenharmony_ci    SetCurrentContext(current_context);
2721cb0ef41Sopenharmony_ci    Goto(&done);
2731cb0ef41Sopenharmony_ci  }
2741cb0ef41Sopenharmony_ci
2751cb0ef41Sopenharmony_ci  BIND(&is_promise_reject_reaction_job);
2761cb0ef41Sopenharmony_ci  {
2771cb0ef41Sopenharmony_ci    // Enter the context of the {microtask}.
2781cb0ef41Sopenharmony_ci    TNode<Context> microtask_context = LoadObjectField<Context>(
2791cb0ef41Sopenharmony_ci        microtask, PromiseReactionJobTask::kContextOffset);
2801cb0ef41Sopenharmony_ci    TNode<NativeContext> native_context = LoadNativeContext(microtask_context);
2811cb0ef41Sopenharmony_ci    PrepareForContext(native_context, &done);
2821cb0ef41Sopenharmony_ci
2831cb0ef41Sopenharmony_ci    const TNode<Object> argument =
2841cb0ef41Sopenharmony_ci        LoadObjectField(microtask, PromiseReactionJobTask::kArgumentOffset);
2851cb0ef41Sopenharmony_ci    const TNode<Object> job_handler =
2861cb0ef41Sopenharmony_ci        LoadObjectField(microtask, PromiseReactionJobTask::kHandlerOffset);
2871cb0ef41Sopenharmony_ci    const TNode<HeapObject> promise_or_capability = CAST(LoadObjectField(
2881cb0ef41Sopenharmony_ci        microtask, PromiseReactionJobTask::kPromiseOrCapabilityOffset));
2891cb0ef41Sopenharmony_ci
2901cb0ef41Sopenharmony_ci    TNode<Object> preserved_embedder_data = LoadObjectField(
2911cb0ef41Sopenharmony_ci        microtask,
2921cb0ef41Sopenharmony_ci        PromiseReactionJobTask::kContinuationPreservedEmbedderDataOffset);
2931cb0ef41Sopenharmony_ci    Label preserved_data_done(this);
2941cb0ef41Sopenharmony_ci    GotoIf(IsUndefined(preserved_embedder_data), &preserved_data_done);
2951cb0ef41Sopenharmony_ci    StoreContextElement(native_context,
2961cb0ef41Sopenharmony_ci                        Context::CONTINUATION_PRESERVED_EMBEDDER_DATA_INDEX,
2971cb0ef41Sopenharmony_ci                        preserved_embedder_data);
2981cb0ef41Sopenharmony_ci    Goto(&preserved_data_done);
2991cb0ef41Sopenharmony_ci    BIND(&preserved_data_done);
3001cb0ef41Sopenharmony_ci
3011cb0ef41Sopenharmony_ci    // Run the promise before/debug hook if enabled.
3021cb0ef41Sopenharmony_ci    RunAllPromiseHooks(PromiseHookType::kBefore, microtask_context,
3031cb0ef41Sopenharmony_ci                       promise_or_capability);
3041cb0ef41Sopenharmony_ci
3051cb0ef41Sopenharmony_ci    {
3061cb0ef41Sopenharmony_ci      ScopedExceptionHandler handler(this, &if_exception, &var_exception);
3071cb0ef41Sopenharmony_ci      CallBuiltin(Builtin::kPromiseRejectReactionJob, microtask_context,
3081cb0ef41Sopenharmony_ci                  argument, job_handler, promise_or_capability);
3091cb0ef41Sopenharmony_ci    }
3101cb0ef41Sopenharmony_ci
3111cb0ef41Sopenharmony_ci    // Run the promise after/debug hook if enabled.
3121cb0ef41Sopenharmony_ci    RunAllPromiseHooks(PromiseHookType::kAfter, microtask_context,
3131cb0ef41Sopenharmony_ci                       promise_or_capability);
3141cb0ef41Sopenharmony_ci
3151cb0ef41Sopenharmony_ci    Label preserved_data_reset_done(this);
3161cb0ef41Sopenharmony_ci    GotoIf(IsUndefined(preserved_embedder_data), &preserved_data_reset_done);
3171cb0ef41Sopenharmony_ci    StoreContextElement(native_context,
3181cb0ef41Sopenharmony_ci                        Context::CONTINUATION_PRESERVED_EMBEDDER_DATA_INDEX,
3191cb0ef41Sopenharmony_ci                        UndefinedConstant());
3201cb0ef41Sopenharmony_ci    Goto(&preserved_data_reset_done);
3211cb0ef41Sopenharmony_ci    BIND(&preserved_data_reset_done);
3221cb0ef41Sopenharmony_ci
3231cb0ef41Sopenharmony_ci    RewindEnteredContext(saved_entered_context_count);
3241cb0ef41Sopenharmony_ci    SetCurrentContext(current_context);
3251cb0ef41Sopenharmony_ci    Goto(&done);
3261cb0ef41Sopenharmony_ci  }
3271cb0ef41Sopenharmony_ci
3281cb0ef41Sopenharmony_ci  BIND(&is_unreachable);
3291cb0ef41Sopenharmony_ci  Unreachable();
3301cb0ef41Sopenharmony_ci
3311cb0ef41Sopenharmony_ci  BIND(&if_exception);
3321cb0ef41Sopenharmony_ci  {
3331cb0ef41Sopenharmony_ci    // Report unhandled exceptions from microtasks.
3341cb0ef41Sopenharmony_ci    CallRuntime(Runtime::kReportMessageFromMicrotask, GetCurrentContext(),
3351cb0ef41Sopenharmony_ci                var_exception.value());
3361cb0ef41Sopenharmony_ci    RewindEnteredContext(saved_entered_context_count);
3371cb0ef41Sopenharmony_ci    SetCurrentContext(current_context);
3381cb0ef41Sopenharmony_ci    Goto(&done);
3391cb0ef41Sopenharmony_ci  }
3401cb0ef41Sopenharmony_ci
3411cb0ef41Sopenharmony_ci  BIND(&done);
3421cb0ef41Sopenharmony_ci}
3431cb0ef41Sopenharmony_ci
3441cb0ef41Sopenharmony_civoid MicrotaskQueueBuiltinsAssembler::IncrementFinishedMicrotaskCount(
3451cb0ef41Sopenharmony_ci    TNode<RawPtrT> microtask_queue) {
3461cb0ef41Sopenharmony_ci  TNode<IntPtrT> count = Load<IntPtrT>(
3471cb0ef41Sopenharmony_ci      microtask_queue,
3481cb0ef41Sopenharmony_ci      IntPtrConstant(MicrotaskQueue::kFinishedMicrotaskCountOffset));
3491cb0ef41Sopenharmony_ci  TNode<IntPtrT> new_count = IntPtrAdd(count, IntPtrConstant(1));
3501cb0ef41Sopenharmony_ci  StoreNoWriteBarrier(
3511cb0ef41Sopenharmony_ci      MachineType::PointerRepresentation(), microtask_queue,
3521cb0ef41Sopenharmony_ci      IntPtrConstant(MicrotaskQueue::kFinishedMicrotaskCountOffset), new_count);
3531cb0ef41Sopenharmony_ci}
3541cb0ef41Sopenharmony_ci
3551cb0ef41Sopenharmony_ciTNode<Context> MicrotaskQueueBuiltinsAssembler::GetCurrentContext() {
3561cb0ef41Sopenharmony_ci  auto ref = ExternalReference::Create(kContextAddress, isolate());
3571cb0ef41Sopenharmony_ci  // TODO(delphick): Add a checked cast. For now this is not possible as context
3581cb0ef41Sopenharmony_ci  // can actually be Smi(0).
3591cb0ef41Sopenharmony_ci  return TNode<Context>::UncheckedCast(LoadFullTagged(ExternalConstant(ref)));
3601cb0ef41Sopenharmony_ci}
3611cb0ef41Sopenharmony_ci
3621cb0ef41Sopenharmony_civoid MicrotaskQueueBuiltinsAssembler::SetCurrentContext(
3631cb0ef41Sopenharmony_ci    TNode<Context> context) {
3641cb0ef41Sopenharmony_ci  auto ref = ExternalReference::Create(kContextAddress, isolate());
3651cb0ef41Sopenharmony_ci  StoreFullTaggedNoWriteBarrier(ExternalConstant(ref), context);
3661cb0ef41Sopenharmony_ci}
3671cb0ef41Sopenharmony_ci
3681cb0ef41Sopenharmony_ciTNode<IntPtrT> MicrotaskQueueBuiltinsAssembler::GetEnteredContextCount() {
3691cb0ef41Sopenharmony_ci  auto ref = ExternalReference::handle_scope_implementer_address(isolate());
3701cb0ef41Sopenharmony_ci  TNode<RawPtrT> hsi = Load<RawPtrT>(ExternalConstant(ref));
3711cb0ef41Sopenharmony_ci
3721cb0ef41Sopenharmony_ci  using ContextStack = DetachableVector<Context>;
3731cb0ef41Sopenharmony_ci  TNode<IntPtrT> size_offset =
3741cb0ef41Sopenharmony_ci      IntPtrConstant(HandleScopeImplementer::kEnteredContextsOffset +
3751cb0ef41Sopenharmony_ci                     ContextStack::kSizeOffset);
3761cb0ef41Sopenharmony_ci  return Load<IntPtrT>(hsi, size_offset);
3771cb0ef41Sopenharmony_ci}
3781cb0ef41Sopenharmony_ci
3791cb0ef41Sopenharmony_civoid MicrotaskQueueBuiltinsAssembler::EnterMicrotaskContext(
3801cb0ef41Sopenharmony_ci    TNode<Context> native_context) {
3811cb0ef41Sopenharmony_ci  CSA_DCHECK(this, IsNativeContext(native_context));
3821cb0ef41Sopenharmony_ci
3831cb0ef41Sopenharmony_ci  auto ref = ExternalReference::handle_scope_implementer_address(isolate());
3841cb0ef41Sopenharmony_ci  TNode<RawPtrT> hsi = Load<RawPtrT>(ExternalConstant(ref));
3851cb0ef41Sopenharmony_ci
3861cb0ef41Sopenharmony_ci  using ContextStack = DetachableVector<Context>;
3871cb0ef41Sopenharmony_ci  TNode<IntPtrT> capacity_offset =
3881cb0ef41Sopenharmony_ci      IntPtrConstant(HandleScopeImplementer::kEnteredContextsOffset +
3891cb0ef41Sopenharmony_ci                     ContextStack::kCapacityOffset);
3901cb0ef41Sopenharmony_ci  TNode<IntPtrT> size_offset =
3911cb0ef41Sopenharmony_ci      IntPtrConstant(HandleScopeImplementer::kEnteredContextsOffset +
3921cb0ef41Sopenharmony_ci                     ContextStack::kSizeOffset);
3931cb0ef41Sopenharmony_ci
3941cb0ef41Sopenharmony_ci  TNode<IntPtrT> capacity = Load<IntPtrT>(hsi, capacity_offset);
3951cb0ef41Sopenharmony_ci  TNode<IntPtrT> size = Load<IntPtrT>(hsi, size_offset);
3961cb0ef41Sopenharmony_ci
3971cb0ef41Sopenharmony_ci  Label if_append(this), if_grow(this, Label::kDeferred), done(this);
3981cb0ef41Sopenharmony_ci  Branch(WordEqual(size, capacity), &if_grow, &if_append);
3991cb0ef41Sopenharmony_ci  BIND(&if_append);
4001cb0ef41Sopenharmony_ci  {
4011cb0ef41Sopenharmony_ci    TNode<IntPtrT> data_offset =
4021cb0ef41Sopenharmony_ci        IntPtrConstant(HandleScopeImplementer::kEnteredContextsOffset +
4031cb0ef41Sopenharmony_ci                       ContextStack::kDataOffset);
4041cb0ef41Sopenharmony_ci    TNode<RawPtrT> data = Load<RawPtrT>(hsi, data_offset);
4051cb0ef41Sopenharmony_ci    StoreFullTaggedNoWriteBarrier(data, TimesSystemPointerSize(size),
4061cb0ef41Sopenharmony_ci                                  native_context);
4071cb0ef41Sopenharmony_ci
4081cb0ef41Sopenharmony_ci    TNode<IntPtrT> new_size = IntPtrAdd(size, IntPtrConstant(1));
4091cb0ef41Sopenharmony_ci    StoreNoWriteBarrier(MachineType::PointerRepresentation(), hsi, size_offset,
4101cb0ef41Sopenharmony_ci                        new_size);
4111cb0ef41Sopenharmony_ci
4121cb0ef41Sopenharmony_ci    using FlagStack = DetachableVector<int8_t>;
4131cb0ef41Sopenharmony_ci    TNode<IntPtrT> flag_data_offset =
4141cb0ef41Sopenharmony_ci        IntPtrConstant(HandleScopeImplementer::kIsMicrotaskContextOffset +
4151cb0ef41Sopenharmony_ci                       FlagStack::kDataOffset);
4161cb0ef41Sopenharmony_ci    TNode<IntPtrT> flag_capacity_offset =
4171cb0ef41Sopenharmony_ci        IntPtrConstant(HandleScopeImplementer::kIsMicrotaskContextOffset +
4181cb0ef41Sopenharmony_ci                       FlagStack::kCapacityOffset);
4191cb0ef41Sopenharmony_ci    TNode<IntPtrT> flag_size_offset =
4201cb0ef41Sopenharmony_ci        IntPtrConstant(HandleScopeImplementer::kIsMicrotaskContextOffset +
4211cb0ef41Sopenharmony_ci                       FlagStack::kSizeOffset);
4221cb0ef41Sopenharmony_ci    // Ensure both stacks are in sync.
4231cb0ef41Sopenharmony_ci    USE(flag_capacity_offset);
4241cb0ef41Sopenharmony_ci    CSA_DCHECK(this,
4251cb0ef41Sopenharmony_ci               WordEqual(capacity, Load<IntPtrT>(hsi, flag_capacity_offset)));
4261cb0ef41Sopenharmony_ci    CSA_DCHECK(this, WordEqual(size, Load<IntPtrT>(hsi, flag_size_offset)));
4271cb0ef41Sopenharmony_ci
4281cb0ef41Sopenharmony_ci    TNode<RawPtrT> flag_data = Load<RawPtrT>(hsi, flag_data_offset);
4291cb0ef41Sopenharmony_ci    StoreNoWriteBarrier(MachineRepresentation::kWord8, flag_data, size,
4301cb0ef41Sopenharmony_ci                        BoolConstant(true));
4311cb0ef41Sopenharmony_ci    StoreNoWriteBarrier(MachineType::PointerRepresentation(), hsi,
4321cb0ef41Sopenharmony_ci                        flag_size_offset, new_size);
4331cb0ef41Sopenharmony_ci
4341cb0ef41Sopenharmony_ci    Goto(&done);
4351cb0ef41Sopenharmony_ci  }
4361cb0ef41Sopenharmony_ci
4371cb0ef41Sopenharmony_ci  BIND(&if_grow);
4381cb0ef41Sopenharmony_ci  {
4391cb0ef41Sopenharmony_ci    TNode<ExternalReference> function =
4401cb0ef41Sopenharmony_ci        ExternalConstant(ExternalReference::call_enter_context_function());
4411cb0ef41Sopenharmony_ci    CallCFunction(function, MachineType::Int32(),
4421cb0ef41Sopenharmony_ci                  std::make_pair(MachineType::Pointer(), hsi),
4431cb0ef41Sopenharmony_ci                  std::make_pair(MachineType::Pointer(),
4441cb0ef41Sopenharmony_ci                                 BitcastTaggedToWord(native_context)));
4451cb0ef41Sopenharmony_ci    Goto(&done);
4461cb0ef41Sopenharmony_ci  }
4471cb0ef41Sopenharmony_ci
4481cb0ef41Sopenharmony_ci  BIND(&done);
4491cb0ef41Sopenharmony_ci}
4501cb0ef41Sopenharmony_ci
4511cb0ef41Sopenharmony_civoid MicrotaskQueueBuiltinsAssembler::RewindEnteredContext(
4521cb0ef41Sopenharmony_ci    TNode<IntPtrT> saved_entered_context_count) {
4531cb0ef41Sopenharmony_ci  auto ref = ExternalReference::handle_scope_implementer_address(isolate());
4541cb0ef41Sopenharmony_ci  TNode<RawPtrT> hsi = Load<RawPtrT>(ExternalConstant(ref));
4551cb0ef41Sopenharmony_ci
4561cb0ef41Sopenharmony_ci  using ContextStack = DetachableVector<Context>;
4571cb0ef41Sopenharmony_ci  TNode<IntPtrT> size_offset =
4581cb0ef41Sopenharmony_ci      IntPtrConstant(HandleScopeImplementer::kEnteredContextsOffset +
4591cb0ef41Sopenharmony_ci                     ContextStack::kSizeOffset);
4601cb0ef41Sopenharmony_ci
4611cb0ef41Sopenharmony_ci  if (DEBUG_BOOL) {
4621cb0ef41Sopenharmony_ci    TNode<IntPtrT> size = Load<IntPtrT>(hsi, size_offset);
4631cb0ef41Sopenharmony_ci    CSA_CHECK(this, IntPtrLessThan(IntPtrConstant(0), size));
4641cb0ef41Sopenharmony_ci    CSA_CHECK(this, IntPtrLessThanOrEqual(saved_entered_context_count, size));
4651cb0ef41Sopenharmony_ci  }
4661cb0ef41Sopenharmony_ci
4671cb0ef41Sopenharmony_ci  StoreNoWriteBarrier(MachineType::PointerRepresentation(), hsi, size_offset,
4681cb0ef41Sopenharmony_ci                      saved_entered_context_count);
4691cb0ef41Sopenharmony_ci
4701cb0ef41Sopenharmony_ci  using FlagStack = DetachableVector<int8_t>;
4711cb0ef41Sopenharmony_ci  StoreNoWriteBarrier(
4721cb0ef41Sopenharmony_ci      MachineType::PointerRepresentation(), hsi,
4731cb0ef41Sopenharmony_ci      IntPtrConstant(HandleScopeImplementer::kIsMicrotaskContextOffset +
4741cb0ef41Sopenharmony_ci                     FlagStack::kSizeOffset),
4751cb0ef41Sopenharmony_ci      saved_entered_context_count);
4761cb0ef41Sopenharmony_ci}
4771cb0ef41Sopenharmony_ci
4781cb0ef41Sopenharmony_civoid MicrotaskQueueBuiltinsAssembler::RunAllPromiseHooks(
4791cb0ef41Sopenharmony_ci    PromiseHookType type, TNode<Context> context,
4801cb0ef41Sopenharmony_ci    TNode<HeapObject> promise_or_capability) {
4811cb0ef41Sopenharmony_ci  TNode<Uint32T> promiseHookFlags = PromiseHookFlags();
4821cb0ef41Sopenharmony_ci#ifdef V8_ENABLE_JAVASCRIPT_PROMISE_HOOKS
4831cb0ef41Sopenharmony_ci  Label hook(this, Label::kDeferred), done_hook(this);
4841cb0ef41Sopenharmony_ci  Branch(NeedsAnyPromiseHooks(promiseHookFlags), &hook, &done_hook);
4851cb0ef41Sopenharmony_ci  BIND(&hook);
4861cb0ef41Sopenharmony_ci  {
4871cb0ef41Sopenharmony_ci#endif
4881cb0ef41Sopenharmony_ci    switch (type) {
4891cb0ef41Sopenharmony_ci      case PromiseHookType::kBefore:
4901cb0ef41Sopenharmony_ci#ifdef V8_ENABLE_JAVASCRIPT_PROMISE_HOOKS
4911cb0ef41Sopenharmony_ci        RunContextPromiseHookBefore(context, promise_or_capability,
4921cb0ef41Sopenharmony_ci                                    promiseHookFlags);
4931cb0ef41Sopenharmony_ci#endif
4941cb0ef41Sopenharmony_ci        RunPromiseHook(Runtime::kPromiseHookBefore, context,
4951cb0ef41Sopenharmony_ci                       promise_or_capability, promiseHookFlags);
4961cb0ef41Sopenharmony_ci        break;
4971cb0ef41Sopenharmony_ci      case PromiseHookType::kAfter:
4981cb0ef41Sopenharmony_ci#ifdef V8_ENABLE_JAVASCRIPT_PROMISE_HOOKS
4991cb0ef41Sopenharmony_ci        RunContextPromiseHookAfter(context, promise_or_capability,
5001cb0ef41Sopenharmony_ci                                   promiseHookFlags);
5011cb0ef41Sopenharmony_ci#endif
5021cb0ef41Sopenharmony_ci        RunPromiseHook(Runtime::kPromiseHookAfter, context,
5031cb0ef41Sopenharmony_ci                       promise_or_capability, promiseHookFlags);
5041cb0ef41Sopenharmony_ci        break;
5051cb0ef41Sopenharmony_ci      default:
5061cb0ef41Sopenharmony_ci        UNREACHABLE();
5071cb0ef41Sopenharmony_ci    }
5081cb0ef41Sopenharmony_ci#ifdef V8_ENABLE_JAVASCRIPT_PROMISE_HOOKS
5091cb0ef41Sopenharmony_ci    Goto(&done_hook);
5101cb0ef41Sopenharmony_ci  }
5111cb0ef41Sopenharmony_ci  BIND(&done_hook);
5121cb0ef41Sopenharmony_ci#endif
5131cb0ef41Sopenharmony_ci}
5141cb0ef41Sopenharmony_ci
5151cb0ef41Sopenharmony_civoid MicrotaskQueueBuiltinsAssembler::RunPromiseHook(
5161cb0ef41Sopenharmony_ci    Runtime::FunctionId id, TNode<Context> context,
5171cb0ef41Sopenharmony_ci    TNode<HeapObject> promise_or_capability,
5181cb0ef41Sopenharmony_ci    TNode<Uint32T> promiseHookFlags) {
5191cb0ef41Sopenharmony_ci  Label hook(this, Label::kDeferred), done_hook(this);
5201cb0ef41Sopenharmony_ci  Branch(IsIsolatePromiseHookEnabledOrDebugIsActiveOrHasAsyncEventDelegate(
5211cb0ef41Sopenharmony_ci      promiseHookFlags), &hook, &done_hook);
5221cb0ef41Sopenharmony_ci  BIND(&hook);
5231cb0ef41Sopenharmony_ci  {
5241cb0ef41Sopenharmony_ci    // Get to the underlying JSPromise instance.
5251cb0ef41Sopenharmony_ci    TNode<HeapObject> promise = Select<HeapObject>(
5261cb0ef41Sopenharmony_ci        IsPromiseCapability(promise_or_capability),
5271cb0ef41Sopenharmony_ci        [=] {
5281cb0ef41Sopenharmony_ci          return CAST(LoadObjectField(promise_or_capability,
5291cb0ef41Sopenharmony_ci                                      PromiseCapability::kPromiseOffset));
5301cb0ef41Sopenharmony_ci        },
5311cb0ef41Sopenharmony_ci
5321cb0ef41Sopenharmony_ci        [=] { return promise_or_capability; });
5331cb0ef41Sopenharmony_ci    GotoIf(IsUndefined(promise), &done_hook);
5341cb0ef41Sopenharmony_ci    CallRuntime(id, context, promise);
5351cb0ef41Sopenharmony_ci    Goto(&done_hook);
5361cb0ef41Sopenharmony_ci  }
5371cb0ef41Sopenharmony_ci  BIND(&done_hook);
5381cb0ef41Sopenharmony_ci}
5391cb0ef41Sopenharmony_ci
5401cb0ef41Sopenharmony_ciTF_BUILTIN(EnqueueMicrotask, MicrotaskQueueBuiltinsAssembler) {
5411cb0ef41Sopenharmony_ci  auto microtask = Parameter<Microtask>(Descriptor::kMicrotask);
5421cb0ef41Sopenharmony_ci  auto context = Parameter<Context>(Descriptor::kContext);
5431cb0ef41Sopenharmony_ci  TNode<NativeContext> native_context = LoadNativeContext(context);
5441cb0ef41Sopenharmony_ci  TNode<RawPtrT> microtask_queue = GetMicrotaskQueue(native_context);
5451cb0ef41Sopenharmony_ci
5461cb0ef41Sopenharmony_ci  // Do not store the microtask if MicrotaskQueue is not available, that may
5471cb0ef41Sopenharmony_ci  // happen when the context shutdown.
5481cb0ef41Sopenharmony_ci  Label if_shutdown(this, Label::kDeferred);
5491cb0ef41Sopenharmony_ci  GotoIf(WordEqual(microtask_queue, IntPtrConstant(0)), &if_shutdown);
5501cb0ef41Sopenharmony_ci
5511cb0ef41Sopenharmony_ci  TNode<RawPtrT> ring_buffer = GetMicrotaskRingBuffer(microtask_queue);
5521cb0ef41Sopenharmony_ci  TNode<IntPtrT> capacity = GetMicrotaskQueueCapacity(microtask_queue);
5531cb0ef41Sopenharmony_ci  TNode<IntPtrT> size = GetMicrotaskQueueSize(microtask_queue);
5541cb0ef41Sopenharmony_ci  TNode<IntPtrT> start = GetMicrotaskQueueStart(microtask_queue);
5551cb0ef41Sopenharmony_ci
5561cb0ef41Sopenharmony_ci  Label if_grow(this, Label::kDeferred);
5571cb0ef41Sopenharmony_ci  GotoIf(IntPtrEqual(size, capacity), &if_grow);
5581cb0ef41Sopenharmony_ci
5591cb0ef41Sopenharmony_ci  // |microtask_queue| has an unused slot to store |microtask|.
5601cb0ef41Sopenharmony_ci  {
5611cb0ef41Sopenharmony_ci    StoreNoWriteBarrier(MachineType::PointerRepresentation(), ring_buffer,
5621cb0ef41Sopenharmony_ci                        CalculateRingBufferOffset(capacity, start, size),
5631cb0ef41Sopenharmony_ci                        BitcastTaggedToWord(microtask));
5641cb0ef41Sopenharmony_ci    StoreNoWriteBarrier(MachineType::PointerRepresentation(), microtask_queue,
5651cb0ef41Sopenharmony_ci                        IntPtrConstant(MicrotaskQueue::kSizeOffset),
5661cb0ef41Sopenharmony_ci                        IntPtrAdd(size, IntPtrConstant(1)));
5671cb0ef41Sopenharmony_ci    Return(UndefinedConstant());
5681cb0ef41Sopenharmony_ci  }
5691cb0ef41Sopenharmony_ci
5701cb0ef41Sopenharmony_ci  // |microtask_queue| has no space to store |microtask|. Fall back to C++
5711cb0ef41Sopenharmony_ci  // implementation to grow the buffer.
5721cb0ef41Sopenharmony_ci  BIND(&if_grow);
5731cb0ef41Sopenharmony_ci  {
5741cb0ef41Sopenharmony_ci    TNode<ExternalReference> isolate_constant =
5751cb0ef41Sopenharmony_ci        ExternalConstant(ExternalReference::isolate_address(isolate()));
5761cb0ef41Sopenharmony_ci    TNode<ExternalReference> function =
5771cb0ef41Sopenharmony_ci        ExternalConstant(ExternalReference::call_enqueue_microtask_function());
5781cb0ef41Sopenharmony_ci    CallCFunction(function, MachineType::AnyTagged(),
5791cb0ef41Sopenharmony_ci                  std::make_pair(MachineType::Pointer(), isolate_constant),
5801cb0ef41Sopenharmony_ci                  std::make_pair(MachineType::IntPtr(), microtask_queue),
5811cb0ef41Sopenharmony_ci                  std::make_pair(MachineType::AnyTagged(), microtask));
5821cb0ef41Sopenharmony_ci    Return(UndefinedConstant());
5831cb0ef41Sopenharmony_ci  }
5841cb0ef41Sopenharmony_ci
5851cb0ef41Sopenharmony_ci  Bind(&if_shutdown);
5861cb0ef41Sopenharmony_ci  Return(UndefinedConstant());
5871cb0ef41Sopenharmony_ci}
5881cb0ef41Sopenharmony_ci
5891cb0ef41Sopenharmony_ciTF_BUILTIN(RunMicrotasks, MicrotaskQueueBuiltinsAssembler) {
5901cb0ef41Sopenharmony_ci  // Load the current context from the isolate.
5911cb0ef41Sopenharmony_ci  TNode<Context> current_context = GetCurrentContext();
5921cb0ef41Sopenharmony_ci
5931cb0ef41Sopenharmony_ci  auto microtask_queue =
5941cb0ef41Sopenharmony_ci      UncheckedParameter<RawPtrT>(Descriptor::kMicrotaskQueue);
5951cb0ef41Sopenharmony_ci
5961cb0ef41Sopenharmony_ci  Label loop(this), done(this);
5971cb0ef41Sopenharmony_ci  Goto(&loop);
5981cb0ef41Sopenharmony_ci  BIND(&loop);
5991cb0ef41Sopenharmony_ci
6001cb0ef41Sopenharmony_ci  TNode<IntPtrT> size = GetMicrotaskQueueSize(microtask_queue);
6011cb0ef41Sopenharmony_ci
6021cb0ef41Sopenharmony_ci  // Exit if the queue is empty.
6031cb0ef41Sopenharmony_ci  GotoIf(WordEqual(size, IntPtrConstant(0)), &done);
6041cb0ef41Sopenharmony_ci
6051cb0ef41Sopenharmony_ci  TNode<RawPtrT> ring_buffer = GetMicrotaskRingBuffer(microtask_queue);
6061cb0ef41Sopenharmony_ci  TNode<IntPtrT> capacity = GetMicrotaskQueueCapacity(microtask_queue);
6071cb0ef41Sopenharmony_ci  TNode<IntPtrT> start = GetMicrotaskQueueStart(microtask_queue);
6081cb0ef41Sopenharmony_ci
6091cb0ef41Sopenharmony_ci  TNode<IntPtrT> offset =
6101cb0ef41Sopenharmony_ci      CalculateRingBufferOffset(capacity, start, IntPtrConstant(0));
6111cb0ef41Sopenharmony_ci  TNode<RawPtrT> microtask_pointer = Load<RawPtrT>(ring_buffer, offset);
6121cb0ef41Sopenharmony_ci  TNode<Microtask> microtask = CAST(BitcastWordToTagged(microtask_pointer));
6131cb0ef41Sopenharmony_ci
6141cb0ef41Sopenharmony_ci  TNode<IntPtrT> new_size = IntPtrSub(size, IntPtrConstant(1));
6151cb0ef41Sopenharmony_ci  TNode<IntPtrT> new_start = WordAnd(IntPtrAdd(start, IntPtrConstant(1)),
6161cb0ef41Sopenharmony_ci                                     IntPtrSub(capacity, IntPtrConstant(1)));
6171cb0ef41Sopenharmony_ci
6181cb0ef41Sopenharmony_ci  // Remove |microtask| from |ring_buffer| before running it, since its
6191cb0ef41Sopenharmony_ci  // invocation may add another microtask into |ring_buffer|.
6201cb0ef41Sopenharmony_ci  SetMicrotaskQueueSize(microtask_queue, new_size);
6211cb0ef41Sopenharmony_ci  SetMicrotaskQueueStart(microtask_queue, new_start);
6221cb0ef41Sopenharmony_ci
6231cb0ef41Sopenharmony_ci  RunSingleMicrotask(current_context, microtask);
6241cb0ef41Sopenharmony_ci  IncrementFinishedMicrotaskCount(microtask_queue);
6251cb0ef41Sopenharmony_ci  Goto(&loop);
6261cb0ef41Sopenharmony_ci
6271cb0ef41Sopenharmony_ci  BIND(&done);
6281cb0ef41Sopenharmony_ci  {
6291cb0ef41Sopenharmony_ci    // Reset the "current microtask" on the isolate.
6301cb0ef41Sopenharmony_ci    StoreRoot(RootIndex::kCurrentMicrotask, UndefinedConstant());
6311cb0ef41Sopenharmony_ci    Return(UndefinedConstant());
6321cb0ef41Sopenharmony_ci  }
6331cb0ef41Sopenharmony_ci}
6341cb0ef41Sopenharmony_ci
6351cb0ef41Sopenharmony_ci}  // namespace internal
6361cb0ef41Sopenharmony_ci}  // namespace v8
637