/*
 * Copyright 2022 WebAssembly Community Group participants
 *
 * 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 <limits>
#include <mutex>

#include "istring.h"
#include "mixed_arena.h"

namespace wasm {

const char* IString::interned(std::string_view s) {
  // A set of interned Views, i.e., that contains our pascal-style strings. We
  // need to query this using a std::string_view, as that is what we receive as
  // input (turning it into pascal-style storage would add overhead). To do so,
  // use overloading in the hash and equality functions (which works thanks to
  // `is_transparent`).
  struct InternedHash {
    using is_transparent = void;
    size_t operator()(View v) const {
      return std::hash<std::string_view>{}(v.view());
    }
    size_t operator()(std::string_view sv) const {
      return std::hash<std::string_view>{}(sv);
    }
  };
  struct InternedEqual {
    using is_transparent = void;
    bool operator()(View a, View b) const { return a.view() == b.view(); }
    bool operator()(std::string_view a, View b) const { return a == b.view(); }
    bool operator()(View a, std::string_view b) const { return a.view() == b; }
    bool operator()(std::string_view a, std::string_view b) const {
      return a == b;
    }
  };
  using StringSet = std::unordered_set<View, InternedHash, InternedEqual>;

  // The authoritative global set of interned string views.
  static StringSet globalStrings;

  // The global backing store for interned strings that do not otherwise have
  // stable addresses.
  static MixedArena arena;

  // Guards access to `globalStrings`. (note: `arena` is thread-safe anyhow)
  static std::mutex mutex;

  // A thread-local cache of strings to reduce contention.
  thread_local static StringSet localStrings;

  if (auto it = localStrings.find(s); it != localStrings.end()) {
    // We already had a local copy of this string.
    return it->internal;
  }

  // No copy yet in the local cache. Check the global cache.
  std::unique_lock<std::mutex> lock(mutex);
  if (auto it = globalStrings.find(s); it != globalStrings.end()) {
    // We already had a global copy of this string. Cache it locally.
    localStrings.insert(*it);
    return it->internal;
  }

  // We have a new string. Create a copy of the data at a stable address with a
  // header we can use. Make sure it is null terminated so legacy uses that get
  // a C string still work.
  size_t size = s.size();
  // The string's size must fit in 32 bits.
  assert(size <= std::numeric_limits<uint32_t>::max());
  char* buffer =
    (char*)arena.allocSpace(sizeof(uint32_t) + size + 1, alignof(uint32_t));
  *(uint32_t*)(buffer) = size;
  char* data = buffer + sizeof(uint32_t);
  std::copy(s.begin(), s.end(), data);
  data[size] = '\0';

  // Intern our new string.
  View v{data};
  globalStrings.insert(v);
  localStrings.insert(v);
  return data;
}

} // namespace wasm
