// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include "vm/tags.h"

#include "vm/isolate.h"
#include "vm/json_stream.h"
#include "vm/native_entry.h"
#include "vm/runtime_entry.h"
#include "vm/object.h"

namespace dart {

const char* VMTag::TagName(uword tag) {
  if (IsNativeEntryTag(tag)) {
    const uint8_t* native_reverse_lookup = NativeEntry::ResolveSymbol(tag);
    if (native_reverse_lookup != NULL) {
      return reinterpret_cast<const char*>(native_reverse_lookup);
    }
    return "Unknown native entry";
  } else if (IsRuntimeEntryTag(tag)) {
    const char* runtime_entry_name = RuntimeEntryTagName(tag);
    ASSERT(runtime_entry_name != NULL);
    return runtime_entry_name;
  }
  ASSERT(tag != kInvalidTagId);
  ASSERT(tag < kNumVMTags);
  const TagEntry& entry = entries_[tag];
  ASSERT(entry.id == tag);
  return entry.name;
}


bool VMTag::IsNativeEntryTag(uword tag) {
  return (tag > kLastTagId) && !IsRuntimeEntryTag(tag);
}


static RuntimeEntry* runtime_entry_list = NULL;


bool VMTag::IsRuntimeEntryTag(uword id) {
  const RuntimeEntry* current = runtime_entry_list;
  while (current != NULL) {
    if (reinterpret_cast<uword>(current->function()) == id) {
      return true;
    }
    current = current->next();
  }
  return false;
}


const char* VMTag::RuntimeEntryTagName(uword id) {
  const RuntimeEntry* current = runtime_entry_list;
  while (current != NULL) {
    if (reinterpret_cast<uword>(current->function()) == id) {
      return current->name();
    }
    current = current->next();
  }
  return NULL;
}


void VMTag::RegisterRuntimeEntry(RuntimeEntry* runtime_entry) {
  ASSERT(runtime_entry != NULL);
  runtime_entry->set_next(runtime_entry_list);
  runtime_entry_list = runtime_entry;
}


VMTag::TagEntry VMTag::entries_[] = {
  { "InvalidTag", kInvalidTagId, },
#define DEFINE_VM_TAG_ENTRY(tag)                                               \
  { ""#tag, k##tag##TagId },
  VM_TAG_LIST(DEFINE_VM_TAG_ENTRY)
#undef DEFINE_VM_TAG_ENTRY
  { "kNumVMTags", kNumVMTags },
};


VMTagScope::VMTagScope(Thread* thread, uword tag, bool conditional_set)
    : StackResource(thread) {
  ASSERT(isolate() != NULL);
  previous_tag_ = isolate()->vm_tag();
  if (conditional_set) {
    isolate()->set_vm_tag(tag);
  }
}


VMTagScope::~VMTagScope() {
  ASSERT(isolate() != NULL);
  isolate()->set_vm_tag(previous_tag_);
}


VMTagCounters::VMTagCounters() {
  for (intptr_t i = 0; i < VMTag::kNumVMTags; i++) {
    counters_[i] = 0;
  }
}


void VMTagCounters::Increment(uword tag) {
  if (VMTag::IsRuntimeEntryTag(tag)) {
    counters_[VMTag::kRuntimeTagId]++;
    return;
  } else if (tag > VMTag::kNumVMTags) {
    // Assume native entry.
    counters_[VMTag::kNativeTagId]++;
    return;
  }
  ASSERT(tag != VMTag::kInvalidTagId);
  ASSERT(tag < VMTag::kNumVMTags);
  counters_[tag]++;
}


int64_t VMTagCounters::count(uword tag) {
  ASSERT(tag != VMTag::kInvalidTagId);
  ASSERT(tag < VMTag::kNumVMTags);
  return counters_[tag];
}


void VMTagCounters::PrintToJSONObject(JSONObject* obj) {
  {
    JSONArray arr(obj, "names");
    for (intptr_t i = 1; i < VMTag::kNumVMTags; i++) {
      arr.AddValue(VMTag::TagName(i));
    }
  }
  {
    JSONArray arr(obj, "counters");
    for (intptr_t i = 1; i < VMTag::kNumVMTags; i++) {
      arr.AddValue64(counters_[i]);
    }
  }
}


const char* UserTags::TagName(uword tag_id) {
  ASSERT(tag_id >= kUserTagIdOffset);
  ASSERT(tag_id < kUserTagIdOffset + kMaxUserTags);
  Isolate* isolate = Isolate::Current();
  const UserTag& tag =
      UserTag::Handle(isolate, UserTag::FindTagById(tag_id));
  ASSERT(!tag.IsNull());
  const String& label = String::Handle(isolate, tag.label());
  return label.ToCString();
}


}  // namespace dart
