/*
 * Copyright (C) 2011 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 "driver/compiler_driver.h"

#include <limits>
#include <stdint.h>
#include <stdio.h>
#include <memory>

#include "art_method-inl.h"
#include "base/casts.h"
#include "class_linker-inl.h"
#include "common_compiler_driver_test.h"
#include "compiled_method-inl.h"
#include "compiler_callbacks.h"
#include "dex/dex_file.h"
#include "dex/dex_file_types.h"
#include "gc/heap.h"
#include "handle_scope-inl.h"
#include "mirror/class-inl.h"
#include "mirror/class_loader.h"
#include "mirror/dex_cache-inl.h"
#include "mirror/object-inl.h"
#include "mirror/object_array-inl.h"
#include "profile/profile_compilation_info.h"
#include "scoped_thread_state_change-inl.h"

namespace art {

class CompilerDriverTest : public CommonCompilerDriverTest {
 protected:
  void CompileAllAndMakeExecutable(jobject class_loader) REQUIRES(!Locks::mutator_lock_) {
    TimingLogger timings("CompilerDriverTest::CompileAllAndMakeExecutable", false, false);
    dex_files_ = GetDexFiles(class_loader);
    CompileAll(class_loader, dex_files_, &timings);
    TimingLogger::ScopedTiming t("MakeAllExecutable", &timings);
    MakeAllExecutable(class_loader);
  }

  void EnsureCompiled(jobject class_loader, const char* class_name, const char* method,
                      const char* signature, bool is_virtual)
      REQUIRES(!Locks::mutator_lock_) {
    CompileAllAndMakeExecutable(class_loader);
    Thread::Current()->TransitionFromSuspendedToRunnable();
    bool started = runtime_->Start();
    CHECK(started);
    env_ = Thread::Current()->GetJniEnv();
    class_ = env_->FindClass(class_name);
    CHECK(class_ != nullptr) << "Class not found: " << class_name;
    if (is_virtual) {
      mid_ = env_->GetMethodID(class_, method, signature);
    } else {
      mid_ = env_->GetStaticMethodID(class_, method, signature);
    }
    CHECK(mid_ != nullptr) << "Method not found: " << class_name << "." << method << signature;
  }

  void MakeAllExecutable(jobject class_loader) {
    const std::vector<const DexFile*> class_path = GetDexFiles(class_loader);
    for (size_t i = 0; i != class_path.size(); ++i) {
      const DexFile* dex_file = class_path[i];
      CHECK(dex_file != nullptr);
      MakeDexFileExecutable(class_loader, *dex_file);
    }
  }

  void MakeExecutable(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_) {
    CHECK(method != nullptr);

    const void* method_code = nullptr;
    if (!method->IsAbstract()) {
      MethodReference method_ref(method->GetDexFile(), method->GetDexMethodIndex());
      const CompiledMethod* compiled_method = compiler_driver_->GetCompiledMethod(method_ref);
      // If the code size is 0 it means the method was skipped due to profile guided compilation.
      if (compiled_method != nullptr && compiled_method->GetQuickCode().size() != 0u) {
        method_code = CommonCompilerTest::MakeExecutable(compiled_method->GetQuickCode(),
                                                         compiled_method->GetVmapTable(),
                                                         compiled_method->GetInstructionSet());
        LOG(INFO) << "MakeExecutable " << method->PrettyMethod() << " code=" << method_code;
      }
    }
    runtime_->GetInstrumentation()->InitializeMethodsCode(method, /*aot_code=*/ method_code);
  }

  void MakeDexFileExecutable(jobject class_loader, const DexFile& dex_file) {
    ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
    for (size_t i = 0; i < dex_file.NumClassDefs(); i++) {
      const dex::ClassDef& class_def = dex_file.GetClassDef(i);
      const char* descriptor = dex_file.GetClassDescriptor(class_def);
      ScopedObjectAccess soa(Thread::Current());
      StackHandleScope<1> hs(soa.Self());
      Handle<mirror::ClassLoader> loader(
          hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader)));
      ObjPtr<mirror::Class> c = class_linker->FindClass(soa.Self(), descriptor, loader);
      CHECK(c != nullptr);
      const auto pointer_size = class_linker->GetImagePointerSize();
      for (auto& m : c->GetMethods(pointer_size)) {
        MakeExecutable(&m);
      }
    }
  }

  JNIEnv* env_;
  jclass class_;
  jmethodID mid_;
  std::vector<const DexFile*> dex_files_;
};

// Disabled due to 10 second runtime on host
// TODO: Update the test for hash-based dex cache arrays. Bug: 30627598
TEST_F(CompilerDriverTest, DISABLED_LARGE_CompileDexLibCore) {
  CompileAllAndMakeExecutable(nullptr);

  // All libcore references should resolve
  ScopedObjectAccess soa(Thread::Current());
  ASSERT_TRUE(java_lang_dex_file_ != nullptr);
  const DexFile& dex = *java_lang_dex_file_;
  ObjPtr<mirror::DexCache> dex_cache = class_linker_->FindDexCache(soa.Self(), dex);
  for (size_t i = 0; i < dex_cache->NumStrings(); i++) {
    const ObjPtr<mirror::String> string = dex_cache->GetResolvedString(dex::StringIndex(i));
    EXPECT_TRUE(string != nullptr) << "string_idx=" << i;
  }
  for (size_t i = 0; i < dex_cache->NumResolvedTypes(); i++) {
    const ObjPtr<mirror::Class> type = dex_cache->GetResolvedType(dex::TypeIndex(i));
    EXPECT_TRUE(type != nullptr)
        << "type_idx=" << i << " " << dex.GetTypeDescriptor(dex.GetTypeId(dex::TypeIndex(i)));
  }
  for (size_t i = 0; i < dex_cache->NumResolvedMethods(); i++) {
    // FIXME: This is outdated for hash-based method array.
    ArtMethod* method = dex_cache->GetResolvedMethod(i);
    EXPECT_TRUE(method != nullptr) << "method_idx=" << i
                                << " " << dex.GetMethodDeclaringClassDescriptor(dex.GetMethodId(i))
                                << " " << dex.GetMethodName(dex.GetMethodId(i));
    EXPECT_TRUE(method->GetEntryPointFromQuickCompiledCode() != nullptr) << "method_idx=" << i
        << " " << dex.GetMethodDeclaringClassDescriptor(dex.GetMethodId(i)) << " "
        << dex.GetMethodName(dex.GetMethodId(i));
  }
  for (size_t i = 0; i < dex_cache->NumResolvedFields(); i++) {
    // FIXME: This is outdated for hash-based field array.
    ArtField* field = dex_cache->GetResolvedField(i);
    EXPECT_TRUE(field != nullptr) << "field_idx=" << i
                               << " " << dex.GetFieldDeclaringClassDescriptor(dex.GetFieldId(i))
                               << " " << dex.GetFieldName(dex.GetFieldId(i));
  }

  // TODO check Class::IsVerified for all classes

  // TODO: check that all Method::GetCode() values are non-null
}

TEST_F(CompilerDriverTest, AbstractMethodErrorStub) {
  jobject class_loader;
  {
    ScopedObjectAccess soa(Thread::Current());
    class_loader = LoadDex("AbstractMethod");
  }
  ASSERT_TRUE(class_loader != nullptr);
  EnsureCompiled(class_loader, "AbstractClass", "foo", "()V", true);

  // Create a jobj_ of ConcreteClass, NOT AbstractClass.
  jclass c_class = env_->FindClass("ConcreteClass");

  jmethodID constructor = env_->GetMethodID(c_class, "<init>", "()V");

  jobject jobj_ = env_->NewObject(c_class, constructor);
  ASSERT_TRUE(jobj_ != nullptr);

  // Force non-virtual call to AbstractClass foo, will throw AbstractMethodError exception.
  env_->CallNonvirtualVoidMethod(jobj_, class_, mid_);

  EXPECT_EQ(env_->ExceptionCheck(), JNI_TRUE);
  jthrowable exception = env_->ExceptionOccurred();
  env_->ExceptionClear();
  jclass jlame = env_->FindClass("java/lang/AbstractMethodError");
  EXPECT_TRUE(env_->IsInstanceOf(exception, jlame));
  {
    ScopedObjectAccess soa(Thread::Current());
    Thread::Current()->ClearException();
  }
}

class CompilerDriverProfileTest : public CompilerDriverTest {
 protected:
  ProfileCompilationInfo* GetProfileCompilationInfo() override {
    ScopedObjectAccess soa(Thread::Current());
    std::vector<std::unique_ptr<const DexFile>> dex_files = OpenTestDexFiles("ProfileTestMultiDex");

    ProfileCompilationInfo info;
    for (const std::unique_ptr<const DexFile>& dex_file : dex_files) {
      profile_info_.AddMethod(ProfileMethodInfo(MethodReference(dex_file.get(), 1)),
                              ProfileCompilationInfo::MethodHotness::kFlagHot);
      profile_info_.AddMethod(ProfileMethodInfo(MethodReference(dex_file.get(), 2)),
                              ProfileCompilationInfo::MethodHotness::kFlagHot);
    }
    return &profile_info_;
  }

  CompilerFilter::Filter GetCompilerFilter() const override {
    // Use a profile based filter.
    return CompilerFilter::kSpeedProfile;
  }

  std::unordered_set<std::string> GetExpectedMethodsForClass(const std::string& clazz) {
    if (clazz == "Main") {
      return std::unordered_set<std::string>({
          "java.lang.String Main.getA()",
          "java.lang.String Main.getB()"});
    } else if (clazz == "Second") {
      return std::unordered_set<std::string>({
          "java.lang.String Second.getX()",
          "java.lang.String Second.getY()"});
    } else {
      return std::unordered_set<std::string>();
    }
  }

  void CheckCompiledMethods(jobject class_loader,
                            const std::string& clazz,
                            const std::unordered_set<std::string>& expected_methods) {
    ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
    Thread* self = Thread::Current();
    ScopedObjectAccess soa(self);
    StackHandleScope<1> hs(self);
    Handle<mirror::ClassLoader> h_loader(
        hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader)));
    ObjPtr<mirror::Class> klass = class_linker->FindClass(self, clazz.c_str(), h_loader);
    ASSERT_NE(klass, nullptr);

    const auto pointer_size = class_linker->GetImagePointerSize();
    size_t number_of_compiled_methods = 0;
    for (auto& m : klass->GetVirtualMethods(pointer_size)) {
      std::string name = m.PrettyMethod(true);
      const void* code = m.GetEntryPointFromQuickCompiledCodePtrSize(pointer_size);
      ASSERT_NE(code, nullptr);
      if (expected_methods.find(name) != expected_methods.end()) {
        number_of_compiled_methods++;
        EXPECT_FALSE(class_linker->IsQuickToInterpreterBridge(code));
      } else {
        EXPECT_TRUE(class_linker->IsQuickToInterpreterBridge(code));
      }
    }
    EXPECT_EQ(expected_methods.size(), number_of_compiled_methods);
  }

 private:
  ProfileCompilationInfo profile_info_;
};

TEST_F(CompilerDriverProfileTest, ProfileGuidedCompilation) {
  TEST_DISABLED_FOR_RISCV64();
  Thread* self = Thread::Current();
  jobject class_loader;
  {
    ScopedObjectAccess soa(self);
    class_loader = LoadDex("ProfileTestMultiDex");
  }
  ASSERT_NE(class_loader, nullptr);

  // Need to enable dex-file writability. Methods rejected to be compiled will run through the
  // dex-to-dex compiler.
  for (const DexFile* dex_file : GetDexFiles(class_loader)) {
    ASSERT_TRUE(dex_file->EnableWrite());
  }

  CompileAllAndMakeExecutable(class_loader);

  std::unordered_set<std::string> m = GetExpectedMethodsForClass("Main");
  std::unordered_set<std::string> s = GetExpectedMethodsForClass("Second");
  CheckCompiledMethods(class_loader, "LMain;", m);
  CheckCompiledMethods(class_loader, "LSecond;", s);
}

// Test that a verify only compiler filter updates the CompiledClass map,
// which will be used for OatClass.
class CompilerDriverVerifyTest : public CompilerDriverTest {
 protected:
  CompilerFilter::Filter GetCompilerFilter() const override {
    return CompilerFilter::kVerify;
  }

  void CheckVerifiedClass(jobject class_loader, const std::string& clazz) const {
    ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
    Thread* self = Thread::Current();
    ScopedObjectAccess soa(self);
    StackHandleScope<1> hs(self);
    Handle<mirror::ClassLoader> h_loader(
        hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader)));
    ObjPtr<mirror::Class> klass = class_linker->FindClass(self, clazz.c_str(), h_loader);
    ASSERT_NE(klass, nullptr);
    EXPECT_TRUE(klass->IsVerified());

    ClassStatus status;
    bool found = compiler_driver_->GetCompiledClass(
        ClassReference(&klass->GetDexFile(), klass->GetDexTypeIndex().index_), &status);
    ASSERT_TRUE(found);
    EXPECT_GE(status, ClassStatus::kVerified);
  }
};

TEST_F(CompilerDriverVerifyTest, VerifyCompilation) {
  Thread* self = Thread::Current();
  jobject class_loader;
  {
    ScopedObjectAccess soa(self);
    class_loader = LoadDex("ProfileTestMultiDex");
  }
  ASSERT_NE(class_loader, nullptr);

  CompileAllAndMakeExecutable(class_loader);

  CheckVerifiedClass(class_loader, "LMain;");
  CheckVerifiedClass(class_loader, "LSecond;");
}

// Test that a class of status ClassStatus::kRetryVerificationAtRuntime is indeed
// recorded that way in the driver.
TEST_F(CompilerDriverVerifyTest, RetryVerifcationStatusCheckVerified) {
  Thread* const self = Thread::Current();
  jobject class_loader;
  std::vector<const DexFile*> dex_files;
  const DexFile* dex_file = nullptr;
  {
    ScopedObjectAccess soa(self);
    class_loader = LoadDex("ProfileTestMultiDex");
    ASSERT_NE(class_loader, nullptr);
    dex_files = GetDexFiles(class_loader);
    ASSERT_GT(dex_files.size(), 0u);
    dex_file = dex_files.front();
  }
  SetDexFilesForOatFile(dex_files);
  callbacks_->SetDoesClassUnloading(true, compiler_driver_.get());
  ClassReference ref(dex_file, 0u);
  // Test that the status is read from the compiler driver as expected.
  static_assert(enum_cast<size_t>(ClassStatus::kLast) < std::numeric_limits<size_t>::max(),
                "Make sure incrementing the class status does not overflow.");
  for (size_t i = enum_cast<size_t>(ClassStatus::kRetryVerificationAtRuntime);
       i <= enum_cast<size_t>(ClassStatus::kLast);
       ++i) {
    const ClassStatus expected_status = enum_cast<ClassStatus>(i);
    // Skip unsupported status that are not supposed to be ever recorded.
    if (expected_status == ClassStatus::kInitializing ||
        expected_status == ClassStatus::kInitialized) {
      continue;
    }
    compiler_driver_->RecordClassStatus(ref, expected_status);
    ClassStatus status = {};
    ASSERT_TRUE(compiler_driver_->GetCompiledClass(ref, &status));
    EXPECT_EQ(status, expected_status);
  }
}

// TODO: need check-cast test (when stub complete & we can throw/catch

}  // namespace art
