// Copyright 2012 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/runtime/runtime.h"

#include "src/assembler.h"
#include "src/base/hashmap.h"
#include "src/contexts.h"
#include "src/handles-inl.h"
#include "src/heap/heap.h"
#include "src/isolate.h"
#include "src/objects-inl.h"
#include "src/runtime/runtime-utils.h"

namespace v8 {
namespace internal {

// Header of runtime functions.
#define F(name, number_of_args, result_size)                    \
  Object* Runtime_##name(int args_length, Object** args_object, \
                         Isolate* isolate);
FOR_EACH_INTRINSIC_RETURN_OBJECT(F)
#undef F

#define P(name, number_of_args, result_size)                       \
  ObjectPair Runtime_##name(int args_length, Object** args_object, \
                            Isolate* isolate);
FOR_EACH_INTRINSIC_RETURN_PAIR(P)
#undef P

#define T(name, number_of_args, result_size)                         \
  ObjectTriple Runtime_##name(int args_length, Object** args_object, \
                              Isolate* isolate);
FOR_EACH_INTRINSIC_RETURN_TRIPLE(T)
#undef T


#define F(name, number_of_args, result_size)                                  \
  {                                                                           \
    Runtime::k##name, Runtime::RUNTIME, #name, FUNCTION_ADDR(Runtime_##name), \
        number_of_args, result_size                                           \
  }                                                                           \
  ,


#define I(name, number_of_args, result_size)                       \
  {                                                                \
    Runtime::kInline##name, Runtime::INLINE, "_" #name,            \
        FUNCTION_ADDR(Runtime_##name), number_of_args, result_size \
  }                                                                \
  ,

static const Runtime::Function kIntrinsicFunctions[] = {
  FOR_EACH_INTRINSIC(F)
  FOR_EACH_INTRINSIC(I)
};

#undef I
#undef F

namespace {

V8_DECLARE_ONCE(initialize_function_name_map_once);
static const base::CustomMatcherHashMap* kRuntimeFunctionNameMap;

struct IntrinsicFunctionIdentifier {
  IntrinsicFunctionIdentifier(const unsigned char* data, const int length)
      : data_(data), length_(length) {}

  static bool Match(void* key1, void* key2) {
    const IntrinsicFunctionIdentifier* lhs =
        static_cast<IntrinsicFunctionIdentifier*>(key1);
    const IntrinsicFunctionIdentifier* rhs =
        static_cast<IntrinsicFunctionIdentifier*>(key2);
    if (lhs->length_ != rhs->length_) return false;
    return CompareCharsUnsigned(reinterpret_cast<const uint8_t*>(lhs->data_),
                                reinterpret_cast<const uint8_t*>(rhs->data_),
                                rhs->length_) == 0;
  }

  uint32_t Hash() {
    return StringHasher::HashSequentialString<uint8_t>(
        data_, length_, v8::internal::kZeroHashSeed);
  }

  const unsigned char* data_;
  const int length_;
};

void InitializeIntrinsicFunctionNames() {
  base::CustomMatcherHashMap* function_name_map =
      new base::CustomMatcherHashMap(IntrinsicFunctionIdentifier::Match);
  for (size_t i = 0; i < arraysize(kIntrinsicFunctions); ++i) {
    const Runtime::Function* function = &kIntrinsicFunctions[i];
    IntrinsicFunctionIdentifier* identifier = new IntrinsicFunctionIdentifier(
        reinterpret_cast<const unsigned char*>(function->name),
        static_cast<int>(strlen(function->name)));
    base::HashMap::Entry* entry =
        function_name_map->InsertNew(identifier, identifier->Hash());
    entry->value = const_cast<Runtime::Function*>(function);
  }
  kRuntimeFunctionNameMap = function_name_map;
}

}  // namespace

const Runtime::Function* Runtime::FunctionForName(const unsigned char* name,
                                                  int length) {
  base::CallOnce(&initialize_function_name_map_once,
                 &InitializeIntrinsicFunctionNames);
  IntrinsicFunctionIdentifier identifier(name, length);
  base::HashMap::Entry* entry =
      kRuntimeFunctionNameMap->Lookup(&identifier, identifier.Hash());
  if (entry) {
    return reinterpret_cast<Function*>(entry->value);
  }
  return NULL;
}


const Runtime::Function* Runtime::FunctionForEntry(Address entry) {
  for (size_t i = 0; i < arraysize(kIntrinsicFunctions); ++i) {
    if (entry == kIntrinsicFunctions[i].entry) {
      return &(kIntrinsicFunctions[i]);
    }
  }
  return NULL;
}


const Runtime::Function* Runtime::FunctionForId(Runtime::FunctionId id) {
  return &(kIntrinsicFunctions[static_cast<int>(id)]);
}


const Runtime::Function* Runtime::RuntimeFunctionTable(Isolate* isolate) {
  if (isolate->external_reference_redirector()) {
    // When running with the simulator we need to provide a table which has
    // redirected runtime entry addresses.
    if (!isolate->runtime_state()->redirected_intrinsic_functions()) {
      size_t function_count = arraysize(kIntrinsicFunctions);
      Function* redirected_functions = new Function[function_count];
      memcpy(redirected_functions, kIntrinsicFunctions,
             sizeof(kIntrinsicFunctions));
      for (size_t i = 0; i < function_count; i++) {
        ExternalReference redirected_entry(static_cast<Runtime::FunctionId>(i),
                                           isolate);
        redirected_functions[i].entry = redirected_entry.address();
      }
      isolate->runtime_state()->set_redirected_intrinsic_functions(
          redirected_functions);
    }

    return isolate->runtime_state()->redirected_intrinsic_functions();
  } else {
    return kIntrinsicFunctions;
  }
}


std::ostream& operator<<(std::ostream& os, Runtime::FunctionId id) {
  return os << Runtime::FunctionForId(id)->name;
}


}  // namespace internal
}  // namespace v8
