/*
 * Copyright (C) 2012 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 "art_method-inl.h"
#include "callee_save_frame.h"
#include "entrypoints/entrypoint_utils-inl.h"
#include "class_linker-inl.h"
#include "class_table-inl.h"
#include "dex_file-inl.h"
#include "dex_file_types.h"
#include "gc/heap.h"
#include "mirror/class-inl.h"
#include "mirror/class_loader.h"
#include "mirror/object_array-inl.h"
#include "mirror/object-inl.h"
#include "oat_file.h"
#include "runtime.h"

namespace art {

static inline void BssWriteBarrier(ArtMethod* outer_method) REQUIRES_SHARED(Locks::mutator_lock_) {
  // For AOT code, we need a write barrier for the class loader that holds the
  // GC roots in the .bss.
  const DexFile* dex_file = outer_method->GetDexFile();
  if (dex_file != nullptr &&
      dex_file->GetOatDexFile() != nullptr &&
      !dex_file->GetOatDexFile()->GetOatFile()->GetBssGcRoots().empty()) {
    ObjPtr<mirror::ClassLoader> class_loader = outer_method->GetClassLoader();
    if (kIsDebugBuild) {
      ClassTable* class_table =
          Runtime::Current()->GetClassLinker()->ClassTableForClassLoader(class_loader);
      CHECK(class_table != nullptr &&
            !class_table->InsertOatFile(dex_file->GetOatDexFile()->GetOatFile()))
          << "Oat file with .bss GC roots was not registered in class table: "
          << dex_file->GetOatDexFile()->GetOatFile()->GetLocation();
    }
    if (class_loader != nullptr) {
      // Note that we emit the barrier before the compiled code stores the String or Class
      // as a GC root. This is OK as there is no suspend point point in between.
      Runtime::Current()->GetHeap()->WriteBarrierEveryFieldOf(class_loader);
    } else {
      Runtime::Current()->GetClassLinker()->WriteBarrierForBootOatFileBssRoots(
          dex_file->GetOatDexFile()->GetOatFile());
    }
  }
}

constexpr Runtime::CalleeSaveType kInitEntrypointSaveType =
    // TODO: Change allocation entrypoints on MIPS and MIPS64 to kSaveEverything.
    (kRuntimeISA == kMips || kRuntimeISA == kMips64) ? Runtime::kSaveRefsOnly
                                                     : Runtime::kSaveEverything;

extern "C" mirror::Class* artInitializeStaticStorageFromCode(uint32_t type_idx, Thread* self)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  // Called to ensure static storage base is initialized for direct static field reads and writes.
  // A class may be accessing another class' fields when it doesn't have access, as access has been
  // given by inheritance.
  ScopedQuickEntrypointChecks sqec(self);
  auto caller_and_outer = GetCalleeSaveMethodCallerAndOuterMethod(self, kInitEntrypointSaveType);
  ArtMethod* caller = caller_and_outer.caller;
  mirror::Class* result =
      ResolveVerifyAndClinit(dex::TypeIndex(type_idx), caller, self, true, false);
  if (LIKELY(result != nullptr)) {
    BssWriteBarrier(caller_and_outer.outer_method);
  }
  return result;
}

extern "C" mirror::Class* artInitializeTypeFromCode(uint32_t type_idx, Thread* self)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  // Called when method->dex_cache_resolved_types_[] misses.
  ScopedQuickEntrypointChecks sqec(self);
  auto caller_and_outer = GetCalleeSaveMethodCallerAndOuterMethod(self, kInitEntrypointSaveType);
  ArtMethod* caller = caller_and_outer.caller;
  mirror::Class* result =
      ResolveVerifyAndClinit(dex::TypeIndex(type_idx), caller, self, false, false);
  if (LIKELY(result != nullptr)) {
    BssWriteBarrier(caller_and_outer.outer_method);
  }
  return result;
}

extern "C" mirror::Class* artInitializeTypeAndVerifyAccessFromCode(uint32_t type_idx, Thread* self)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  // Called when caller isn't guaranteed to have access to a type and the dex cache may be
  // unpopulated.
  ScopedQuickEntrypointChecks sqec(self);
  auto caller_and_outer = GetCalleeSaveMethodCallerAndOuterMethod(self, kInitEntrypointSaveType);
  ArtMethod* caller = caller_and_outer.caller;
  mirror::Class* result =
      ResolveVerifyAndClinit(dex::TypeIndex(type_idx), caller, self, false, true);
  if (LIKELY(result != nullptr)) {
    BssWriteBarrier(caller_and_outer.outer_method);
  }
  return result;
}

extern "C" mirror::String* artResolveStringFromCode(int32_t string_idx, Thread* self)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  ScopedQuickEntrypointChecks sqec(self);
  auto caller_and_outer = GetCalleeSaveMethodCallerAndOuterMethod(self, kInitEntrypointSaveType);
  ArtMethod* caller = caller_and_outer.caller;
  mirror::String* result = ResolveStringFromCode(caller, dex::StringIndex(string_idx));
  if (LIKELY(result != nullptr)) {
    BssWriteBarrier(caller_and_outer.outer_method);
  }
  return result;
}

}  // namespace art
