• 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/base/platform/wrappers.h"
9 #include "src/codegen/reloc-info.h"
10 #include "src/execution/isolate.h"
11 #include "src/handles/handles-inl.h"
12 #include "src/heap/heap.h"
13 #include "src/objects/contexts.h"
14 #include "src/objects/objects-inl.h"
15 #include "src/runtime/runtime-utils.h"
16 
17 namespace v8 {
18 namespace internal {
19 
20 // Header of runtime functions.
21 #define F(name, number_of_args, result_size)                    \
22   Address Runtime_##name(int args_length, Address* args_object, \
23                          Isolate* isolate);
24 FOR_EACH_INTRINSIC_RETURN_OBJECT(F)
25 #undef F
26 
27 #define P(name, number_of_args, result_size)                       \
28   ObjectPair Runtime_##name(int args_length, Address* args_object, \
29                             Isolate* isolate);
30 FOR_EACH_INTRINSIC_RETURN_PAIR(P)
31 #undef P
32 
33 #define F(name, number_of_args, result_size)                                  \
34   {                                                                           \
35     Runtime::k##name, Runtime::RUNTIME, #name, FUNCTION_ADDR(Runtime_##name), \
36         number_of_args, result_size                                           \
37   }                                                                           \
38   ,
39 
40 
41 #define I(name, number_of_args, result_size)                       \
42   {                                                                \
43     Runtime::kInline##name, Runtime::INLINE, "_" #name,            \
44         FUNCTION_ADDR(Runtime_##name), number_of_args, result_size \
45   }                                                                \
46   ,
47 
48 static const Runtime::Function kIntrinsicFunctions[] = {
49     FOR_EACH_INTRINSIC(F) FOR_EACH_INLINE_INTRINSIC(I)};
50 
51 #undef I
52 #undef F
53 
54 namespace {
55 
56 V8_DECLARE_ONCE(initialize_function_name_map_once);
57 static const base::CustomMatcherHashMap* kRuntimeFunctionNameMap;
58 
59 struct IntrinsicFunctionIdentifier {
IntrinsicFunctionIdentifierv8::internal::__anon198ba05e0111::IntrinsicFunctionIdentifier60   IntrinsicFunctionIdentifier(const unsigned char* data, const int length)
61       : data_(data), length_(length) {}
62 
Matchv8::internal::__anon198ba05e0111::IntrinsicFunctionIdentifier63   static bool Match(void* key1, void* key2) {
64     const IntrinsicFunctionIdentifier* lhs =
65         static_cast<IntrinsicFunctionIdentifier*>(key1);
66     const IntrinsicFunctionIdentifier* rhs =
67         static_cast<IntrinsicFunctionIdentifier*>(key2);
68     if (lhs->length_ != rhs->length_) return false;
69     return CompareCharsEqual(lhs->data_, rhs->data_, rhs->length_);
70   }
71 
Hashv8::internal::__anon198ba05e0111::IntrinsicFunctionIdentifier72   uint32_t Hash() {
73     return StringHasher::HashSequentialString<uint8_t>(
74         data_, length_, v8::internal::kZeroHashSeed);
75   }
76 
77   const unsigned char* data_;
78   const int length_;
79 };
80 
InitializeIntrinsicFunctionNames()81 void InitializeIntrinsicFunctionNames() {
82   base::CustomMatcherHashMap* function_name_map =
83       new base::CustomMatcherHashMap(IntrinsicFunctionIdentifier::Match);
84   for (size_t i = 0; i < arraysize(kIntrinsicFunctions); ++i) {
85     const Runtime::Function* function = &kIntrinsicFunctions[i];
86     IntrinsicFunctionIdentifier* identifier = new IntrinsicFunctionIdentifier(
87         reinterpret_cast<const unsigned char*>(function->name),
88         static_cast<int>(strlen(function->name)));
89     base::HashMap::Entry* entry =
90         function_name_map->InsertNew(identifier, identifier->Hash());
91     entry->value = const_cast<Runtime::Function*>(function);
92   }
93   kRuntimeFunctionNameMap = function_name_map;
94 }
95 
96 }  // namespace
97 
NeedsExactContext(FunctionId id)98 bool Runtime::NeedsExactContext(FunctionId id) {
99   switch (id) {
100     case Runtime::kInlineAsyncFunctionReject:
101     case Runtime::kInlineAsyncFunctionResolve:
102       // For %_AsyncFunctionReject and %_AsyncFunctionResolve we don't
103       // really need the current context, which in particular allows
104       // us to usually eliminate the catch context for the implicit
105       // try-catch in async function.
106       return false;
107     case Runtime::kCreatePrivateAccessors:
108     case Runtime::kCopyDataProperties:
109     case Runtime::kCreateDataProperty:
110     case Runtime::kCreatePrivateNameSymbol:
111     case Runtime::kCreatePrivateBrandSymbol:
112     case Runtime::kLoadPrivateGetter:
113     case Runtime::kLoadPrivateSetter:
114     case Runtime::kReThrow:
115     case Runtime::kReThrowWithMessage:
116     case Runtime::kThrow:
117     case Runtime::kThrowApplyNonFunction:
118     case Runtime::kThrowCalledNonCallable:
119     case Runtime::kThrowConstAssignError:
120     case Runtime::kThrowConstructorNonCallableError:
121     case Runtime::kThrowConstructedNonConstructable:
122     case Runtime::kThrowConstructorReturnedNonObject:
123     case Runtime::kThrowInvalidStringLength:
124     case Runtime::kThrowInvalidTypedArrayAlignment:
125     case Runtime::kThrowIteratorError:
126     case Runtime::kThrowIteratorResultNotAnObject:
127     case Runtime::kThrowNotConstructor:
128     case Runtime::kThrowRangeError:
129     case Runtime::kThrowReferenceError:
130     case Runtime::kThrowAccessedUninitializedVariable:
131     case Runtime::kThrowStackOverflow:
132     case Runtime::kThrowStaticPrototypeError:
133     case Runtime::kThrowSuperAlreadyCalledError:
134     case Runtime::kThrowSuperNotCalled:
135     case Runtime::kThrowSymbolAsyncIteratorInvalid:
136     case Runtime::kThrowSymbolIteratorInvalid:
137     case Runtime::kThrowThrowMethodMissing:
138     case Runtime::kThrowTypeError:
139     case Runtime::kThrowUnsupportedSuperError:
140 #if V8_ENABLE_WEBASSEMBLY
141     case Runtime::kThrowWasmError:
142     case Runtime::kThrowWasmStackOverflow:
143 #endif  // V8_ENABLE_WEBASSEMBLY
144       return false;
145     default:
146       return true;
147   }
148 }
149 
IsNonReturning(FunctionId id)150 bool Runtime::IsNonReturning(FunctionId id) {
151   switch (id) {
152     case Runtime::kThrowUnsupportedSuperError:
153     case Runtime::kThrowConstructorNonCallableError:
154     case Runtime::kThrowStaticPrototypeError:
155     case Runtime::kThrowSuperAlreadyCalledError:
156     case Runtime::kThrowSuperNotCalled:
157     case Runtime::kReThrow:
158     case Runtime::kReThrowWithMessage:
159     case Runtime::kThrow:
160     case Runtime::kThrowApplyNonFunction:
161     case Runtime::kThrowCalledNonCallable:
162     case Runtime::kThrowConstructedNonConstructable:
163     case Runtime::kThrowConstructorReturnedNonObject:
164     case Runtime::kThrowInvalidStringLength:
165     case Runtime::kThrowInvalidTypedArrayAlignment:
166     case Runtime::kThrowIteratorError:
167     case Runtime::kThrowIteratorResultNotAnObject:
168     case Runtime::kThrowThrowMethodMissing:
169     case Runtime::kThrowSymbolIteratorInvalid:
170     case Runtime::kThrowNotConstructor:
171     case Runtime::kThrowRangeError:
172     case Runtime::kThrowReferenceError:
173     case Runtime::kThrowAccessedUninitializedVariable:
174     case Runtime::kThrowStackOverflow:
175     case Runtime::kThrowSymbolAsyncIteratorInvalid:
176     case Runtime::kThrowTypeError:
177     case Runtime::kThrowConstAssignError:
178 #if V8_ENABLE_WEBASSEMBLY
179     case Runtime::kThrowWasmError:
180     case Runtime::kThrowWasmStackOverflow:
181 #endif  // V8_ENABLE_WEBASSEMBLY
182       return true;
183     default:
184       return false;
185   }
186 }
187 
MayAllocate(FunctionId id)188 bool Runtime::MayAllocate(FunctionId id) {
189   switch (id) {
190     case Runtime::kCompleteInobjectSlackTracking:
191     case Runtime::kCompleteInobjectSlackTrackingForMap:
192       return false;
193     default:
194       return true;
195   }
196 }
197 
IsAllowListedForFuzzing(FunctionId id)198 bool Runtime::IsAllowListedForFuzzing(FunctionId id) {
199   CHECK(FLAG_fuzzing);
200   switch (id) {
201     // Runtime functions allowlisted for all fuzzers. Only add functions that
202     // help increase coverage.
203     case Runtime::kArrayBufferDetach:
204     case Runtime::kDeoptimizeFunction:
205     case Runtime::kDeoptimizeNow:
206     case Runtime::kDisableOptimizationFinalization:
207     case Runtime::kEnableCodeLoggingForTesting:
208     case Runtime::kFinalizeOptimization:
209     case Runtime::kGetUndetectable:
210     case Runtime::kNeverOptimizeFunction:
211     case Runtime::kOptimizeFunctionOnNextCall:
212     case Runtime::kOptimizeOsr:
213     case Runtime::kPrepareFunctionForOptimization:
214     case Runtime::kPretenureAllocationSite:
215     case Runtime::kSetAllocationTimeout:
216     case Runtime::kSimulateNewspaceFull:
217     case Runtime::kWaitForBackgroundOptimization:
218       return true;
219     // Runtime functions only permitted for non-differential fuzzers.
220     // This list may contain functions performing extra checks or returning
221     // different values in the context of different flags passed to V8.
222     case Runtime::kGetOptimizationStatus:
223     case Runtime::kHeapObjectVerify:
224     case Runtime::kIsBeingInterpreted:
225       return !FLAG_allow_natives_for_differential_fuzzing;
226     case Runtime::kVerifyType:
227       return !FLAG_allow_natives_for_differential_fuzzing &&
228              !FLAG_concurrent_recompilation;
229     case Runtime::kBaselineOsr:
230     case Runtime::kCompileBaseline:
231       return ENABLE_SPARKPLUG;
232     default:
233       return false;
234   }
235 }
236 
FunctionForName(const unsigned char * name,int length)237 const Runtime::Function* Runtime::FunctionForName(const unsigned char* name,
238                                                   int length) {
239   base::CallOnce(&initialize_function_name_map_once,
240                  &InitializeIntrinsicFunctionNames);
241   IntrinsicFunctionIdentifier identifier(name, length);
242   base::HashMap::Entry* entry =
243       kRuntimeFunctionNameMap->Lookup(&identifier, identifier.Hash());
244   if (entry) {
245     return reinterpret_cast<Function*>(entry->value);
246   }
247   return nullptr;
248 }
249 
250 
FunctionForEntry(Address entry)251 const Runtime::Function* Runtime::FunctionForEntry(Address entry) {
252   for (size_t i = 0; i < arraysize(kIntrinsicFunctions); ++i) {
253     if (entry == kIntrinsicFunctions[i].entry) {
254       return &(kIntrinsicFunctions[i]);
255     }
256   }
257   return nullptr;
258 }
259 
260 
FunctionForId(Runtime::FunctionId id)261 const Runtime::Function* Runtime::FunctionForId(Runtime::FunctionId id) {
262   return &(kIntrinsicFunctions[static_cast<int>(id)]);
263 }
264 
RuntimeFunctionTable(Isolate * isolate)265 const Runtime::Function* Runtime::RuntimeFunctionTable(Isolate* isolate) {
266 #ifdef USE_SIMULATOR
267   // When running with the simulator we need to provide a table which has
268   // redirected runtime entry addresses.
269   if (!isolate->runtime_state()->redirected_intrinsic_functions()) {
270     size_t function_count = arraysize(kIntrinsicFunctions);
271     Function* redirected_functions = new Function[function_count];
272     memcpy(redirected_functions, kIntrinsicFunctions,
273            sizeof(kIntrinsicFunctions));
274     for (size_t i = 0; i < function_count; i++) {
275       ExternalReference redirected_entry =
276           ExternalReference::Create(static_cast<Runtime::FunctionId>(i));
277       redirected_functions[i].entry = redirected_entry.address();
278     }
279     isolate->runtime_state()->set_redirected_intrinsic_functions(
280         redirected_functions);
281   }
282 
283   return isolate->runtime_state()->redirected_intrinsic_functions();
284 #else
285   return kIntrinsicFunctions;
286 #endif
287 }
288 
operator <<(std::ostream & os,Runtime::FunctionId id)289 std::ostream& operator<<(std::ostream& os, Runtime::FunctionId id) {
290   return os << Runtime::FunctionForId(id)->name;
291 }
292 
293 
294 }  // namespace internal
295 }  // namespace v8
296