// Copyright 2013 Google Inc. All Rights Reserved.
//
// 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 "syzygy/agent/profiler/symbol_map.h"

namespace agent {
namespace profiler {

base::subtle::Atomic32 SymbolMap::Symbol::next_symbol_id_ = 0;

SymbolMap::SymbolMap() {
}

SymbolMap::~SymbolMap() {
}

void SymbolMap::AddSymbol(const void* start_addr,
                          size_t length,
                          const base::StringPiece& name) {
  base::AutoLock hold(lock_);

  scoped_refptr<Symbol> symbol = new Symbol(name, start_addr);
  // TODO(siggi): Perhaps this should be an error?
  if (!symbol)
    return;

  Range range(reinterpret_cast<const uint8*>(start_addr), length);
  RetireRangeUnlocked(range);

  bool inserted = addr_space_.Insert(
      Range(reinterpret_cast<const uint8*>(start_addr), length), symbol);
  DCHECK(inserted);
}

void SymbolMap::MoveSymbol(const void* old_addr, const void* new_addr) {
  base::AutoLock hold(lock_);

  SymbolAddressSpace::RangeMapIter found =
      addr_space_.FindFirstIntersection(
          Range(reinterpret_cast<const uint8*>(old_addr), 1));

  // If we don't have a record of the original symbol, then we can't move it.
  // This may occur if a symbol provider starts pushing events only after its
  // address space has been stocked.
  if (found == addr_space_.end() || found->first.start() != old_addr)
    return;

  scoped_refptr<Symbol> symbol = found->second;

  // Note the fact that it's been moved.
  symbol->Move(new_addr);

  size_t length = found->first.size();
  addr_space_.Remove(found);

  RetireRangeUnlocked(
      Range(reinterpret_cast<const uint8*>(new_addr), length));

  bool inserted = addr_space_.Insert(
      Range(reinterpret_cast<const uint8*>(new_addr), length), symbol);
  DCHECK(inserted);
}

scoped_refptr<SymbolMap::Symbol> SymbolMap::FindSymbol(const void* addr) {
  base::AutoLock hold(lock_);

  SymbolAddressSpace::RangeMapIter found =
      addr_space_.FindFirstIntersection(
          Range(reinterpret_cast<const uint8*>(addr), 1));

  if (found == addr_space_.end())
    return NULL;

  return found->second;
}

void SymbolMap::RetireRangeUnlocked(const Range& range) {
  lock_.AssertAcquired();

  SymbolAddressSpace::RangeMapIterPair found =
      addr_space_.FindIntersecting(range);
  SymbolAddressSpace::iterator it = found.first;
  for (; it != found.second; ++it)
    found.first->second->Invalidate();

  addr_space_.Remove(found);
}

SymbolMap::Symbol::Symbol(const base::StringPiece& name, const void* address)
    : name_(name.begin(), name.end()),
      move_count_(0),
      id_(0),
      address_(address) {
}

bool SymbolMap::Symbol::EnsureHasId() {
  DCHECK(!invalid());
  if (base::subtle::Acquire_Load(&id_) != 0)
    return false;

  // Allocate a new symbol ID. Note that we may be racing against other
  // threads to assign this ID to the symbol, hence the compare-and-swap
  // below. In the case of a race, this ID may not get allocated to any
  // symbol.
  base::subtle::Atomic32 next_id = 0;
  do {
    next_id = base::subtle::NoBarrier_AtomicIncrement(&next_symbol_id_, 1);
  } while (next_id == 0);

  return base::subtle::NoBarrier_CompareAndSwap(&id_, 0, next_id) == 0;
}

void SymbolMap::Symbol::Invalidate() {
  DCHECK(!invalid());
  Move(NULL);
}

void SymbolMap::Symbol::Move(const void* new_address) {
  DCHECK(!invalid());
  // TODO(siggi): The intent here is to make sure other cores see the new
  //     value without delay. The barrier may not be what's needed to do that?
  address_ = new_address;
  base::subtle::Barrier_AtomicIncrement(&move_count_, 1);
}

}  // namespace profiler
}  // namespace agent
