// Copyright (C) 2018 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 <android-base/logging.h>
#include <jni.h>
#include <jvmti.h>

#include "base/runtime_debug.h"
#include "jit/jit.h"
#include "runtime-inl.h"
#include "scoped_thread_state_change-inl.h"
#include "thread-inl.h"
#include "thread_list.h"

namespace jitload {

// Special env version that allows JVMTI-like access on userdebug builds.
static constexpr jint kArtTiVersion = JVMTI_VERSION_1_2 | 0x40000000;

#define CHECK_CALL_SUCCESS(c) \
  do { \
    auto vc = (c); \
    CHECK(vc == JNI_OK || vc == JVMTI_ERROR_NONE) << "call " << #c  << " did not succeed\n"; \
  } while (false)

static jthread GetJitThread() {
  art::ScopedObjectAccess soa(art::Thread::Current());
  auto* jit = art::Runtime::Current()->GetJit();
  if (jit == nullptr) {
    return nullptr;
  }
  auto* thread_pool = jit->GetThreadPool();
  if (thread_pool == nullptr) {
    return nullptr;
  }
  // Currently we only have a single jit thread so we only look at that one.
  return soa.AddLocalReference<jthread>(
          thread_pool->GetWorkers()[0]->GetThread()->GetPeerFromOtherThread());
}

JNICALL void VmInitCb(jvmtiEnv* jvmti,
                      [[maybe_unused]] JNIEnv* env,
                      [[maybe_unused]] jthread curthread) {
  jthread jit_thread = GetJitThread();
  if (jit_thread != nullptr) {
    CHECK_EQ(jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_CLASS_PREPARE, jit_thread),
             JVMTI_ERROR_NONE);
  }
}

struct AgentOptions {
  bool fatal;
  uint64_t cnt;
};

JNICALL static void DataDumpRequestCb(jvmtiEnv* jvmti) {
  AgentOptions* ops;
  CHECK_CALL_SUCCESS(jvmti->GetEnvironmentLocalStorage(reinterpret_cast<void**>(&ops)));
  LOG(WARNING) << "Jit thread has loaded " << ops->cnt << " classes";
}

JNICALL void ClassPrepareJit(jvmtiEnv* jvmti,
                             [[maybe_unused]] JNIEnv* jni_env,
                             [[maybe_unused]] jthread thr,
                             jclass klass) {
  AgentOptions* ops;
  CHECK_CALL_SUCCESS(jvmti->GetEnvironmentLocalStorage(reinterpret_cast<void**>(&ops)));
  char* klass_name;
  CHECK_CALL_SUCCESS(jvmti->GetClassSignature(klass, &klass_name, nullptr));
  (ops->fatal ? LOG_STREAM(FATAL)
              : LOG_STREAM(WARNING)) << "Loaded " << klass_name << " on jit thread!";
  ops->cnt++;
  CHECK_CALL_SUCCESS(jvmti->Deallocate(reinterpret_cast<unsigned char*>(klass_name)));
}

JNICALL void VMDeathCb(jvmtiEnv* jvmti, [[maybe_unused]] JNIEnv* env) { DataDumpRequestCb(jvmti); }

static jvmtiEnv* SetupJvmti(JavaVM* vm, const char* options) {
  android::base::InitLogging(/* argv= */nullptr);

  jvmtiEnv* jvmti = nullptr;
  if (vm->GetEnv(reinterpret_cast<void**>(&jvmti), JVMTI_VERSION_1_0) != JNI_OK &&
      vm->GetEnv(reinterpret_cast<void**>(&jvmti), kArtTiVersion) != JNI_OK) {
    LOG(FATAL) << "Unable to setup JVMTI environment!";
  }
  jvmtiEventCallbacks cb {
        .VMInit = VmInitCb,
        .VMDeath = VMDeathCb,
        .ClassPrepare = ClassPrepareJit,
        .DataDumpRequest = DataDumpRequestCb,
  };
  AgentOptions* ops;
  CHECK_CALL_SUCCESS(
      jvmti->Allocate(sizeof(AgentOptions), reinterpret_cast<unsigned char**>(&ops)));
  ops->fatal = (strcmp(options, "fatal") == 0);
  ops->cnt = 0;
  CHECK_CALL_SUCCESS(jvmti->SetEnvironmentLocalStorage(ops));
  CHECK_CALL_SUCCESS(jvmti->SetEventCallbacks(&cb, sizeof(cb)));
  CHECK_CALL_SUCCESS(jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_VM_INIT, nullptr));
  CHECK_CALL_SUCCESS(
      jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_DATA_DUMP_REQUEST, nullptr));
  return jvmti;
}

// Early attachment (e.g. 'java -agent[lib|path]:filename.so').
extern "C" JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM* vm, char* options, void* /* reserved */) {
  SetupJvmti(vm, options);
  return JNI_OK;
}

// Late attachment (e.g. 'am attach-agent').
extern "C" JNIEXPORT jint JNICALL Agent_OnAttach(JavaVM *vm, char* options, void* /* reserved */) {
  jvmtiEnv* jvmti = SetupJvmti(vm, options);

  JNIEnv* jni = nullptr;
  jthread thr = nullptr;
  CHECK_CALL_SUCCESS(vm->GetEnv(reinterpret_cast<void**>(&jni), JNI_VERSION_1_6));
  CHECK_CALL_SUCCESS(jvmti->GetCurrentThread(&thr));

  // Final setup is done in the VmInitCb.
  VmInitCb(jvmti, jni, thr);

  jni->DeleteLocalRef(thr);
  return JNI_OK;
}

#undef CHECK_CALL_SUCCESS

}  // namespace jitload

