1// Copyright 2012 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "src/runtime/runtime.h"
6
7#include "src/assembler.h"
8#include "src/base/hashmap.h"
9#include "src/contexts.h"
10#include "src/handles-inl.h"
11#include "src/heap/heap.h"
12#include "src/isolate.h"
13#include "src/runtime/runtime-utils.h"
14
15namespace v8 {
16namespace internal {
17
18// Header of runtime functions.
19#define F(name, number_of_args, result_size)                    \
20  Object* Runtime_##name(int args_length, Object** args_object, \
21                         Isolate* isolate);
22FOR_EACH_INTRINSIC_RETURN_OBJECT(F)
23#undef F
24
25#define P(name, number_of_args, result_size)                       \
26  ObjectPair Runtime_##name(int args_length, Object** args_object, \
27                            Isolate* isolate);
28FOR_EACH_INTRINSIC_RETURN_PAIR(P)
29#undef P
30
31#define T(name, number_of_args, result_size)                         \
32  ObjectTriple Runtime_##name(int args_length, Object** args_object, \
33                              Isolate* isolate);
34FOR_EACH_INTRINSIC_RETURN_TRIPLE(T)
35#undef T
36
37
38#define F(name, number_of_args, result_size)                                  \
39  {                                                                           \
40    Runtime::k##name, Runtime::RUNTIME, #name, FUNCTION_ADDR(Runtime_##name), \
41        number_of_args, result_size                                           \
42  }                                                                           \
43  ,
44
45
46#define I(name, number_of_args, result_size)                       \
47  {                                                                \
48    Runtime::kInline##name, Runtime::INLINE, "_" #name,            \
49        FUNCTION_ADDR(Runtime_##name), number_of_args, result_size \
50  }                                                                \
51  ,
52
53static const Runtime::Function kIntrinsicFunctions[] = {
54  FOR_EACH_INTRINSIC(F)
55  FOR_EACH_INTRINSIC(I)
56};
57
58#undef I
59#undef F
60
61namespace {
62
63V8_DECLARE_ONCE(initialize_function_name_map_once);
64static const base::CustomMatcherHashMap* kRuntimeFunctionNameMap;
65
66struct IntrinsicFunctionIdentifier {
67  IntrinsicFunctionIdentifier(const unsigned char* data, const int length)
68      : data_(data), length_(length) {}
69
70  static bool Match(void* key1, void* key2) {
71    const IntrinsicFunctionIdentifier* lhs =
72        static_cast<IntrinsicFunctionIdentifier*>(key1);
73    const IntrinsicFunctionIdentifier* rhs =
74        static_cast<IntrinsicFunctionIdentifier*>(key2);
75    if (lhs->length_ != rhs->length_) return false;
76    return CompareCharsUnsigned(reinterpret_cast<const uint8_t*>(lhs->data_),
77                                reinterpret_cast<const uint8_t*>(rhs->data_),
78                                rhs->length_) == 0;
79  }
80
81  uint32_t Hash() {
82    return StringHasher::HashSequentialString<uint8_t>(
83        data_, length_, v8::internal::kZeroHashSeed);
84  }
85
86  const unsigned char* data_;
87  const int length_;
88};
89
90void InitializeIntrinsicFunctionNames() {
91  base::CustomMatcherHashMap* function_name_map =
92      new base::CustomMatcherHashMap(IntrinsicFunctionIdentifier::Match);
93  for (size_t i = 0; i < arraysize(kIntrinsicFunctions); ++i) {
94    const Runtime::Function* function = &kIntrinsicFunctions[i];
95    IntrinsicFunctionIdentifier* identifier = new IntrinsicFunctionIdentifier(
96        reinterpret_cast<const unsigned char*>(function->name),
97        static_cast<int>(strlen(function->name)));
98    base::HashMap::Entry* entry =
99        function_name_map->InsertNew(identifier, identifier->Hash());
100    entry->value = const_cast<Runtime::Function*>(function);
101  }
102  kRuntimeFunctionNameMap = function_name_map;
103}
104
105}  // namespace
106
107const Runtime::Function* Runtime::FunctionForName(const unsigned char* name,
108                                                  int length) {
109  base::CallOnce(&initialize_function_name_map_once,
110                 &InitializeIntrinsicFunctionNames);
111  IntrinsicFunctionIdentifier identifier(name, length);
112  base::HashMap::Entry* entry =
113      kRuntimeFunctionNameMap->Lookup(&identifier, identifier.Hash());
114  if (entry) {
115    return reinterpret_cast<Function*>(entry->value);
116  }
117  return NULL;
118}
119
120
121const Runtime::Function* Runtime::FunctionForEntry(Address entry) {
122  for (size_t i = 0; i < arraysize(kIntrinsicFunctions); ++i) {
123    if (entry == kIntrinsicFunctions[i].entry) {
124      return &(kIntrinsicFunctions[i]);
125    }
126  }
127  return NULL;
128}
129
130
131const Runtime::Function* Runtime::FunctionForId(Runtime::FunctionId id) {
132  return &(kIntrinsicFunctions[static_cast<int>(id)]);
133}
134
135
136const Runtime::Function* Runtime::RuntimeFunctionTable(Isolate* isolate) {
137  if (isolate->external_reference_redirector()) {
138    // When running with the simulator we need to provide a table which has
139    // redirected runtime entry addresses.
140    if (!isolate->runtime_state()->redirected_intrinsic_functions()) {
141      size_t function_count = arraysize(kIntrinsicFunctions);
142      Function* redirected_functions = new Function[function_count];
143      memcpy(redirected_functions, kIntrinsicFunctions,
144             sizeof(kIntrinsicFunctions));
145      for (size_t i = 0; i < function_count; i++) {
146        ExternalReference redirected_entry(static_cast<Runtime::FunctionId>(i),
147                                           isolate);
148        redirected_functions[i].entry = redirected_entry.address();
149      }
150      isolate->runtime_state()->set_redirected_intrinsic_functions(
151          redirected_functions);
152    }
153
154    return isolate->runtime_state()->redirected_intrinsic_functions();
155  } else {
156    return kIntrinsicFunctions;
157  }
158}
159
160
161std::ostream& operator<<(std::ostream& os, Runtime::FunctionId id) {
162  return os << Runtime::FunctionForId(id)->name;
163}
164
165
166}  // namespace internal
167}  // namespace v8
168