/*
 * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
 * Copyright (c) 2020 SAP SE. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 *
 */

#include "code/scopeDesc.hpp"
#include "memory/allocation.hpp"
#include "prims/jvmtiDeferredUpdates.hpp"
#include "runtime/deoptimization.hpp"
#include "runtime/escapeBarrier.hpp"
#include "runtime/frame.inline.hpp"
#include "runtime/handles.hpp"
#include "runtime/handshake.hpp"
#include "runtime/interfaceSupport.inline.hpp"
#include "runtime/javaThread.inline.hpp"
#include "runtime/keepStackGCProcessed.hpp"
#include "runtime/mutexLocker.hpp"
#include "runtime/registerMap.hpp"
#include "runtime/stackFrameStream.inline.hpp"
#include "runtime/stackValue.hpp"
#include "runtime/stackValueCollection.hpp"
#include "runtime/threadSMR.hpp"
#include "runtime/vframe.hpp"
#include "runtime/vframe_hp.hpp"
#include "utilities/debug.hpp"
#include "utilities/globalDefinitions.hpp"
#include "utilities/macros.hpp"

#if COMPILER2_OR_JVMCI

// Returns true iff objects were reallocated and relocked because of access through JVMTI
bool EscapeBarrier::objs_are_deoptimized(JavaThread* thread, intptr_t* fr_id) {
  // first/oldest update holds the flag
  GrowableArrayView<jvmtiDeferredLocalVariableSet*>* list = JvmtiDeferredUpdates::deferred_locals(thread);
  bool result = false;
  if (list != nullptr) {
    for (int i = 0; i < list->length(); i++) {
      if (list->at(i)->matches(fr_id)) {
        result = list->at(i)->objects_are_deoptimized();
        break;
      }
    }
  }
  return result;
}

// Deoptimize objects of frames of the target thread at depth >= d1 and depth <= d2.
// Deoptimize objects of caller frames if they passed references to ArgEscape objects as arguments.
// Return false in the case of a reallocation failure and true otherwise.
bool EscapeBarrier::deoptimize_objects(int d1, int d2) {
  if (!barrier_active()) return true;
  if (d1 < deoptee_thread()->frames_to_pop_failed_realloc()) {
    // The deoptee thread has frames with reallocation failures on top of its stack.
    // These frames are about to be removed. We must not interfere with that and signal failure.
    return false;
  }
  if (deoptee_thread()->has_last_Java_frame() &&
      deoptee_thread()->last_continuation() == nullptr) {
    assert(calling_thread() == Thread::current(), "should be");
    KeepStackGCProcessedMark ksgcpm(deoptee_thread());
    ResourceMark rm(calling_thread());
    HandleMark   hm(calling_thread());
    RegisterMap  reg_map(deoptee_thread(),
                         RegisterMap::UpdateMap::skip,
                         RegisterMap::ProcessFrames::skip,
                         RegisterMap::WalkContinuation::skip);
    vframe* vf = deoptee_thread()->last_java_vframe(&reg_map);
    int cur_depth = 0;

    // Skip frames at depth < d1
    while (vf != nullptr && cur_depth < d1) {
      cur_depth++;
      vf = vf->sender();
    }

    while (vf != nullptr && ((cur_depth <= d2) || !vf->is_entry_frame())) {
      if (vf->is_compiled_frame()) {
        compiledVFrame* cvf = compiledVFrame::cast(vf);
        // Deoptimize frame and local objects if any exist.
        // If cvf is deeper than depth, then we deoptimize iff local objects are passed as args.
        bool should_deopt = cur_depth <= d2 ? cvf->has_ea_local_in_scope() : cvf->arg_escape();
        if (should_deopt && !deoptimize_objects(cvf->fr().id())) {
          // reallocation of scalar replaced objects failed because heap is exhausted
          return false;
        }

        // move to top frame
        while(!vf->is_top()) {
          cur_depth++;
          vf = vf->sender();
        }
      }

      // move to next physical frame
      cur_depth++;
      vf = vf->sender();
    }
  }
  return true;
}

bool EscapeBarrier::deoptimize_objects_all_threads() {
  if (!barrier_active()) return true;
  ResourceMark rm(calling_thread());
  for (JavaThreadIteratorWithHandle jtiwh; JavaThread *jt = jtiwh.next(); ) {
    // Skip thread with mounted continuation
    if (jt->last_continuation() != nullptr) {
      continue;
    }
    if (jt->frames_to_pop_failed_realloc() > 0) {
      // The deoptee thread jt has frames with reallocation failures on top of its stack.
      // These frames are about to be removed. We must not interfere with that and signal failure.
      return false;
    }
    if (jt->has_last_Java_frame()) {
      KeepStackGCProcessedMark ksgcpm(jt);
      RegisterMap reg_map(jt,
                          RegisterMap::UpdateMap::skip,
                          RegisterMap::ProcessFrames::skip,
                          RegisterMap::WalkContinuation::skip);
      vframe* vf = jt->last_java_vframe(&reg_map);
      assert(jt->frame_anchor()->walkable(),
             "The stack of JavaThread " PTR_FORMAT " is not walkable. Thread state is %d",
             p2i(jt), jt->thread_state());
      while (vf != nullptr) {
        if (vf->is_compiled_frame()) {
          compiledVFrame* cvf = compiledVFrame::cast(vf);
          if ((cvf->has_ea_local_in_scope() || cvf->arg_escape()) &&
              !deoptimize_objects_internal(jt, cvf->fr().id())) {
            return false; // reallocation failure
          }
          // move to top frame
          while(!vf->is_top()) {
            vf = vf->sender();
          }
        }
        // move to next physical frame
        vf = vf->sender();
      }
    }
  }
  return true; // success
}

bool EscapeBarrier::_deoptimizing_objects_for_all_threads = false;
bool EscapeBarrier::_self_deoptimization_in_progress      = false;

class EscapeBarrierSuspendHandshake : public HandshakeClosure {
 public:
  EscapeBarrierSuspendHandshake(const char* name) :
    HandshakeClosure(name) { }
  void do_thread(Thread* th) { }
};

void EscapeBarrier::sync_and_suspend_one() {
  assert(_calling_thread != nullptr, "calling thread must not be null");
  assert(_deoptee_thread != nullptr, "deoptee thread must not be null");
  assert(barrier_active(), "should not call");

  // Sync with other threads that might be doing deoptimizations
  {
    // Need to switch to _thread_blocked for the wait() call
    ThreadBlockInVM tbivm(_calling_thread);
    MonitorLocker ml(_calling_thread, EscapeBarrier_lock, Mutex::_no_safepoint_check_flag);
    while (_self_deoptimization_in_progress || _deoptee_thread->is_obj_deopt_suspend()) {
      ml.wait();
    }

    if (self_deopt()) {
      _self_deoptimization_in_progress = true;
      return;
    }

    // set suspend flag for target thread
    _deoptee_thread->set_obj_deopt_flag();
  }

  // Use a handshake to synchronize with the target thread.
  EscapeBarrierSuspendHandshake sh("EscapeBarrierSuspendOne");
  Handshake::execute(&sh, _deoptee_thread);
  assert(!_deoptee_thread->has_last_Java_frame() || _deoptee_thread->frame_anchor()->walkable(),
         "stack should be walkable now");
}

void EscapeBarrier::sync_and_suspend_all() {
  assert(barrier_active(), "should not call");
  assert(_calling_thread != nullptr, "calling thread must not be null");
  assert(all_threads(), "sanity");

  // Sync with other threads that might be doing deoptimizations
  {
    // Need to switch to _thread_blocked for the wait() call
    ThreadBlockInVM tbivm(_calling_thread);
    MonitorLocker ml(_calling_thread, EscapeBarrier_lock, Mutex::_no_safepoint_check_flag);

    bool deopt_in_progress;
    do {
      deopt_in_progress = _self_deoptimization_in_progress;
      for (JavaThreadIteratorWithHandle jtiwh; JavaThread *jt = jtiwh.next(); ) {
        deopt_in_progress = (deopt_in_progress || jt->is_obj_deopt_suspend());
        if (deopt_in_progress) {
          break;
        }
      }
      if (deopt_in_progress) {
        ml.wait(); // then check again
      }
    } while(deopt_in_progress);

    _self_deoptimization_in_progress = true;
    _deoptimizing_objects_for_all_threads = true;

    // We set the suspend flags before executing the handshake because then the
    // setting will be visible after leaving the _thread_blocked state in
    // JavaThread::wait_for_object_deoptimization(). If we set the flags in the
    // handshake then the read must happen after the safepoint/handshake poll.
    for (JavaThreadIteratorWithHandle jtiwh; JavaThread *jt = jtiwh.next(); ) {
      if (jt->is_Java_thread() && !jt->is_hidden_from_external_view() && (jt != _calling_thread)) {
        jt->set_obj_deopt_flag();
      }
    }
  }

  // Use a handshake to synchronize with the other threads.
  EscapeBarrierSuspendHandshake sh("EscapeBarrierSuspendAll");
  Handshake::execute(&sh);
#ifdef ASSERT
  for (JavaThreadIteratorWithHandle jtiwh; JavaThread *jt = jtiwh.next(); ) {
    if (jt->is_hidden_from_external_view()) continue;
    assert(!jt->has_last_Java_frame() || jt->frame_anchor()->walkable(),
           "The stack of JavaThread " PTR_FORMAT " is not walkable. Thread state is %d",
           p2i(jt), jt->thread_state());
  }
#endif // ASSERT
}

void EscapeBarrier::resume_one() {
  assert(barrier_active(), "should not call");
  assert(!all_threads(), "use resume_all()");
  MonitorLocker ml(_calling_thread, EscapeBarrier_lock, Mutex::_no_safepoint_check_flag);
  if (self_deopt()) {
    assert(_self_deoptimization_in_progress, "incorrect synchronization");
    _self_deoptimization_in_progress = false;
  } else {
    _deoptee_thread->clear_obj_deopt_flag();
  }
  ml.notify_all();
}

void EscapeBarrier::resume_all() {
  assert(barrier_active(), "should not call");
  assert(all_threads(), "use resume_one()");
  MonitorLocker ml(_calling_thread, EscapeBarrier_lock, Mutex::_no_safepoint_check_flag);
  assert(_self_deoptimization_in_progress, "incorrect synchronization");
  _deoptimizing_objects_for_all_threads = false;
  _self_deoptimization_in_progress = false;
  for (JavaThreadIteratorWithHandle jtiwh; JavaThread *jt = jtiwh.next(); ) {
    jt->clear_obj_deopt_flag();
  }
  ml.notify_all();
}

void EscapeBarrier::thread_added(JavaThread* jt) {
  if (!jt->is_hidden_from_external_view()) {
    MutexLocker ml(EscapeBarrier_lock, Mutex::_no_safepoint_check_flag);
    if (_deoptimizing_objects_for_all_threads) {
      jt->set_obj_deopt_flag();
    }
  }
}

void EscapeBarrier::thread_removed(JavaThread* jt) {
  MonitorLocker ml(EscapeBarrier_lock, Mutex::_no_safepoint_check_flag);
  if (jt->is_obj_deopt_suspend()) {
    // jt terminated before it self suspended.
    // Other threads might be waiting to perform deoptimizations for it.
    jt->clear_obj_deopt_flag();
    ml.notify_all();
  }
}

// Remember that objects were reallocated and relocked for the compiled frame with the given id
static void set_objs_are_deoptimized(JavaThread* thread, intptr_t* fr_id) {
  // set in first/oldest update
  GrowableArrayView<jvmtiDeferredLocalVariableSet*>* list =
    JvmtiDeferredUpdates::deferred_locals(thread);
  DEBUG_ONLY(bool found = false);
  if (list != nullptr) {
    for (int i = 0; i < list->length(); i++) {
      if (list->at(i)->matches(fr_id)) {
        DEBUG_ONLY(found = true);
        list->at(i)->set_objs_are_deoptimized();
        break;
      }
    }
  }
  assert(found, "variable set should exist at least for one vframe");
}

// Deoptimize the given frame and deoptimize objects with optimizations based on
// escape analysis, i.e. reallocate scalar replaced objects on the heap and
// relock objects if locking has been eliminated.
// Deoptimized objects are kept as JVMTI deferred updates until the compiled
// frame is replaced with interpreter frames.  Returns false iff at least one
// reallocation failed.
bool EscapeBarrier::deoptimize_objects_internal(JavaThread* deoptee, intptr_t* fr_id) {
  assert(barrier_active(), "should not call");

  JavaThread* ct = calling_thread();
  bool realloc_failures = false;

  if (!objs_are_deoptimized(deoptee, fr_id)) {
    // Make sure the frame identified by fr_id is deoptimized and fetch its last vframe
    compiledVFrame* last_cvf;
    bool fr_is_deoptimized;
    do {
      StackFrameStream fst(deoptee, true /* update */, false /* process_frames */);
      while (fst.current()->id() != fr_id && !fst.is_done()) {
        fst.next();
      }
      assert(fst.current()->id() == fr_id, "frame not found");
      assert(fst.current()->is_compiled_frame(),
             "only compiled frames can contain stack allocated objects");
      fr_is_deoptimized = fst.current()->is_deoptimized_frame();
      if (!fr_is_deoptimized) {
        // Execution must not continue in the compiled method, so we deoptimize the frame.
        Deoptimization::deoptimize_frame(deoptee, fr_id);
      } else {
        last_cvf = compiledVFrame::cast(vframe::new_vframe(fst.current(), fst.register_map(), deoptee));
      }
    } while(!fr_is_deoptimized);

    // collect inlined frames
    compiledVFrame* cvf = last_cvf;
    GrowableArray<compiledVFrame*>* vfs = new GrowableArray<compiledVFrame*>(10);
    while (!cvf->is_top()) {
      vfs->push(cvf);
      cvf = compiledVFrame::cast(cvf->sender());
    }
    vfs->push(cvf);

    // reallocate and relock optimized objects
    bool deoptimized_objects = Deoptimization::deoptimize_objects_internal(ct, vfs, realloc_failures);
    if (!realloc_failures && deoptimized_objects) {
      // now do the updates
      for (int frame_index = 0; frame_index < vfs->length(); frame_index++) {
        cvf = vfs->at(frame_index);
        cvf->create_deferred_updates_after_object_deoptimization();
      }
      set_objs_are_deoptimized(deoptee, fr_id);
    }
  }
  return !realloc_failures;
}

#endif // COMPILER2_OR_JVMCI
