/*
 * Copyright (C) 2023 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "startup_completed_task.h"

#include "base/systrace.h"
#include "class_linker.h"
#include "gc/heap.h"
#include "gc/scoped_gc_critical_section.h"
#include "gc/space/image_space.h"
#include "gc/space/space-inl.h"
#include "handle_scope-inl.h"
#include "linear_alloc-inl.h"
#include "mirror/dex_cache.h"
#include "mirror/object-inl.h"
#include "obj_ptr.h"
#include "runtime_image.h"
#include "scoped_thread_state_change-inl.h"
#include "thread.h"
#include "thread_list.h"

namespace art {

class UnlinkStartupDexCacheVisitor : public DexCacheVisitor {
 public:
  UnlinkStartupDexCacheVisitor() {}

  void Visit(ObjPtr<mirror::DexCache> dex_cache)
      REQUIRES_SHARED(Locks::dex_lock_, Locks::mutator_lock_) override {
    dex_cache->UnlinkStartupCaches();
  }
};

void StartupCompletedTask::Run(Thread* self) {
  Runtime* const runtime = Runtime::Current();
  if (runtime->NotifyStartupCompleted()) {
    // Maybe generate a runtime app image. If the runtime is debuggable, boot
    // classpath classes can be dynamically changed, so don't bother generating an
    // image.
    if (!runtime->IsJavaDebuggable()) {
      std::string compiler_filter;
      std::string compilation_reason;
      runtime->GetAppInfo()->GetPrimaryApkOptimizationStatus(&compiler_filter, &compilation_reason);
      CompilerFilter::Filter filter;
      if (CompilerFilter::ParseCompilerFilter(compiler_filter.c_str(), &filter) &&
          !CompilerFilter::IsAotCompilationEnabled(filter)) {
        std::string error_msg;
        if (!RuntimeImage::WriteImageToDisk(&error_msg)) {
          LOG(DEBUG) << "Could not write temporary image to disk " << error_msg;
        }
      }
    }

    ScopedObjectAccess soa(self);
    DeleteStartupDexCaches(self, /* called_by_gc= */ false);
  }

  // Delete the thread pool used for app image loading since startup is assumed to be completed.
  ScopedTrace trace2("Delete thread pool");
  Runtime::Current()->DeleteThreadPool();
}

void StartupCompletedTask::DeleteStartupDexCaches(Thread* self, bool called_by_gc) {
  VLOG(startup) << "StartupCompletedTask running";
  Runtime* const runtime = Runtime::Current();

  ScopedTrace trace("Releasing dex caches and app image spaces metadata");

  static struct EmptyClosure : Closure {
    void Run([[maybe_unused]] Thread* thread) override {}
  } closure;

  // Fetch the startup linear alloc so no other thread tries to allocate there.
  std::unique_ptr<LinearAlloc> startup_linear_alloc(runtime->ReleaseStartupLinearAlloc());
  // No thread could be allocating arrays or accessing dex caches when this
  // thread has mutator-lock held exclusively.
  bool run_checkpoints = !Locks::mutator_lock_->IsExclusiveHeld(self);

  // Request a checkpoint to make sure all threads see we have started up and
  // won't allocate in the startup linear alloc. Without this checkpoint what
  // could happen is (T0 == self):
  // 1) T1 fetches startup alloc, allocates an array there.
  // 2) T0 goes over the dex caches, clear dex cache arrays in the startup alloc.
  // 3) T1 sets the dex cache array from startup alloc in a dex cache.
  // 4) T0 releases startup alloc.
  //
  // With this checkpoint, 3) cannot happen as T0 waits for T1 to reach the
  // checkpoint.
  if (run_checkpoints) {
    runtime->GetThreadList()->RunCheckpoint(&closure);
  }

  {
    UnlinkStartupDexCacheVisitor visitor;
    ReaderMutexLock mu(self, *Locks::dex_lock_);
    runtime->GetClassLinker()->VisitDexCaches(&visitor);
  }


  // Request a checkpoint to make sure no threads are:
  // - accessing the image space metadata section when we madvise it
  // - accessing dex caches when we free them
  if (run_checkpoints) {
    runtime->GetThreadList()->RunCheckpoint(&closure);
  }

  // If this isn't the GC calling `DeleteStartupDexCaches` and a GC may be
  // running, wait for it to be complete. We don't want it to see these dex
  // caches.
  if (!called_by_gc) {
    runtime->GetHeap()->WaitForGcToComplete(gc::kGcCauseDeletingDexCacheArrays, self);
  }

  // At this point, we know no other thread can see the arrays, nor the GC. So
  // we can safely release them.
  for (gc::space::ContinuousSpace* space : runtime->GetHeap()->GetContinuousSpaces()) {
    if (space->IsImageSpace()) {
      gc::space::ImageSpace* image_space = space->AsImageSpace();
      if (image_space->GetImageHeader().IsAppImage()) {
        image_space->ReleaseMetadata();
      }
    }
  }

  if (startup_linear_alloc != nullptr) {
    ScopedTrace trace2("Delete startup linear alloc");
    ArenaPool* arena_pool = startup_linear_alloc->GetArenaPool();
    startup_linear_alloc.reset();
    arena_pool->TrimMaps();
  }
}

}  // namespace art
