v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
runtime.cc
Go to the documentation of this file.
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
6
7#include "src/base/hashmap.h"
11
12namespace v8 {
13namespace internal {
14
15// Header of runtime functions.
16#define F(name, number_of_args, result_size) \
17 Address Runtime_##name(int args_length, Address* args_object, \
18 Isolate* isolate);
20#undef F
21
22#define P(name, number_of_args, result_size) \
23 ObjectPair Runtime_##name(int args_length, Address* args_object, \
24 Isolate* isolate);
26#undef P
27
28#define F(name, number_of_args, result_size) \
29 { \
30 Runtime::k##name, Runtime::RUNTIME, #name, FUNCTION_ADDR(Runtime_##name), \
31 number_of_args, result_size \
32 } \
33 ,
34
35
36#define I(name, number_of_args, result_size) \
37 { \
38 Runtime::kInline##name, Runtime::INLINE, "_" #name, \
39 FUNCTION_ADDR(Runtime_##name), number_of_args, result_size \
40 } \
41 ,
42
45
46#undef I
47#undef F
48
49namespace {
50
51V8_DECLARE_ONCE(initialize_function_name_map_once);
52static const base::CustomMatcherHashMap* kRuntimeFunctionNameMap;
53
54struct IntrinsicFunctionIdentifier {
55 IntrinsicFunctionIdentifier(const unsigned char* data, const int length)
56 : data_(data), length_(length) {}
57
58 static bool Match(void* key1, void* key2) {
59 const IntrinsicFunctionIdentifier* lhs =
60 static_cast<IntrinsicFunctionIdentifier*>(key1);
61 const IntrinsicFunctionIdentifier* rhs =
62 static_cast<IntrinsicFunctionIdentifier*>(key2);
63 if (lhs->length_ != rhs->length_) return false;
64 return CompareCharsEqual(lhs->data_, rhs->data_, rhs->length_);
65 }
66
67 uint32_t Hash() {
69 data_, length_, v8::internal::kZeroHashSeed);
70 }
71
72 const unsigned char* data_;
73 const int length_;
74};
75
76void InitializeIntrinsicFunctionNames() {
77 base::CustomMatcherHashMap* function_name_map =
78 new base::CustomMatcherHashMap(IntrinsicFunctionIdentifier::Match);
79 for (size_t i = 0; i < arraysize(kIntrinsicFunctions); ++i) {
80 const Runtime::Function* function = &kIntrinsicFunctions[i];
81 IntrinsicFunctionIdentifier* identifier = new IntrinsicFunctionIdentifier(
82 reinterpret_cast<const unsigned char*>(function->name),
83 static_cast<int>(strlen(function->name)));
85 function_name_map->InsertNew(identifier, identifier->Hash());
86 entry->value = const_cast<Runtime::Function*>(function);
87 }
88 kRuntimeFunctionNameMap = function_name_map;
89}
90
91} // namespace
92
94 switch (id) {
95 case Runtime::kInlineAsyncFunctionReject:
96 case Runtime::kInlineAsyncFunctionResolve:
97 // For %_AsyncFunctionReject and %_AsyncFunctionResolve we don't
98 // really need the current context, which in particular allows
99 // us to usually eliminate the catch context for the implicit
100 // try-catch in async function.
101 return false;
102 case Runtime::kCreatePrivateAccessors:
103 case Runtime::kCopyDataProperties:
104 case Runtime::kCreateDataProperty:
105 case Runtime::kCreatePrivateNameSymbol:
106 case Runtime::kCreatePrivateBrandSymbol:
107 case Runtime::kLoadPrivateGetter:
108 case Runtime::kLoadPrivateSetter:
109 case Runtime::kReThrow:
110 case Runtime::kReThrowWithMessage:
111 case Runtime::kThrow:
112 case Runtime::kThrowApplyNonFunction:
113 case Runtime::kThrowCalledNonCallable:
114 case Runtime::kThrowConstAssignError:
115 case Runtime::kThrowConstructorNonCallableError:
116 case Runtime::kThrowConstructedNonConstructable:
117 case Runtime::kThrowConstructorReturnedNonObject:
118 case Runtime::kThrowInvalidStringLength:
119 case Runtime::kThrowInvalidTypedArrayAlignment:
120 case Runtime::kThrowIteratorError:
121 case Runtime::kThrowIteratorResultNotAnObject:
122 case Runtime::kThrowNotConstructor:
123 case Runtime::kThrowRangeError:
124 case Runtime::kThrowReferenceError:
125 case Runtime::kThrowAccessedUninitializedVariable:
126 case Runtime::kThrowStackOverflow:
127 case Runtime::kThrowStaticPrototypeError:
128 case Runtime::kThrowSuperAlreadyCalledError:
129 case Runtime::kThrowSuperNotCalled:
130 case Runtime::kThrowSymbolAsyncIteratorInvalid:
131 case Runtime::kThrowSymbolIteratorInvalid:
132 case Runtime::kThrowThrowMethodMissing:
133 case Runtime::kThrowTypeError:
134 case Runtime::kThrowUnsupportedSuperError:
135 case Runtime::kTerminateExecution:
136#if V8_ENABLE_WEBASSEMBLY
137 case Runtime::kThrowWasmError:
138 case Runtime::kThrowWasmStackOverflow:
139#endif // V8_ENABLE_WEBASSEMBLY
140 return false;
141 default:
142 return true;
143 }
144}
145
147 switch (id) {
148 case Runtime::kThrowUnsupportedSuperError:
149 case Runtime::kThrowConstructorNonCallableError:
150 case Runtime::kThrowStaticPrototypeError:
151 case Runtime::kThrowSuperAlreadyCalledError:
152 case Runtime::kThrowSuperNotCalled:
153 case Runtime::kReThrow:
154 case Runtime::kReThrowWithMessage:
155 case Runtime::kThrow:
156 case Runtime::kThrowApplyNonFunction:
157 case Runtime::kThrowCalledNonCallable:
158 case Runtime::kThrowConstructedNonConstructable:
159 case Runtime::kThrowConstructorReturnedNonObject:
160 case Runtime::kThrowInvalidStringLength:
161 case Runtime::kThrowInvalidTypedArrayAlignment:
162 case Runtime::kThrowIteratorError:
163 case Runtime::kThrowIteratorResultNotAnObject:
164 case Runtime::kThrowThrowMethodMissing:
165 case Runtime::kThrowSymbolIteratorInvalid:
166 case Runtime::kThrowNotConstructor:
167 case Runtime::kThrowRangeError:
168 case Runtime::kThrowReferenceError:
169 case Runtime::kThrowAccessedUninitializedVariable:
170 case Runtime::kThrowStackOverflow:
171 case Runtime::kThrowSymbolAsyncIteratorInvalid:
172 case Runtime::kThrowTypeError:
173 case Runtime::kThrowConstAssignError:
174 case Runtime::kTerminateExecution:
175#if V8_ENABLE_WEBASSEMBLY
176 case Runtime::kThrowWasmError:
177 case Runtime::kThrowWasmStackOverflow:
178 case Runtime::kThrowWasmSuspendError:
179#endif // V8_ENABLE_WEBASSEMBLY
180 return true;
181 default:
182 return false;
183 }
184}
185
187 switch (id) {
188 case Runtime::kCompleteInobjectSlackTracking:
189 case Runtime::kCompleteInobjectSlackTrackingForMap:
190 case Runtime::kGlobalPrint:
191 return false;
192 default:
193 return true;
194 }
195}
196
198 CHECK(v8_flags.fuzzing);
199
200 // In general, all runtime functions meant for testing should also be exposed
201 // to the fuzzers. That way, the fuzzers are able to import and mutate
202 // regression tests that use those functions. Internal runtime functions
203 // (which are e.g. only called from other builtins, etc.) should not directly
204 // be exposed as they are not meant to be called directly from JavaScript.
205 // However, exceptions exist: some test functions cannot be used for certain
206 // types of fuzzing (e.g. differential fuzzing), or would cause false
207 // positive crashes and therefore should not be exposed to fuzzers at all.
208
209 // For differential fuzzing, only a handful of functions are allowed,
210 // everything else is disabled. Many runtime functions are unsuited for
211 // differential fuzzing as they for example expose internal engine state
212 // (e.g. functions such as %HasFastProperties). To avoid having to maintain a
213 // large denylist of such functions, we instead use an allowlist for
214 // differential fuzzing.
215 bool is_differential_fuzzing =
216 v8_flags.allow_natives_for_differential_fuzzing;
217 if (is_differential_fuzzing) {
218 switch (id) {
219 case Runtime::kArrayBufferDetach:
220 case Runtime::kDeoptimizeFunction:
221 case Runtime::kDeoptimizeNow:
222 case Runtime::kDisableOptimizationFinalization:
223 case Runtime::kEnableCodeLoggingForTesting:
224 case Runtime::kFinalizeOptimization:
225 case Runtime::kGetUndetectable:
226 case Runtime::kNeverOptimizeFunction:
227 case Runtime::kOptimizeFunctionOnNextCall:
228 case Runtime::kOptimizeMaglevOnNextCall:
229 case Runtime::kOptimizeOsr:
230 case Runtime::kPrepareFunctionForOptimization:
231 case Runtime::kPretenureAllocationSite:
232 case Runtime::kSetAllocationTimeout:
233 case Runtime::kSetForceSlowPath:
234 case Runtime::kSimulateNewspaceFull:
235 case Runtime::kWaitForBackgroundOptimization:
236 case Runtime::kSetBatterySaverMode:
237 case Runtime::kSetPriorityBestEffort:
238 case Runtime::kSetPriorityUserVisible:
239 case Runtime::kSetPriorityUserBlocking:
240 case Runtime::kIsEfficiencyModeEnabled:
241 case Runtime::kBaselineOsr:
242 case Runtime::kCompileBaseline:
243#if V8_ENABLE_WEBASSEMBLY && V8_WASM_RANDOM_FUZZERS
244 case Runtime::kWasmGenerateRandomModule:
245#endif // V8_ENABLE_WEBASSEMBLY && V8_WASM_RANDOM_FUZZERS
246#if V8_ENABLE_WEBASSEMBLY
247 case Runtime::kWasmArray:
248 case Runtime::kWasmStruct:
249 case Runtime::kWasmTierUpFunction:
250 case Runtime::kWasmTriggerTierUpForTesting:
251#endif // V8_ENABLE_WEBASSEMBLY
252 return true;
253
254 default:
255 return false;
256 }
257 }
258
259 // Runtime functions disabled for all/most types of fuzzing.
260 // Reasons for a function to be in this list include that it is not useful
261 // for fuzzing (e.g. %DebugPrint) or not fuzzing-safe and therefore would
262 // cause false-positive crashes (e.g. %AbortJS).
263 switch (id) {
264 case Runtime::kAbort:
265 case Runtime::kAbortCSADcheck:
266 case Runtime::kAbortJS:
267 case Runtime::kSystemBreak:
268 case Runtime::kBenchMaglev:
269 case Runtime::kBenchTurbofan:
270 case Runtime::kDebugPrint:
271 case Runtime::kDisassembleFunction:
272 case Runtime::kGetFunctionForCurrentFrame:
273 case Runtime::kGetCallable:
274 case Runtime::kGetAbstractModuleSource:
275 case Runtime::kTurbofanStaticAssert:
276 case Runtime::kClearFunctionFeedback:
277 case Runtime::kStringIsFlat:
278 case Runtime::kGetInitializerFunction:
279#ifdef V8_ENABLE_WEBASSEMBLY
280 case Runtime::kWasmTraceEnter:
281 case Runtime::kWasmTraceExit:
282 case Runtime::kWasmTraceMemory:
283 case Runtime::kCheckIsOnCentralStack:
284 case Runtime::kSetWasmInstantiateControls:
285 case Runtime::kWasmNull:
286 case Runtime::kFreezeWasmLazyCompilation:
287 case Runtime::kDeserializeWasmModule:
288#endif // V8_ENABLE_WEBASSEMBLY
289 // TODO(353685107): investigate whether these should be exposed to fuzzers.
290 case Runtime::kConstructDouble:
291 case Runtime::kConstructConsString:
292 case Runtime::kConstructSlicedString:
293 case Runtime::kConstructInternalizedString:
294 case Runtime::kConstructThinString:
295 // TODO(353971258): investigate whether this should be exposed to fuzzers.
296 case Runtime::kSerializeDeserializeNow:
297 // TODO(353928347): investigate whether this should be exposed to fuzzers.
298 case Runtime::kCompleteInobjectSlackTracking:
299 // TODO(354005312): investigate whether this should be exposed to fuzzers.
300 case Runtime::kShareObject:
301 // TODO(354310130): investigate whether this should be exposed to fuzzers.
302 case Runtime::kForceFlush:
303 return false;
304
305 case Runtime::kLeakHole:
306 return v8_flags.hole_fuzzing;
307
308 default:
309 break;
310 }
311
312 // The default case: test functions are exposed, everything else is not.
313 switch (id) {
314#define F(name, nargs, ressize) case k##name:
315#define I(name, nargs, ressize) case kInline##name:
318#undef I
319#undef F
320 return true;
321 default:
322 return false;
323 }
324}
325
326const Runtime::Function* Runtime::FunctionForName(const unsigned char* name,
327 int length) {
328 base::CallOnce(&initialize_function_name_map_once,
329 &InitializeIntrinsicFunctionNames);
330 IntrinsicFunctionIdentifier identifier(name, length);
331 base::HashMap::Entry* entry =
332 kRuntimeFunctionNameMap->Lookup(&identifier, identifier.Hash());
333 if (entry) {
334 return reinterpret_cast<Function*>(entry->value);
335 }
336 return nullptr;
337}
338
339
341 for (size_t i = 0; i < arraysize(kIntrinsicFunctions); ++i) {
342 if (entry == kIntrinsicFunctions[i].entry) {
343 return &(kIntrinsicFunctions[i]);
344 }
345 }
346 return nullptr;
347}
348
349
351 return &(kIntrinsicFunctions[static_cast<int>(id)]);
352}
353
355#ifdef USE_SIMULATOR
356 // When running with the simulator we need to provide a table which has
357 // redirected runtime entry addresses.
358 if (!isolate->runtime_state()->redirected_intrinsic_functions()) {
359 size_t function_count = arraysize(kIntrinsicFunctions);
360 Function* redirected_functions = new Function[function_count];
361 memcpy(redirected_functions, kIntrinsicFunctions,
362 sizeof(kIntrinsicFunctions));
363 for (size_t i = 0; i < function_count; i++) {
364 ExternalReference redirected_entry =
366 redirected_functions[i].entry = redirected_entry.address();
367 }
368 isolate->runtime_state()->set_redirected_intrinsic_functions(
369 redirected_functions);
370 }
371
372 return isolate->runtime_state()->redirected_intrinsic_functions();
373#else
374 return kIntrinsicFunctions;
375#endif
376}
377
378std::ostream& operator<<(std::ostream& os, Runtime::FunctionId id) {
379 return os << Runtime::FunctionForId(id)->name;
380}
381
383
384} // namespace internal
385} // namespace v8
uint8_t data_[MAX_STACK_LENGTH]
Entry * Lookup(const Key &key, uint32_t hash) const
Definition hashmap.h:214
V8_EXPORT_PRIVATE Address address() const
static ExternalReference Create(const SCTableReference &table_ref)
static const Function * RuntimeFunctionTable(Isolate *isolate)
Definition runtime.cc:354
static bool NeedsExactContext(FunctionId id)
Definition runtime.cc:93
static V8_EXPORT_PRIVATE const Function * FunctionForId(FunctionId id)
Definition runtime.cc:350
static bool MayAllocate(FunctionId id)
Definition runtime.cc:186
static bool IsNonReturning(FunctionId id)
Definition runtime.cc:146
static const Function * FunctionForEntry(Address ref)
Definition runtime.cc:340
static bool IsEnabledForFuzzing(FunctionId id)
Definition runtime.cc:197
static const Function * FunctionForName(const unsigned char *name, int length)
Definition runtime.cc:326
static uint32_t HashSequentialString(const char_t *chars, uint32_t length, uint64_t seed)
const int length_
Definition mul-fft.cc:473
void CallOnce(OnceType *once, std::function< void()> init_func)
Definition once.h:90
CustomMatcherTemplateHashMapImpl< DefaultAllocationPolicy > CustomMatcherHashMap
Definition hashmap.h:480
constexpr int I
int g_num_isolates_for_testing
Definition runtime.cc:382
std::ostream & operator<<(std::ostream &os, AtomicMemoryOrder order)
constexpr int P
bool CompareCharsEqual(const lchar *lhs, const rchar *rhs, size_t chars)
Definition utils.h:509
static uint32_t Hash(RegisteredExtension *extension)
static const uint64_t kZeroHashSeed
Definition utils.h:267
V8_EXPORT_PRIVATE FlagValues v8_flags
static const Runtime::Function kIntrinsicFunctions[]
Definition runtime.cc:43
#define V8_DECLARE_ONCE(NAME)
Definition once.h:72
#define FOR_EACH_INLINE_INTRINSIC(I)
Definition runtime.h:887
#define FOR_EACH_INTRINSIC_RETURN_PAIR(F)
Definition runtime.h:879
#define FOR_EACH_INTRINSIC_TEST(F, I)
Definition runtime.h:525
#define FOR_EACH_INTRINSIC_RETURN_OBJECT(F)
Definition runtime.h:876
#define FOR_EACH_INTRINSIC_WASM_TEST(F, I)
Definition runtime.h:738
#define FOR_EACH_INTRINSIC(F)
Definition runtime.h:884
#define CHECK(condition)
Definition logging.h:124
#define arraysize(array)
Definition macros.h:67
#define IF_WASM(V,...)
Definition macros.h:472
Symbol identifier