/*
 * 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.
 */

#ifndef ART_RUNTIME_INTERN_TABLE_INL_H_
#define ART_RUNTIME_INTERN_TABLE_INL_H_

#include "intern_table.h"

#include "dex/utf.h"
#include "gc/space/image_space.h"
#include "gc_root-inl.h"
#include "image.h"
#include "mirror/string-inl.h"
#include "thread-current-inl.h"

namespace art {

inline std::size_t InternTable::StringHash::operator()(const GcRoot<mirror::String>& root) const {
  if (kIsDebugBuild) {
    Locks::mutator_lock_->AssertSharedHeld(Thread::Current());
  }
  // An additional cast to prevent undesired sign extension.
  return static_cast<size_t>(
      static_cast<uint32_t>(root.Read<kWithoutReadBarrier>()->GetHashCode()));
}

inline bool InternTable::StringEquals::operator()(const GcRoot<mirror::String>& a,
                                                  const GcRoot<mirror::String>& b) const {
  if (kIsDebugBuild) {
    Locks::mutator_lock_->AssertSharedHeld(Thread::Current());
  }
  return a.Read<kWithoutReadBarrier>()->Equals(b.Read<kWithoutReadBarrier>());
}

inline bool InternTable::StringEquals::operator()(const GcRoot<mirror::String>& a,
                                                  const Utf8String& b) const {
  if (kIsDebugBuild) {
    Locks::mutator_lock_->AssertSharedHeld(Thread::Current());
  }
  ObjPtr<mirror::String> a_string = a.Read<kWithoutReadBarrier>();
  uint32_t a_length = static_cast<uint32_t>(a_string->GetLength());
  if (a_length != b.GetUtf16Length()) {
    return false;
  }
  if (a_string->IsCompressed()) {
    size_t b_byte_count = strlen(b.GetUtf8Data());
    size_t b_utf8_length = CountModifiedUtf8Chars(b.GetUtf8Data(), b_byte_count);
    // Modified UTF-8 single byte character range is 0x01 .. 0x7f
    // The string compression occurs on regular ASCII with same exact range,
    // not on extended ASCII which up to 0xff
    const bool is_b_regular_ascii = (b_byte_count == b_utf8_length);
    if (is_b_regular_ascii) {
      return memcmp(b.GetUtf8Data(),
                    a_string->GetValueCompressed(), a_length * sizeof(uint8_t)) == 0;
    } else {
      return false;
    }
  } else {
    const uint16_t* a_value = a_string->GetValue();
    return CompareModifiedUtf8ToUtf16AsCodePointValues(b.GetUtf8Data(), a_value, a_length) == 0;
  }
}

template <typename Visitor>
inline void InternTable::AddImageStringsToTable(gc::space::ImageSpace* image_space,
                                                const Visitor& visitor) {
  DCHECK(image_space != nullptr);
  // Only add if we have the interned strings section.
  const ImageHeader& header = image_space->GetImageHeader();
  const ImageSection& section = header.GetInternedStringsSection();
  if (section.Size() > 0) {
    AddTableFromMemory(image_space->Begin() + section.Offset(), visitor, !header.IsAppImage());
  }
}

template <typename Visitor>
inline size_t InternTable::AddTableFromMemory(const uint8_t* ptr,
                                              const Visitor& visitor,
                                              bool is_boot_image) {
  size_t read_count = 0;
  UnorderedSet set(ptr, /*make copy*/false, &read_count);
  {
    // Hold the lock while calling the visitor to prevent possible race
    // conditions with another thread adding intern strings.
    MutexLock mu(Thread::Current(), *Locks::intern_table_lock_);
    // Visit the unordered set, may remove elements.
    visitor(set);
    if (!set.empty()) {
      strong_interns_.AddInternStrings(std::move(set), is_boot_image);
    }
  }
  return read_count;
}

inline void InternTable::Table::AddInternStrings(UnorderedSet&& intern_strings,
                                                 bool is_boot_image) {
  static constexpr bool kCheckDuplicates = kIsDebugBuild;
  if (kCheckDuplicates) {
    // Avoid doing read barriers since the space might not yet be added to the heap.
    // See b/117803941
    for (GcRoot<mirror::String>& string : intern_strings) {
      CHECK(Find(string.Read<kWithoutReadBarrier>()) == nullptr)
          << "Already found " << string.Read<kWithoutReadBarrier>()->ToModifiedUtf8()
          << " in the intern table";
    }
  }
  // Insert at the front since we add new interns into the back.
  tables_.insert(tables_.begin(),
                 InternalTable(std::move(intern_strings), is_boot_image));
}

template <typename Visitor>
inline void InternTable::VisitInterns(const Visitor& visitor,
                                      bool visit_boot_images,
                                      bool visit_non_boot_images) {
  auto visit_tables = [&](std::vector<Table::InternalTable>& tables)
      NO_THREAD_SAFETY_ANALYSIS {
    for (Table::InternalTable& table : tables) {
      // Determine if we want to visit the table based on the flags..
      const bool visit =
          (visit_boot_images && table.IsBootImage()) ||
          (visit_non_boot_images && !table.IsBootImage());
      if (visit) {
        for (auto& intern : table.set_) {
          visitor(intern);
        }
      }
    }
  };
  visit_tables(strong_interns_.tables_);
  visit_tables(weak_interns_.tables_);
}

inline size_t InternTable::CountInterns(bool visit_boot_images,
                                        bool visit_non_boot_images) const {
  size_t ret = 0u;
  auto visit_tables = [&](const std::vector<Table::InternalTable>& tables)
      NO_THREAD_SAFETY_ANALYSIS {
    for (const Table::InternalTable& table : tables) {
      // Determine if we want to visit the table based on the flags..
      const bool visit =
          (visit_boot_images && table.IsBootImage()) ||
          (visit_non_boot_images && !table.IsBootImage());
      if (visit) {
        ret += table.set_.size();
      }
    }
  };
  visit_tables(strong_interns_.tables_);
  visit_tables(weak_interns_.tables_);
  return ret;
}

}  // namespace art

#endif  // ART_RUNTIME_INTERN_TABLE_INL_H_
