• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/base/hashmap.h"
8 #include "src/contexts.h"
9 #include "src/handles-inl.h"
10 #include "src/heap/heap.h"
11 #include "src/isolate.h"
12 #include "src/objects-inl.h"
13 #include "src/reloc-info.h"
14 #include "src/runtime/runtime-utils.h"
15 
16 namespace v8 {
17 namespace internal {
18 
19 // Header of runtime functions.
20 #define F(name, number_of_args, result_size)                    \
21   Object* Runtime_##name(int args_length, Object** args_object, \
22                          Isolate* isolate);
23 FOR_EACH_INTRINSIC_RETURN_OBJECT(F)
24 #undef F
25 
26 #define P(name, number_of_args, result_size)                       \
27   ObjectPair Runtime_##name(int args_length, Object** args_object, \
28                             Isolate* isolate);
29 FOR_EACH_INTRINSIC_RETURN_PAIR(P)
30 #undef P
31 
32 #define F(name, number_of_args, result_size)                                  \
33   {                                                                           \
34     Runtime::k##name, Runtime::RUNTIME, #name, FUNCTION_ADDR(Runtime_##name), \
35         number_of_args, result_size                                           \
36   }                                                                           \
37   ,
38 
39 
40 #define I(name, number_of_args, result_size)                       \
41   {                                                                \
42     Runtime::kInline##name, Runtime::INLINE, "_" #name,            \
43         FUNCTION_ADDR(Runtime_##name), number_of_args, result_size \
44   }                                                                \
45   ,
46 
47 static const Runtime::Function kIntrinsicFunctions[] = {
48   FOR_EACH_INTRINSIC(F)
49   FOR_EACH_INTRINSIC(I)
50 };
51 
52 #undef I
53 #undef F
54 
55 namespace {
56 
57 V8_DECLARE_ONCE(initialize_function_name_map_once);
58 static const base::CustomMatcherHashMap* kRuntimeFunctionNameMap;
59 
60 struct IntrinsicFunctionIdentifier {
IntrinsicFunctionIdentifierv8::internal::__anon547708990111::IntrinsicFunctionIdentifier61   IntrinsicFunctionIdentifier(const unsigned char* data, const int length)
62       : data_(data), length_(length) {}
63 
Matchv8::internal::__anon547708990111::IntrinsicFunctionIdentifier64   static bool Match(void* key1, void* key2) {
65     const IntrinsicFunctionIdentifier* lhs =
66         static_cast<IntrinsicFunctionIdentifier*>(key1);
67     const IntrinsicFunctionIdentifier* rhs =
68         static_cast<IntrinsicFunctionIdentifier*>(key2);
69     if (lhs->length_ != rhs->length_) return false;
70     return CompareCharsUnsigned(reinterpret_cast<const uint8_t*>(lhs->data_),
71                                 reinterpret_cast<const uint8_t*>(rhs->data_),
72                                 rhs->length_) == 0;
73   }
74 
Hashv8::internal::__anon547708990111::IntrinsicFunctionIdentifier75   uint32_t Hash() {
76     return StringHasher::HashSequentialString<uint8_t>(
77         data_, length_, v8::internal::kZeroHashSeed);
78   }
79 
80   const unsigned char* data_;
81   const int length_;
82 };
83 
InitializeIntrinsicFunctionNames()84 void InitializeIntrinsicFunctionNames() {
85   base::CustomMatcherHashMap* function_name_map =
86       new base::CustomMatcherHashMap(IntrinsicFunctionIdentifier::Match);
87   for (size_t i = 0; i < arraysize(kIntrinsicFunctions); ++i) {
88     const Runtime::Function* function = &kIntrinsicFunctions[i];
89     IntrinsicFunctionIdentifier* identifier = new IntrinsicFunctionIdentifier(
90         reinterpret_cast<const unsigned char*>(function->name),
91         static_cast<int>(strlen(function->name)));
92     base::HashMap::Entry* entry =
93         function_name_map->InsertNew(identifier, identifier->Hash());
94     entry->value = const_cast<Runtime::Function*>(function);
95   }
96   kRuntimeFunctionNameMap = function_name_map;
97 }
98 
99 }  // namespace
100 
IsNonReturning(FunctionId id)101 bool Runtime::IsNonReturning(FunctionId id) {
102   switch (id) {
103     case Runtime::kThrowUnsupportedSuperError:
104     case Runtime::kThrowConstructorNonCallableError:
105     case Runtime::kThrowStaticPrototypeError:
106     case Runtime::kThrowSuperAlreadyCalledError:
107     case Runtime::kThrowSuperNotCalled:
108     case Runtime::kReThrow:
109     case Runtime::kThrow:
110     case Runtime::kThrowApplyNonFunction:
111     case Runtime::kThrowCalledNonCallable:
112     case Runtime::kThrowConstructedNonConstructable:
113     case Runtime::kThrowConstructorReturnedNonObject:
114     case Runtime::kThrowInvalidStringLength:
115     case Runtime::kThrowInvalidTypedArrayAlignment:
116     case Runtime::kThrowIteratorResultNotAnObject:
117     case Runtime::kThrowThrowMethodMissing:
118     case Runtime::kThrowSymbolIteratorInvalid:
119     case Runtime::kThrowNotConstructor:
120     case Runtime::kThrowRangeError:
121     case Runtime::kThrowReferenceError:
122     case Runtime::kThrowStackOverflow:
123     case Runtime::kThrowSymbolAsyncIteratorInvalid:
124     case Runtime::kThrowTypeError:
125     case Runtime::kThrowConstAssignError:
126     case Runtime::kThrowWasmError:
127     case Runtime::kThrowWasmStackOverflow:
128       return true;
129     default:
130       return false;
131   }
132 }
133 
FunctionForName(const unsigned char * name,int length)134 const Runtime::Function* Runtime::FunctionForName(const unsigned char* name,
135                                                   int length) {
136   base::CallOnce(&initialize_function_name_map_once,
137                  &InitializeIntrinsicFunctionNames);
138   IntrinsicFunctionIdentifier identifier(name, length);
139   base::HashMap::Entry* entry =
140       kRuntimeFunctionNameMap->Lookup(&identifier, identifier.Hash());
141   if (entry) {
142     return reinterpret_cast<Function*>(entry->value);
143   }
144   return nullptr;
145 }
146 
147 
FunctionForEntry(Address entry)148 const Runtime::Function* Runtime::FunctionForEntry(Address entry) {
149   for (size_t i = 0; i < arraysize(kIntrinsicFunctions); ++i) {
150     if (entry == kIntrinsicFunctions[i].entry) {
151       return &(kIntrinsicFunctions[i]);
152     }
153   }
154   return nullptr;
155 }
156 
157 
FunctionForId(Runtime::FunctionId id)158 const Runtime::Function* Runtime::FunctionForId(Runtime::FunctionId id) {
159   return &(kIntrinsicFunctions[static_cast<int>(id)]);
160 }
161 
RuntimeFunctionTable(Isolate * isolate)162 const Runtime::Function* Runtime::RuntimeFunctionTable(Isolate* isolate) {
163 #ifdef USE_SIMULATOR
164   // When running with the simulator we need to provide a table which has
165   // redirected runtime entry addresses.
166   if (!isolate->runtime_state()->redirected_intrinsic_functions()) {
167     size_t function_count = arraysize(kIntrinsicFunctions);
168     Function* redirected_functions = new Function[function_count];
169     memcpy(redirected_functions, kIntrinsicFunctions,
170            sizeof(kIntrinsicFunctions));
171     for (size_t i = 0; i < function_count; i++) {
172       ExternalReference redirected_entry =
173           ExternalReference::Create(static_cast<Runtime::FunctionId>(i));
174       redirected_functions[i].entry = redirected_entry.address();
175     }
176     isolate->runtime_state()->set_redirected_intrinsic_functions(
177         redirected_functions);
178   }
179 
180   return isolate->runtime_state()->redirected_intrinsic_functions();
181 #else
182   return kIntrinsicFunctions;
183 #endif
184 }
185 
operator <<(std::ostream & os,Runtime::FunctionId id)186 std::ostream& operator<<(std::ostream& os, Runtime::FunctionId id) {
187   return os << Runtime::FunctionForId(id)->name;
188 }
189 
190 
191 }  // namespace internal
192 }  // namespace v8
193