/* Copyright (C) 2017 The Android Open Source Project
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This file implements interfaces from the file jvmti.h. This implementation
 * is licensed under the same terms as the file jvmti.h.  The
 * copyright and license information for the file jvmti.h follows.
 *
 * Copyright (c) 2003, 2011, Oracle and/or its affiliates. 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.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * 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.
 */

#ifndef ART_OPENJDKJVMTI_TI_CLASS_DEFINITION_H_
#define ART_OPENJDKJVMTI_TI_CLASS_DEFINITION_H_

#include <stddef.h>
#include <sys/mman.h>
#include <sys/types.h>

#include "art_jvmti.h"

#include "base/array_ref.h"
#include "base/mem_map.h"

namespace openjdkjvmti {

// A struct that stores data needed for redefining/transforming classes. This structure should only
// even be accessed from a single thread and must not survive past the completion of the
// redefinition/retransformation function that created it.
class ArtClassDefinition {
 public:
  // If we support doing a on-demand dex-dequickening using signal handlers.
  static constexpr bool kEnableOnDemandDexDequicken = true;

  ArtClassDefinition()
      : klass_(nullptr),
        loader_(nullptr),
        name_(),
        protection_domain_(nullptr),
        dex_data_mmap_(),
        temp_mmap_(),
        dex_data_memory_(),
        initial_dex_file_unquickened_(nullptr),
        dex_data_(),
        current_dex_memory_(),
        current_dex_file_(),
        redefined_(false),
        from_class_ext_(false),
        initialized_(false) {}

  void InitFirstLoad(const char* descriptor,
                     art::Handle<art::mirror::ClassLoader> klass_loader,
                     const art::DexFile& dex_file);
  jvmtiError Init(art::Thread* self, jclass klass);
  jvmtiError Init(art::Thread* self, const jvmtiClassDefinition& def);

  ArtClassDefinition(ArtClassDefinition&& o) = default;
  ArtClassDefinition& operator=(ArtClassDefinition&& o) = default;

  void SetNewDexData(jint new_dex_len, unsigned char* new_dex_data) {
    DCHECK(IsInitialized());
    if (new_dex_data == nullptr) {
      return;
    } else {
      art::ArrayRef<const unsigned char> new_data(new_dex_data, new_dex_len);
      if (new_data != dex_data_) {
        dex_data_memory_.resize(new_dex_len);
        memcpy(dex_data_memory_.data(), new_dex_data, new_dex_len);
        dex_data_ = art::ArrayRef<const unsigned char>(dex_data_memory_);
      }
    }
  }

  art::ArrayRef<const unsigned char> GetNewOriginalDexFile() const {
    DCHECK(IsInitialized());
    if (redefined_) {
      return current_dex_file_;
    } else {
      return art::ArrayRef<const unsigned char>();
    }
  }

  bool ContainsAddress(uintptr_t ptr) const {
    return dex_data_mmap_.IsValid() &&
        reinterpret_cast<uintptr_t>(dex_data_mmap_.Begin()) <= ptr &&
        reinterpret_cast<uintptr_t>(dex_data_mmap_.End()) > ptr;
  }

  bool IsModified() const REQUIRES_SHARED(art::Locks::mutator_lock_);

  bool IsInitialized() const {
    return initialized_;
  }

  jclass GetClass() const {
    DCHECK(IsInitialized());
    return klass_;
  }

  jobject GetLoader() const {
    DCHECK(IsInitialized());
    return loader_;
  }

  const std::string& GetName() const {
    DCHECK(IsInitialized());
    return name_;
  }

  bool IsLazyDefinition() const {
    DCHECK(IsInitialized());
    return dex_data_mmap_.IsValid() &&
        dex_data_.data() == dex_data_mmap_.Begin() &&
        dex_data_mmap_.GetProtect() == PROT_NONE;
  }

  jobject GetProtectionDomain() const {
    DCHECK(IsInitialized());
    return protection_domain_;
  }

  art::ArrayRef<const unsigned char> GetDexData() const {
    DCHECK(IsInitialized());
    return dex_data_;
  }

  void InitializeMemory() const;

 private:
  jvmtiError InitCommon(art::Thread* self, jclass klass);

  template<typename GetOriginalDexFile>
  void InitWithDex(GetOriginalDexFile get_original, const art::DexFile* quick_dex)
      REQUIRES_SHARED(art::Locks::mutator_lock_);

  jclass klass_;
  jobject loader_;
  std::string name_;
  jobject protection_domain_;

  // Mmap that will be filled with the original-dex-file lazily if it needs to be de-quickened or
  // de-compact-dex'd
  mutable art::MemMap dex_data_mmap_;
  // This is a temporary mmap we will use to be able to fill the dex file data atomically.
  mutable art::MemMap temp_mmap_;

  // A unique_ptr to the current dex_data if it needs to be cleaned up.
  std::vector<unsigned char> dex_data_memory_;

  const art::DexFile* initial_dex_file_unquickened_;

  // A ref to the current dex data. This is either dex_data_memory_, or current_dex_file_. This is
  // what the dex file will be turned into.
  art::ArrayRef<const unsigned char> dex_data_;

  // This is only used if we failed to create a mmap to store the dequickened data
  std::vector<unsigned char> current_dex_memory_;

  // This is a dequickened version of what is loaded right now. It is either current_dex_memory_ (if
  // no other redefinition has ever happened to this) or the current dex_file_ directly (if this
  // class has been redefined, thus it cannot have any quickened stuff).
  art::ArrayRef<const unsigned char> current_dex_file_;

  bool redefined_;

  // If we got the initial dex_data_ from a class_ext
  bool from_class_ext_;

  bool initialized_;

  DISALLOW_COPY_AND_ASSIGN(ArtClassDefinition);
};

}  // namespace openjdkjvmti

#endif  // ART_OPENJDKJVMTI_TI_CLASS_DEFINITION_H_
