/*
 * Copyright (c) 2016, 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.
 *
 * 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.
 *
 */

#include "precompiled.hpp"
#include "classfile/moduleEntry.hpp"
#include "classfile/packageEntry.hpp"
#include "memory/resourceArea.hpp"
#include "oops/symbol.hpp"
#include "runtime/handles.inline.hpp"
#include "trace/traceMacros.hpp"
#include "utilities/events.hpp"
#include "utilities/growableArray.hpp"
#include "utilities/hashtable.inline.hpp"
#include "utilities/ostream.hpp"

// Returns true if this package specifies m as a qualified export, including through an unnamed export
bool PackageEntry::is_qexported_to(ModuleEntry* m) const {
  assert(m != NULL, "No module to lookup in this package's qualified exports list");
  MutexLocker m1(Module_lock);
  if (is_exported_allUnnamed() && !m->is_named()) {
    return true;
  } else if (!has_qual_exports_list()) {
    return false;
  } else {
    return _qualified_exports->contains(m);
  }
}

// Add a module to the package's qualified export list.
void PackageEntry::add_qexport(ModuleEntry* m) {
  assert_locked_or_safepoint(Module_lock);
  if (!has_qual_exports_list()) {
    // Lazily create a package's qualified exports list.
    // Initial size is small, do not anticipate export lists to be large.
    _qualified_exports =
      new (ResourceObj::C_HEAP, mtModule) GrowableArray<ModuleEntry*>(QUAL_EXP_SIZE, true);
  }
  _qualified_exports->append_if_missing(m);
}

// Set the package's exported states based on the value of the ModuleEntry.
void PackageEntry::set_exported(ModuleEntry* m) {
  MutexLocker m1(Module_lock);
  if (is_unqual_exported()) {
    // An exception could be thrown, but choose to simply ignore.
    // Illegal to convert an unqualified exported package to be qualifiedly exported
    return;
  }

  if (m == NULL) {
    // NULL indicates the package is being unqualifiedly exported
    if (has_qual_exports_list()) {
      // Legit to transition a package from being qualifiedly exported
      // to unqualified.  Clean up the qualified lists at the next
      // safepoint.
      _exported_pending_delete = _qualified_exports;
    }

    // Mark package as unqualifiedly exported
    set_unqual_exported();

  } else {
    // Add the exported module
    add_qexport(m);
  }
}

void PackageEntry::set_is_exported_allUnnamed() {
  MutexLocker m1(Module_lock);
  if (!is_unqual_exported()) {
   _is_exported_allUnnamed = true;
  }
}

// Remove dead module entries within the package's exported list.
void PackageEntry::purge_qualified_exports() {
  assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
  if (_qualified_exports != NULL) {
    // Go backwards because this removes entries that are dead.
    int len = _qualified_exports->length();
    for (int idx = len - 1; idx >= 0; idx--) {
      ModuleEntry* module_idx = _qualified_exports->at(idx);
      ClassLoaderData* cld = module_idx->loader();
      if (cld->is_unloading()) {
        _qualified_exports->delete_at(idx);
      }
    }
  }
}

void PackageEntry::delete_qualified_exports() {
  assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
  if (_exported_pending_delete != NULL) {
    // If a transition occurred from qualified to unqualified, the _qualified_exports
    // field should have been NULL'ed out.
    assert(_qualified_exports == NULL, "Package's exported pending delete, exported list should not be active");
    delete _exported_pending_delete;
  }

  if (_qualified_exports != NULL) {
    delete _qualified_exports;
  }

  _exported_pending_delete = NULL;
  _qualified_exports = NULL;
}

PackageEntryTable::PackageEntryTable(int table_size)
  : Hashtable<Symbol*, mtModule>(table_size, sizeof(PackageEntry))
{
}

PackageEntryTable::~PackageEntryTable() {
  assert_locked_or_safepoint(Module_lock);

  // Walk through all buckets and all entries in each bucket,
  // freeing each entry.
  for (int i = 0; i < table_size(); ++i) {
    for (PackageEntry* p = bucket(i); p != NULL;) {
      PackageEntry* to_remove = p;
      // read next before freeing.
      p = p->next();

      // Clean out the C heap allocated qualified exports list first before freeing the entry
      to_remove->delete_qualified_exports();
      to_remove->name()->decrement_refcount();

      // Unlink from the Hashtable prior to freeing
      unlink_entry(to_remove);
      FREE_C_HEAP_ARRAY(char, to_remove);
    }
  }
  assert(number_of_entries() == 0, "should have removed all entries");
  assert(new_entry_free_list() == NULL, "entry present on PackageEntryTable's free list");
  free_buckets();
}

PackageEntry* PackageEntryTable::new_entry(unsigned int hash, Symbol* name, ModuleEntry* module) {
  assert_locked_or_safepoint(Module_lock);
  PackageEntry* entry = (PackageEntry*) NEW_C_HEAP_ARRAY(char, entry_size(), mtModule);

  // Initialize everything BasicHashtable would
  entry->set_next(NULL);
  entry->set_hash(hash);
  entry->set_literal(name);

  TRACE_INIT_PACKAGE_ID(entry);

  // Initialize fields specific to a PackageEntry
  entry->init();
  entry->name()->increment_refcount();
  if (!module->is_named()) {
    // Set the exported state to true because all packages
    // within the unnamed module are unqualifiedly exported
    entry->set_unqual_exported();
  }
  entry->set_module(module);
  return entry;
}

void PackageEntryTable::add_entry(int index, PackageEntry* new_entry) {
  assert_locked_or_safepoint(Module_lock);
  Hashtable<Symbol*, mtModule>::add_entry(index, (HashtableEntry<Symbol*, mtModule>*)new_entry);
}

// Create package in loader's package entry table and return the entry.
// If entry already exists, return null.  Assume Module lock was taken by caller.
PackageEntry* PackageEntryTable::locked_create_entry_or_null(Symbol* name, ModuleEntry* module) {
  assert_locked_or_safepoint(Module_lock);
  // Check if package already exists.  Return NULL if it does.
  if (lookup_only(name) != NULL) {
    return NULL;
  } else {
    PackageEntry* entry = new_entry(compute_hash(name), name, module);
    add_entry(index_for(name), entry);
    return entry;
  }
}

PackageEntry* PackageEntryTable::lookup(Symbol* name, ModuleEntry* module) {
  PackageEntry* p = lookup_only(name);
  if (p != NULL) {
    return p;
  } else {
    // If not found, add to table. Grab the PackageEntryTable lock first.
    MutexLocker ml(Module_lock);

    // Since look-up was done lock-free, we need to check if another thread beat
    // us in the race to insert the package.
    PackageEntry* test = lookup_only(name);
    if (test != NULL) {
      // A race occurred and another thread introduced the package.
      return test;
    } else {
      assert(module != NULL, "module should never be null");
      PackageEntry* entry = new_entry(compute_hash(name), name, module);
      add_entry(index_for(name), entry);
      return entry;
    }
  }
}

PackageEntry* PackageEntryTable::lookup_only(Symbol* name) {
  int index = index_for(name);
  for (PackageEntry* p = bucket(index); p != NULL; p = p->next()) {
    if (p->name()->fast_compare(name) == 0) {
      return p;
    }
  }
  return NULL;
}

// Called when a define module for java.base is being processed.
// Verify the packages loaded thus far are in java.base's package list.
void PackageEntryTable::verify_javabase_packages(GrowableArray<Symbol*> *pkg_list) {
  for (int i = 0; i < table_size(); i++) {
    for (PackageEntry* entry = bucket(i);
                       entry != NULL;
                       entry = entry->next()) {
      ModuleEntry* m = entry->module();
      Symbol* module_name = (m == NULL ? NULL : m->name());
      if (module_name != NULL &&
          (module_name->fast_compare(vmSymbols::java_base()) == 0) &&
          !pkg_list->contains(entry->name())) {
        ResourceMark rm;
        vm_exit_during_initialization("A non-java.base package was loaded prior to module system initialization", entry->name()->as_C_string());
      }
    }
  }

}

// iteration of qualified exports
void PackageEntry::package_exports_do(ModuleClosure* const f) {
  assert_locked_or_safepoint(Module_lock);
  assert(f != NULL, "invariant");

  if (has_qual_exports_list()) {
    int qe_len = _qualified_exports->length();

    for (int i = 0; i < qe_len; ++i) {
      f->do_module(_qualified_exports->at(i));
    }
  }
}

// Remove dead entries from all packages' exported list
void PackageEntryTable::purge_all_package_exports() {
  assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
  for (int i = 0; i < table_size(); i++) {
    for (PackageEntry* entry = bucket(i);
                       entry != NULL;
                       entry = entry->next()) {
      if (entry->exported_pending_delete()) {
        // exported list is pending deletion due to a transition
        // from qualified to unqualified
        entry->delete_qualified_exports();
      } else if (entry->is_qual_exported()) {
        entry->purge_qualified_exports();
      }
    }
  }
}

void PackageEntryTable::print(outputStream* st) {
  st->print_cr("Package Entry Table (table_size=%d, entries=%d)",
               table_size(), number_of_entries());
  for (int i = 0; i < table_size(); i++) {
    for (PackageEntry* probe = bucket(i);
                       probe != NULL;
                       probe = probe->next()) {
      probe->print(st);
    }
  }
}

void PackageEntry::print(outputStream* st) {
  ResourceMark rm;
  st->print_cr("package entry "PTR_FORMAT" name %s module %s classpath_index "
               INT32_FORMAT " is_exported_unqualified %d is_exported_allUnnamed %d " "next "PTR_FORMAT,
               p2i(this), name()->as_C_string(),
               (module()->is_named() ? module()->name()->as_C_string() : UNNAMED_MODULE),
               _classpath_index, _is_exported_unqualified, _is_exported_allUnnamed, p2i(next()));
}

void PackageEntryTable::verify() {
  int element_count = 0;
  for (int index = 0; index < table_size(); index++) {
    for (PackageEntry* probe = bucket(index);
                              probe != NULL;
                              probe = probe->next()) {
      probe->verify();
      element_count++;
    }
  }
  guarantee(number_of_entries() == element_count,
            "Verify of Package Entry Table failed");
  debug_only(verify_lookup_length((double)number_of_entries() / table_size()));
}

void PackageEntry::verify() {
  guarantee(name() != NULL, "A package entry must have a corresponding symbol name.");
}
