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
15 namespace v8 {
16 namespace 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);
22 FOR_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);
28 FOR_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);
34 FOR_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
53 static const Runtime::Function kIntrinsicFunctions[] = {
54 FOR_EACH_INTRINSIC(F)
55 FOR_EACH_INTRINSIC(I)
56 };
57
58 #undef I
59 #undef F
60
61 namespace {
62
63 V8_DECLARE_ONCE(initialize_function_name_map_once);
64 static const base::CustomMatcherHashMap* kRuntimeFunctionNameMap;
65
66 struct IntrinsicFunctionIdentifier {
IntrinsicFunctionIdentifierv8::internal::__anonff20b14f0111::IntrinsicFunctionIdentifier67 IntrinsicFunctionIdentifier(const unsigned char* data, const int length)
68 : data_(data), length_(length) {}
69
Matchv8::internal::__anonff20b14f0111::IntrinsicFunctionIdentifier70 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
Hashv8::internal::__anonff20b14f0111::IntrinsicFunctionIdentifier81 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
InitializeIntrinsicFunctionNames()90 void 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
FunctionForName(const unsigned char * name,int length)107 const 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
FunctionForEntry(Address entry)121 const 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
FunctionForId(Runtime::FunctionId id)131 const Runtime::Function* Runtime::FunctionForId(Runtime::FunctionId id) {
132 return &(kIntrinsicFunctions[static_cast<int>(id)]);
133 }
134
135
RuntimeFunctionTable(Isolate * isolate)136 const 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
operator <<(std::ostream & os,Runtime::FunctionId id)161 std::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