Line data Source code
1 : // Copyright 2014 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-utils.h"
6 :
7 : #include <memory>
8 : #include <sstream>
9 :
10 : #include "src/api-inl.h"
11 : #include "src/arguments-inl.h"
12 : #include "src/assembler-inl.h"
13 : #include "src/base/platform/mutex.h"
14 : #include "src/compiler-dispatcher/optimizing-compile-dispatcher.h"
15 : #include "src/compiler.h"
16 : #include "src/counters.h"
17 : #include "src/deoptimizer.h"
18 : #include "src/frames-inl.h"
19 : #include "src/heap/heap-inl.h" // For ToBoolean. TODO(jkummerow): Drop.
20 : #include "src/heap/heap-write-barrier-inl.h"
21 : #include "src/ic/stub-cache.h"
22 : #include "src/isolate-inl.h"
23 : #include "src/objects/heap-object-inl.h"
24 : #include "src/objects/smi.h"
25 : #include "src/ostreams.h"
26 : #include "src/runtime-profiler.h"
27 : #include "src/snapshot/natives.h"
28 : #include "src/trap-handler/trap-handler.h"
29 : #include "src/wasm/memory-tracing.h"
30 : #include "src/wasm/module-compiler.h"
31 : #include "src/wasm/wasm-engine.h"
32 : #include "src/wasm/wasm-module.h"
33 : #include "src/wasm/wasm-objects-inl.h"
34 : #include "src/wasm/wasm-serialization.h"
35 :
36 : namespace v8 {
37 : namespace internal {
38 :
39 : namespace {
40 8 : struct WasmCompileControls {
41 : uint32_t MaxWasmBufferSize = std::numeric_limits<uint32_t>::max();
42 : bool AllowAnySizeForAsync = true;
43 : };
44 : using WasmCompileControlsMap = std::map<v8::Isolate*, WasmCompileControls>;
45 :
46 : // We need per-isolate controls, because we sometimes run tests in multiple
47 : // isolates concurrently. Methods need to hold the accompanying mutex on access.
48 : // To avoid upsetting the static initializer count, we lazy initialize this.
49 100 : DEFINE_LAZY_LEAKY_OBJECT_GETTER(WasmCompileControlsMap,
50 : GetPerIsolateWasmControls)
51 : base::LazyMutex g_PerIsolateWasmControlsMutex = LAZY_MUTEX_INITIALIZER;
52 :
53 24 : bool IsWasmCompileAllowed(v8::Isolate* isolate, v8::Local<v8::Value> value,
54 : bool is_async) {
55 : base::MutexGuard guard(g_PerIsolateWasmControlsMutex.Pointer());
56 : DCHECK_GT(GetPerIsolateWasmControls()->count(isolate), 0);
57 24 : const WasmCompileControls& ctrls = GetPerIsolateWasmControls()->at(isolate);
58 24 : return (is_async && ctrls.AllowAnySizeForAsync) ||
59 24 : (value->IsArrayBuffer() &&
60 0 : v8::Local<v8::ArrayBuffer>::Cast(value)->ByteLength() <=
61 48 : ctrls.MaxWasmBufferSize) ||
62 48 : (value->IsArrayBufferView() &&
63 48 : v8::Local<v8::ArrayBufferView>::Cast(value)->ByteLength() <=
64 48 : ctrls.MaxWasmBufferSize);
65 : }
66 :
67 : // Use the compile controls for instantiation, too
68 20 : bool IsWasmInstantiateAllowed(v8::Isolate* isolate,
69 : v8::Local<v8::Value> module_or_bytes,
70 : bool is_async) {
71 : base::MutexGuard guard(g_PerIsolateWasmControlsMutex.Pointer());
72 : DCHECK_GT(GetPerIsolateWasmControls()->count(isolate), 0);
73 20 : const WasmCompileControls& ctrls = GetPerIsolateWasmControls()->at(isolate);
74 20 : if (is_async && ctrls.AllowAnySizeForAsync) return true;
75 20 : if (!module_or_bytes->IsWebAssemblyCompiledModule()) {
76 0 : return IsWasmCompileAllowed(isolate, module_or_bytes, is_async);
77 : }
78 : v8::Local<v8::WasmModuleObject> module =
79 : v8::Local<v8::WasmModuleObject>::Cast(module_or_bytes);
80 : return static_cast<uint32_t>(
81 60 : module->GetCompiledModule().GetWireBytesRef().size()) <=
82 20 : ctrls.MaxWasmBufferSize;
83 : }
84 :
85 16 : v8::Local<v8::Value> NewRangeException(v8::Isolate* isolate,
86 : const char* message) {
87 : return v8::Exception::RangeError(
88 16 : v8::String::NewFromOneByte(isolate,
89 : reinterpret_cast<const uint8_t*>(message),
90 : v8::NewStringType::kNormal)
91 16 : .ToLocalChecked());
92 : }
93 :
94 16 : void ThrowRangeException(v8::Isolate* isolate, const char* message) {
95 16 : isolate->ThrowException(NewRangeException(isolate, message));
96 16 : }
97 :
98 24 : bool WasmModuleOverride(const v8::FunctionCallbackInfo<v8::Value>& args) {
99 24 : if (IsWasmCompileAllowed(args.GetIsolate(), args[0], false)) return false;
100 8 : ThrowRangeException(args.GetIsolate(), "Sync compile not allowed");
101 8 : return true;
102 : }
103 :
104 20 : bool WasmInstanceOverride(const v8::FunctionCallbackInfo<v8::Value>& args) {
105 20 : if (IsWasmInstantiateAllowed(args.GetIsolate(), args[0], false)) return false;
106 8 : ThrowRangeException(args.GetIsolate(), "Sync instantiate not allowed");
107 8 : return true;
108 : }
109 :
110 : } // namespace
111 :
112 0 : RUNTIME_FUNCTION(Runtime_ClearMegamorphicStubCache) {
113 : HandleScope scope(isolate);
114 : DCHECK_EQ(0, args.length());
115 0 : isolate->load_stub_cache()->Clear();
116 0 : isolate->store_stub_cache()->Clear();
117 : return ReadOnlyRoots(isolate).undefined_value();
118 : }
119 :
120 936 : RUNTIME_FUNCTION(Runtime_ConstructDouble) {
121 : HandleScope scope(isolate);
122 : DCHECK_EQ(2, args.length());
123 936 : CONVERT_NUMBER_CHECKED(uint32_t, hi, Uint32, args[0]);
124 936 : CONVERT_NUMBER_CHECKED(uint32_t, lo, Uint32, args[1]);
125 468 : uint64_t result = (static_cast<uint64_t>(hi) << 32) | lo;
126 936 : return *isolate->factory()->NewNumber(uint64_to_double(result));
127 : }
128 :
129 18 : RUNTIME_FUNCTION(Runtime_ConstructConsString) {
130 : HandleScope scope(isolate);
131 : DCHECK_EQ(2, args.length());
132 9 : CONVERT_ARG_HANDLE_CHECKED(String, left, 0);
133 9 : CONVERT_ARG_HANDLE_CHECKED(String, right, 1);
134 :
135 9 : CHECK(left->IsOneByteRepresentation());
136 9 : CHECK(right->IsOneByteRepresentation());
137 :
138 : const bool kIsOneByte = true;
139 9 : const int length = left->length() + right->length();
140 18 : return *isolate->factory()->NewConsString(left, right, length, kIsOneByte);
141 : }
142 :
143 18 : RUNTIME_FUNCTION(Runtime_ConstructSlicedString) {
144 : HandleScope scope(isolate);
145 : DCHECK_EQ(2, args.length());
146 9 : CONVERT_ARG_HANDLE_CHECKED(String, string, 0);
147 9 : CONVERT_ARG_HANDLE_CHECKED(Smi, index, 1);
148 :
149 9 : CHECK(string->IsOneByteRepresentation());
150 9 : CHECK_LT(index->value(), string->length());
151 :
152 : Handle<String> sliced_string = isolate->factory()->NewSubString(
153 9 : string, index->value(), string->length());
154 9 : CHECK(sliced_string->IsSlicedString());
155 : return *sliced_string;
156 : }
157 :
158 116446 : RUNTIME_FUNCTION(Runtime_DeoptimizeFunction) {
159 : HandleScope scope(isolate);
160 : DCHECK_EQ(1, args.length());
161 :
162 : // This function is used by fuzzers to get coverage in compiler.
163 : // Ignore calls on non-function objects to avoid runtime errors.
164 : CONVERT_ARG_HANDLE_CHECKED(Object, function_object, 0);
165 58223 : if (!function_object->IsJSFunction()) {
166 : return ReadOnlyRoots(isolate).undefined_value();
167 : }
168 58223 : Handle<JSFunction> function = Handle<JSFunction>::cast(function_object);
169 :
170 : // If the function is not optimized, just return.
171 58223 : if (!function->IsOptimized()) return ReadOnlyRoots(isolate).undefined_value();
172 :
173 14383 : Deoptimizer::DeoptimizeFunction(*function);
174 :
175 : return ReadOnlyRoots(isolate).undefined_value();
176 : }
177 :
178 8330 : RUNTIME_FUNCTION(Runtime_DeoptimizeNow) {
179 : HandleScope scope(isolate);
180 : DCHECK_EQ(0, args.length());
181 :
182 : Handle<JSFunction> function;
183 :
184 : // Find the JavaScript function on the top of the stack.
185 4165 : JavaScriptFrameIterator it(isolate);
186 4165 : if (!it.done()) function = handle(it.frame()->function(), isolate);
187 4165 : if (function.is_null()) return ReadOnlyRoots(isolate).undefined_value();
188 :
189 : // If the function is not optimized, just return.
190 4165 : if (!function->IsOptimized()) return ReadOnlyRoots(isolate).undefined_value();
191 :
192 639 : Deoptimizer::DeoptimizeFunction(*function);
193 :
194 : return ReadOnlyRoots(isolate).undefined_value();
195 : }
196 :
197 18 : RUNTIME_FUNCTION(Runtime_RunningInSimulator) {
198 : SealHandleScope shs(isolate);
199 : DCHECK_EQ(0, args.length());
200 : #if defined(USE_SIMULATOR)
201 : return ReadOnlyRoots(isolate).true_value();
202 : #else
203 : return ReadOnlyRoots(isolate).false_value();
204 : #endif
205 : }
206 :
207 80 : RUNTIME_FUNCTION(Runtime_ICsAreEnabled) {
208 : SealHandleScope shs(isolate);
209 : DCHECK_EQ(0, args.length());
210 40 : return isolate->heap()->ToBoolean(FLAG_use_ic);
211 : }
212 :
213 94 : RUNTIME_FUNCTION(Runtime_IsConcurrentRecompilationSupported) {
214 : SealHandleScope shs(isolate);
215 : DCHECK_EQ(0, args.length());
216 : return isolate->heap()->ToBoolean(
217 : isolate->concurrent_recompilation_enabled());
218 : }
219 :
220 569336 : RUNTIME_FUNCTION(Runtime_OptimizeFunctionOnNextCall) {
221 : HandleScope scope(isolate);
222 :
223 : // This function is used by fuzzers, ignore calls with bogus arguments count.
224 284668 : if (args.length() != 1 && args.length() != 2) {
225 : return ReadOnlyRoots(isolate).undefined_value();
226 : }
227 :
228 : // This function is used by fuzzers to get coverage for optimizations
229 : // in compiler. Ignore calls on non-function objects to avoid runtime errors.
230 : CONVERT_ARG_HANDLE_CHECKED(Object, function_object, 0);
231 284668 : if (!function_object->IsJSFunction()) {
232 : return ReadOnlyRoots(isolate).undefined_value();
233 : }
234 284668 : Handle<JSFunction> function = Handle<JSFunction>::cast(function_object);
235 :
236 : // The following conditions were lifted (in part) from the DCHECK inside
237 : // JSFunction::MarkForOptimization().
238 :
239 569336 : if (!function->shared()->allows_lazy_compilation()) {
240 : return ReadOnlyRoots(isolate).undefined_value();
241 : }
242 :
243 : // If function isn't compiled, compile it now.
244 284616 : IsCompiledScope is_compiled_scope(function->shared()->is_compiled_scope());
245 285497 : if (!is_compiled_scope.is_compiled() &&
246 881 : !Compiler::Compile(function, Compiler::CLEAR_EXCEPTION,
247 : &is_compiled_scope)) {
248 : return ReadOnlyRoots(isolate).undefined_value();
249 : }
250 :
251 860745 : if (function->shared()->optimization_disabled() &&
252 291983 : function->shared()->disable_optimization_reason() ==
253 : BailoutReason::kNeverOptimize) {
254 : return ReadOnlyRoots(isolate).undefined_value();
255 : }
256 :
257 : // If the function is already optimized, just return.
258 530959 : if (function->IsOptimized() || function->shared()->HasAsmWasmData()) {
259 : return ReadOnlyRoots(isolate).undefined_value();
260 : }
261 :
262 : // If the function has optimized code, ensure that we check for it and return.
263 246593 : if (function->HasOptimizedCode()) {
264 : DCHECK(function->ChecksOptimizationMarker());
265 : return ReadOnlyRoots(isolate).undefined_value();
266 : }
267 :
268 : ConcurrencyMode concurrency_mode = ConcurrencyMode::kNotConcurrent;
269 246569 : if (args.length() == 2) {
270 : // Ignore invalid inputs produced by fuzzers.
271 : CONVERT_ARG_HANDLE_CHECKED(Object, type, 1);
272 105 : if (!type->IsString()) {
273 : return ReadOnlyRoots(isolate).undefined_value();
274 : }
275 315 : if (Handle<String>::cast(type)->IsOneByteEqualTo(
276 105 : StaticCharVector("concurrent")) &&
277 : isolate->concurrent_recompilation_enabled()) {
278 : concurrency_mode = ConcurrencyMode::kConcurrent;
279 : }
280 : }
281 246569 : if (FLAG_trace_opt) {
282 672 : PrintF("[manually marking ");
283 1344 : function->ShortPrint();
284 672 : PrintF(" for %s optimization]\n",
285 : concurrency_mode == ConcurrencyMode::kConcurrent ? "concurrent"
286 672 : : "non-concurrent");
287 : }
288 :
289 : // This function may not have been lazily compiled yet, even though its shared
290 : // function has.
291 246569 : if (!function->is_compiled()) {
292 : DCHECK(function->shared()->IsInterpreted());
293 149776 : function->set_code(*BUILTIN_CODE(isolate, InterpreterEntryTrampoline));
294 : }
295 :
296 246569 : JSFunction::EnsureFeedbackVector(function);
297 246569 : function->MarkForOptimization(concurrency_mode);
298 :
299 : return ReadOnlyRoots(isolate).undefined_value();
300 : }
301 :
302 93340 : RUNTIME_FUNCTION(Runtime_PrepareFunctionForOptimization) {
303 : HandleScope scope(isolate);
304 : DCHECK_EQ(1, args.length());
305 46670 : CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
306 :
307 : // Only one function should be prepared for optimization at a time
308 46670 : CHECK(isolate->heap()->pending_optimize_for_test_bytecode()->IsUndefined());
309 :
310 : // Check function allows lazy compilation.
311 93340 : if (!function->shared()->allows_lazy_compilation()) {
312 : return ReadOnlyRoots(isolate).undefined_value();
313 : }
314 :
315 : // If function isn't compiled, compile it now.
316 46670 : IsCompiledScope is_compiled_scope(function->shared()->is_compiled_scope());
317 53769 : if (!is_compiled_scope.is_compiled() &&
318 7099 : !Compiler::Compile(function, Compiler::CLEAR_EXCEPTION,
319 : &is_compiled_scope)) {
320 : return ReadOnlyRoots(isolate).undefined_value();
321 : }
322 :
323 : // Ensure function has a feedback vector to hold type feedback for
324 : // optimization.
325 46670 : JSFunction::EnsureFeedbackVector(function);
326 :
327 : // If optimization is disabled for the function, return without making it
328 : // pending optimize for test.
329 141786 : if (function->shared()->optimization_disabled() &&
330 48446 : function->shared()->disable_optimization_reason() ==
331 : BailoutReason::kNeverOptimize) {
332 : return ReadOnlyRoots(isolate).undefined_value();
333 : }
334 :
335 : // If the function is already optimized, return without making it pending
336 : // optimize for test.
337 81264 : if (function->IsOptimized() || function->shared()->HasAsmWasmData()) {
338 : return ReadOnlyRoots(isolate).undefined_value();
339 : }
340 :
341 : // If the function has optimized code, ensure that we check for it and then
342 : // return without making it pending optimize for test.
343 34594 : if (function->HasOptimizedCode()) {
344 : DCHECK(function->ChecksOptimizationMarker());
345 : return ReadOnlyRoots(isolate).undefined_value();
346 : }
347 :
348 : // Hold onto the bytecode array between marking and optimization to ensure
349 : // it's not flushed.
350 : isolate->heap()->SetPendingOptimizeForTestBytecode(
351 68260 : function->shared()->GetBytecodeArray());
352 :
353 : return ReadOnlyRoots(isolate).undefined_value();
354 : }
355 :
356 46956 : RUNTIME_FUNCTION(Runtime_OptimizeOsr) {
357 : HandleScope scope(isolate);
358 : DCHECK(args.length() == 0 || args.length() == 1);
359 :
360 : Handle<JSFunction> function;
361 :
362 : // The optional parameter determines the frame being targeted.
363 23478 : int stack_depth = args.length() == 1 ? args.smi_at(0) : 0;
364 :
365 : // Find the JavaScript function on the top of the stack.
366 23478 : JavaScriptFrameIterator it(isolate);
367 23667 : while (!it.done() && stack_depth--) it.Advance();
368 23478 : if (!it.done()) function = handle(it.frame()->function(), isolate);
369 23478 : if (function.is_null()) return ReadOnlyRoots(isolate).undefined_value();
370 :
371 : // If the function is already optimized, just return.
372 23478 : if (function->IsOptimized()) return ReadOnlyRoots(isolate).undefined_value();
373 :
374 44269 : if (function->shared()->optimization_disabled() &&
375 17745 : function->shared()->disable_optimization_reason() ==
376 : BailoutReason::kNeverOptimize) {
377 : return ReadOnlyRoots(isolate).undefined_value();
378 : }
379 :
380 : // Ensure that the function is marked for non-concurrent optimization, so that
381 : // subsequent runs don't also optimize.
382 13262 : if (!function->HasOptimizedCode()) {
383 13262 : if (FLAG_trace_osr) {
384 0 : PrintF("[OSR - OptimizeOsr marking ");
385 0 : function->ShortPrint();
386 0 : PrintF(" for non-concurrent optimization]\n");
387 : }
388 13262 : function->MarkForOptimization(ConcurrencyMode::kNotConcurrent);
389 : }
390 :
391 : // Make the profiler arm all back edges in unoptimized code.
392 13262 : if (it.frame()->type() == StackFrame::INTERPRETED) {
393 : isolate->runtime_profiler()->AttemptOnStackReplacement(
394 : InterpretedFrame::cast(it.frame()),
395 6605 : AbstractCode::kMaxLoopNestingMarker);
396 : }
397 :
398 : return ReadOnlyRoots(isolate).undefined_value();
399 : }
400 :
401 :
402 3716 : RUNTIME_FUNCTION(Runtime_NeverOptimizeFunction) {
403 : HandleScope scope(isolate);
404 : DCHECK_EQ(1, args.length());
405 : // This function is used by fuzzers to get coverage for optimizations
406 : // in compiler. Ignore calls on non-function objects to avoid runtime errors.
407 : CONVERT_ARG_HANDLE_CHECKED(Object, function_object, 0);
408 1858 : if (!function_object->IsJSFunction()) {
409 : return ReadOnlyRoots(isolate).undefined_value();
410 : }
411 1822 : Handle<JSFunction> function = Handle<JSFunction>::cast(function_object);
412 1822 : function->shared()->DisableOptimization(BailoutReason::kNeverOptimize);
413 : return ReadOnlyRoots(isolate).undefined_value();
414 : }
415 :
416 11808 : RUNTIME_FUNCTION(Runtime_GetOptimizationStatus) {
417 : HandleScope scope(isolate);
418 : DCHECK(args.length() == 1 || args.length() == 2);
419 : int status = 0;
420 5904 : if (FLAG_lite_mode || FLAG_jitless) {
421 : // Both jitless and lite modes cannot optimize. Unit tests should handle
422 : // these the same way. In the future, the two flags may become synonyms.
423 : status |= static_cast<int>(OptimizationStatus::kLiteMode);
424 : }
425 5904 : if (!isolate->use_optimizer()) {
426 43 : status |= static_cast<int>(OptimizationStatus::kNeverOptimize);
427 : }
428 5904 : if (FLAG_always_opt || FLAG_prepare_always_opt) {
429 1620 : status |= static_cast<int>(OptimizationStatus::kAlwaysOptimize);
430 : }
431 5904 : if (FLAG_deopt_every_n_times) {
432 24 : status |= static_cast<int>(OptimizationStatus::kMaybeDeopted);
433 : }
434 :
435 : // This function is used by fuzzers to get coverage for optimizations
436 : // in compiler. Ignore calls on non-function objects to avoid runtime errors.
437 : CONVERT_ARG_HANDLE_CHECKED(Object, function_object, 0);
438 5904 : if (!function_object->IsJSFunction()) {
439 : return Smi::FromInt(status);
440 : }
441 5875 : Handle<JSFunction> function = Handle<JSFunction>::cast(function_object);
442 5875 : status |= static_cast<int>(OptimizationStatus::kIsFunction);
443 :
444 : bool sync_with_compiler_thread = true;
445 5875 : if (args.length() == 2) {
446 : CONVERT_ARG_HANDLE_CHECKED(Object, sync_object, 1);
447 5834 : if (!sync_object->IsString())
448 : return ReadOnlyRoots(isolate).undefined_value();
449 5834 : Handle<String> sync = Handle<String>::cast(sync_object);
450 11668 : if (sync->IsOneByteEqualTo(StaticCharVector("no sync"))) {
451 : sync_with_compiler_thread = false;
452 : }
453 : }
454 :
455 5875 : if (isolate->concurrent_recompilation_enabled() &&
456 : sync_with_compiler_thread) {
457 5908 : while (function->IsInOptimizationQueue()) {
458 78 : isolate->optimizing_compile_dispatcher()->InstallOptimizedFunctions();
459 78 : base::OS::Sleep(base::TimeDelta::FromMilliseconds(50));
460 : }
461 : }
462 :
463 5875 : if (function->IsMarkedForOptimization()) {
464 8 : status |= static_cast<int>(OptimizationStatus::kMarkedForOptimization);
465 5867 : } else if (function->IsInOptimizationQueue()) {
466 : status |=
467 32 : static_cast<int>(OptimizationStatus::kMarkedForConcurrentOptimization);
468 5835 : } else if (function->IsInOptimizationQueue()) {
469 0 : status |= static_cast<int>(OptimizationStatus::kOptimizingConcurrently);
470 : }
471 :
472 5875 : if (function->IsOptimized()) {
473 4785 : status |= static_cast<int>(OptimizationStatus::kOptimized);
474 9570 : if (function->code()->is_turbofanned()) {
475 4785 : status |= static_cast<int>(OptimizationStatus::kTurboFanned);
476 : }
477 : }
478 5875 : if (function->IsInterpreted()) {
479 1082 : status |= static_cast<int>(OptimizationStatus::kInterpreted);
480 : }
481 :
482 : // Additionally, detect activations of this frame on the stack, and report the
483 : // status of the topmost frame.
484 : JavaScriptFrame* frame = nullptr;
485 5875 : JavaScriptFrameIterator it(isolate);
486 35881 : while (!it.done()) {
487 60040 : if (it.frame()->function() == *function) {
488 : frame = it.frame();
489 : break;
490 : }
491 30006 : it.Advance();
492 : }
493 5875 : if (frame != nullptr) {
494 14 : status |= static_cast<int>(OptimizationStatus::kIsExecuting);
495 28 : if (frame->is_optimized()) {
496 : status |=
497 10 : static_cast<int>(OptimizationStatus::kTopmostFrameIsTurboFanned);
498 : }
499 : }
500 :
501 : return Smi::FromInt(status);
502 : }
503 :
504 148 : RUNTIME_FUNCTION(Runtime_UnblockConcurrentRecompilation) {
505 : DCHECK_EQ(0, args.length());
506 74 : if (FLAG_block_concurrent_recompilation &&
507 : isolate->concurrent_recompilation_enabled()) {
508 74 : isolate->optimizing_compile_dispatcher()->Unblock();
509 : }
510 : return ReadOnlyRoots(isolate).undefined_value();
511 : }
512 :
513 130 : RUNTIME_FUNCTION(Runtime_GetDeoptCount) {
514 : HandleScope scope(isolate);
515 : DCHECK_EQ(1, args.length());
516 65 : CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
517 : // Functions without a feedback vector have never deoptimized.
518 65 : if (!function->has_feedback_vector()) return Smi::kZero;
519 98 : return Smi::FromInt(function->feedback_vector()->deopt_count());
520 : }
521 :
522 45 : static void ReturnThis(const v8::FunctionCallbackInfo<v8::Value>& args) {
523 : args.GetReturnValue().Set(args.This());
524 45 : }
525 :
526 238 : RUNTIME_FUNCTION(Runtime_GetUndetectable) {
527 : HandleScope scope(isolate);
528 : DCHECK_EQ(0, args.length());
529 : v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
530 :
531 119 : Local<v8::ObjectTemplate> desc = v8::ObjectTemplate::New(v8_isolate);
532 119 : desc->MarkAsUndetectable();
533 119 : desc->SetCallAsFunctionHandler(ReturnThis);
534 : Local<v8::Object> obj;
535 238 : if (!desc->NewInstance(v8_isolate->GetCurrentContext()).ToLocal(&obj)) {
536 : return Object();
537 : }
538 : return *Utils::OpenHandle(*obj);
539 : }
540 :
541 80 : static void call_as_function(const v8::FunctionCallbackInfo<v8::Value>& args) {
542 : double v1 = args[0]
543 240 : ->NumberValue(v8::Isolate::GetCurrent()->GetCurrentContext())
544 : .ToChecked();
545 : double v2 = args[1]
546 240 : ->NumberValue(v8::Isolate::GetCurrent()->GetCurrentContext())
547 : .ToChecked();
548 80 : args.GetReturnValue().Set(
549 : v8::Number::New(v8::Isolate::GetCurrent(), v1 - v2));
550 80 : }
551 :
552 : // Returns a callable object. The object returns the difference of its two
553 : // parameters when it is called.
554 16 : RUNTIME_FUNCTION(Runtime_GetCallable) {
555 : HandleScope scope(isolate);
556 : DCHECK_EQ(0, args.length());
557 : v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
558 8 : Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(v8_isolate);
559 8 : Local<ObjectTemplate> instance_template = t->InstanceTemplate();
560 8 : instance_template->SetCallAsFunctionHandler(call_as_function);
561 8 : v8_isolate->GetCurrentContext();
562 : Local<v8::Object> instance =
563 8 : t->GetFunction(v8_isolate->GetCurrentContext())
564 : .ToLocalChecked()
565 8 : ->NewInstance(v8_isolate->GetCurrentContext())
566 : .ToLocalChecked();
567 : return *Utils::OpenHandle(*instance);
568 : }
569 :
570 104796 : RUNTIME_FUNCTION(Runtime_ClearFunctionFeedback) {
571 : HandleScope scope(isolate);
572 : DCHECK_EQ(1, args.length());
573 52398 : CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
574 52398 : function->ClearTypeFeedbackInfo();
575 : return ReadOnlyRoots(isolate).undefined_value();
576 : }
577 :
578 96 : RUNTIME_FUNCTION(Runtime_SetWasmCompileControls) {
579 : HandleScope scope(isolate);
580 48 : v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
581 48 : CHECK_EQ(args.length(), 2);
582 48 : CONVERT_ARG_HANDLE_CHECKED(Smi, block_size, 0);
583 48 : CONVERT_BOOLEAN_ARG_CHECKED(allow_async, 1);
584 48 : base::MutexGuard guard(g_PerIsolateWasmControlsMutex.Pointer());
585 48 : WasmCompileControls& ctrl = (*GetPerIsolateWasmControls())[v8_isolate];
586 48 : ctrl.AllowAnySizeForAsync = allow_async;
587 48 : ctrl.MaxWasmBufferSize = static_cast<uint32_t>(block_size->value());
588 48 : v8_isolate->SetWasmModuleCallback(WasmModuleOverride);
589 : return ReadOnlyRoots(isolate).undefined_value();
590 : }
591 :
592 16 : RUNTIME_FUNCTION(Runtime_SetWasmInstantiateControls) {
593 : HandleScope scope(isolate);
594 : v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
595 8 : CHECK_EQ(args.length(), 0);
596 8 : v8_isolate->SetWasmInstanceCallback(WasmInstanceOverride);
597 : return ReadOnlyRoots(isolate).undefined_value();
598 : }
599 :
600 108 : RUNTIME_FUNCTION(Runtime_NotifyContextDisposed) {
601 : HandleScope scope(isolate);
602 : DCHECK_EQ(0, args.length());
603 54 : isolate->heap()->NotifyContextDisposed(true);
604 : return ReadOnlyRoots(isolate).undefined_value();
605 : }
606 :
607 :
608 604 : RUNTIME_FUNCTION(Runtime_SetAllocationTimeout) {
609 : SealHandleScope shs(isolate);
610 : DCHECK(args.length() == 2 || args.length() == 3);
611 : #ifdef V8_ENABLE_ALLOCATION_TIMEOUT
612 : CONVERT_INT32_ARG_CHECKED(timeout, 1);
613 : isolate->heap()->set_allocation_timeout(timeout);
614 : #endif
615 : #ifdef DEBUG
616 : CONVERT_INT32_ARG_CHECKED(interval, 0);
617 : FLAG_gc_interval = interval;
618 : if (args.length() == 3) {
619 : // Enable/disable inline allocation if requested.
620 : CONVERT_BOOLEAN_ARG_CHECKED(inline_allocation, 2);
621 : if (inline_allocation) {
622 : isolate->heap()->EnableInlineAllocation();
623 : } else {
624 : isolate->heap()->DisableInlineAllocation();
625 : }
626 : }
627 : #endif
628 : return ReadOnlyRoots(isolate).undefined_value();
629 : }
630 :
631 :
632 1556 : RUNTIME_FUNCTION(Runtime_DebugPrint) {
633 : SealHandleScope shs(isolate);
634 : DCHECK_EQ(1, args.length());
635 :
636 778 : MaybeObject maybe_object(*args.address_of_arg_at(0));
637 :
638 1556 : StdoutStream os;
639 778 : if (maybe_object->IsCleared()) {
640 0 : os << "[weak cleared]";
641 : } else {
642 : Object object = maybe_object.GetHeapObjectOrSmi();
643 : bool weak = maybe_object.IsWeak();
644 :
645 : #ifdef DEBUG
646 : if (object->IsString() && !isolate->context().is_null()) {
647 : DCHECK(!weak);
648 : // If we have a string, assume it's a code "marker"
649 : // and print some interesting cpu debugging info.
650 : object->Print(os);
651 : JavaScriptFrameIterator it(isolate);
652 : JavaScriptFrame* frame = it.frame();
653 : os << "fp = " << reinterpret_cast<void*>(frame->fp())
654 : << ", sp = " << reinterpret_cast<void*>(frame->sp())
655 : << ", caller_sp = " << reinterpret_cast<void*>(frame->caller_sp())
656 : << ": ";
657 : } else {
658 : os << "DebugPrint: ";
659 : if (weak) {
660 : os << "[weak] ";
661 : }
662 : object->Print(os);
663 : }
664 : if (object->IsHeapObject()) {
665 : HeapObject::cast(object)->map()->Print(os);
666 : }
667 : #else
668 778 : if (weak) {
669 0 : os << "[weak] ";
670 : }
671 : // ShortPrint is available in release mode. Print is not.
672 778 : os << Brief(object);
673 : #endif
674 : }
675 : os << std::endl;
676 :
677 : return args[0]; // return TOS
678 : }
679 :
680 0 : RUNTIME_FUNCTION(Runtime_PrintWithNameForAssert) {
681 : SealHandleScope shs(isolate);
682 : DCHECK_EQ(2, args.length());
683 :
684 0 : CONVERT_ARG_CHECKED(String, name, 0);
685 :
686 0 : PrintF(" * ");
687 0 : StringCharacterStream stream(name);
688 0 : while (stream.HasMore()) {
689 0 : uint16_t character = stream.GetNext();
690 0 : PrintF("%c", character);
691 : }
692 0 : PrintF(": ");
693 0 : args[1]->ShortPrint();
694 0 : PrintF("\n");
695 :
696 : return ReadOnlyRoots(isolate).undefined_value();
697 : }
698 :
699 16 : RUNTIME_FUNCTION(Runtime_DebugTrace) {
700 : SealHandleScope shs(isolate);
701 : DCHECK_EQ(0, args.length());
702 8 : isolate->PrintStack(stdout);
703 : return ReadOnlyRoots(isolate).undefined_value();
704 : }
705 :
706 0 : RUNTIME_FUNCTION(Runtime_DebugTrackRetainingPath) {
707 : HandleScope scope(isolate);
708 : DCHECK_LE(1, args.length());
709 : DCHECK_GE(2, args.length());
710 0 : if (!FLAG_track_retaining_path) {
711 0 : PrintF("DebugTrackRetainingPath requires --track-retaining-path flag.\n");
712 : } else {
713 0 : CONVERT_ARG_HANDLE_CHECKED(HeapObject, object, 0);
714 : RetainingPathOption option = RetainingPathOption::kDefault;
715 0 : if (args.length() == 2) {
716 0 : CONVERT_ARG_HANDLE_CHECKED(String, str, 1);
717 0 : const char track_ephemeron_path[] = "track-ephemeron-path";
718 0 : if (str->IsOneByteEqualTo(StaticCharVector(track_ephemeron_path))) {
719 : option = RetainingPathOption::kTrackEphemeronPath;
720 0 : } else if (str->length() != 0) {
721 0 : PrintF("Unexpected second argument of DebugTrackRetainingPath.\n");
722 0 : PrintF("Expected an empty string or '%s', got '%s'.\n",
723 0 : track_ephemeron_path, str->ToCString().get());
724 : }
725 : }
726 0 : isolate->heap()->AddRetainingPathTarget(object, option);
727 : }
728 : return ReadOnlyRoots(isolate).undefined_value();
729 : }
730 :
731 : // This will not allocate (flatten the string), but it may run
732 : // very slowly for very deeply nested ConsStrings. For debugging use only.
733 0 : RUNTIME_FUNCTION(Runtime_GlobalPrint) {
734 : SealHandleScope shs(isolate);
735 : DCHECK_EQ(1, args.length());
736 :
737 0 : CONVERT_ARG_CHECKED(String, string, 0);
738 0 : StringCharacterStream stream(string);
739 0 : while (stream.HasMore()) {
740 0 : uint16_t character = stream.GetNext();
741 0 : PrintF("%c", character);
742 : }
743 : return string;
744 : }
745 :
746 :
747 0 : RUNTIME_FUNCTION(Runtime_SystemBreak) {
748 : // The code below doesn't create handles, but when breaking here in GDB
749 : // having a handle scope might be useful.
750 : HandleScope scope(isolate);
751 : DCHECK_EQ(0, args.length());
752 0 : base::OS::DebugBreak();
753 : return ReadOnlyRoots(isolate).undefined_value();
754 : }
755 :
756 :
757 84 : RUNTIME_FUNCTION(Runtime_SetForceSlowPath) {
758 : SealHandleScope shs(isolate);
759 : DCHECK_EQ(1, args.length());
760 : CONVERT_ARG_CHECKED(Object, arg, 0);
761 42 : if (arg->IsTrue(isolate)) {
762 : isolate->set_force_slow_path(true);
763 : } else {
764 : DCHECK(arg->IsFalse(isolate));
765 : isolate->set_force_slow_path(false);
766 : }
767 : return ReadOnlyRoots(isolate).undefined_value();
768 : }
769 :
770 0 : RUNTIME_FUNCTION(Runtime_Abort) {
771 : SealHandleScope shs(isolate);
772 : DCHECK_EQ(1, args.length());
773 0 : CONVERT_SMI_ARG_CHECKED(message_id, 0);
774 0 : const char* message = GetAbortReason(static_cast<AbortReason>(message_id));
775 0 : base::OS::PrintError("abort: %s\n", message);
776 0 : isolate->PrintStack(stderr);
777 0 : base::OS::Abort();
778 : UNREACHABLE();
779 : }
780 :
781 :
782 0 : RUNTIME_FUNCTION(Runtime_AbortJS) {
783 : HandleScope scope(isolate);
784 : DCHECK_EQ(1, args.length());
785 0 : CONVERT_ARG_HANDLE_CHECKED(String, message, 0);
786 0 : if (FLAG_disable_abortjs) {
787 0 : base::OS::PrintError("[disabled] abort: %s\n", message->ToCString().get());
788 : return Object();
789 : }
790 0 : base::OS::PrintError("abort: %s\n", message->ToCString().get());
791 0 : isolate->PrintStack(stderr);
792 0 : base::OS::Abort();
793 : UNREACHABLE();
794 : }
795 :
796 :
797 36 : RUNTIME_FUNCTION(Runtime_DisassembleFunction) {
798 : HandleScope scope(isolate);
799 : #ifdef DEBUG
800 : DCHECK_EQ(1, args.length());
801 : // Get the function and make sure it is compiled.
802 : CONVERT_ARG_HANDLE_CHECKED(JSFunction, func, 0);
803 : IsCompiledScope is_compiled_scope;
804 : if (!func->is_compiled() &&
805 : !Compiler::Compile(func, Compiler::KEEP_EXCEPTION, &is_compiled_scope)) {
806 : return ReadOnlyRoots(isolate).exception();
807 : }
808 : StdoutStream os;
809 : func->code()->Print(os);
810 : os << std::endl;
811 : #endif // DEBUG
812 : return ReadOnlyRoots(isolate).undefined_value();
813 : }
814 :
815 : namespace {
816 :
817 0 : int StackSize(Isolate* isolate) {
818 : int n = 0;
819 0 : for (JavaScriptFrameIterator it(isolate); !it.done(); it.Advance()) n++;
820 0 : return n;
821 : }
822 :
823 0 : void PrintIndentation(Isolate* isolate) {
824 : const int nmax = 80;
825 0 : int n = StackSize(isolate);
826 0 : if (n <= nmax) {
827 0 : PrintF("%4d:%*s", n, n, "");
828 : } else {
829 0 : PrintF("%4d:%*s", n, nmax, "...");
830 : }
831 0 : }
832 :
833 : } // namespace
834 :
835 0 : RUNTIME_FUNCTION(Runtime_TraceEnter) {
836 : SealHandleScope shs(isolate);
837 : DCHECK_EQ(0, args.length());
838 0 : PrintIndentation(isolate);
839 0 : JavaScriptFrame::PrintTop(isolate, stdout, true, false);
840 0 : PrintF(" {\n");
841 : return ReadOnlyRoots(isolate).undefined_value();
842 : }
843 :
844 :
845 0 : RUNTIME_FUNCTION(Runtime_TraceExit) {
846 : SealHandleScope shs(isolate);
847 : DCHECK_EQ(1, args.length());
848 0 : CONVERT_ARG_CHECKED(Object, obj, 0);
849 0 : PrintIndentation(isolate);
850 0 : PrintF("} -> ");
851 0 : obj->ShortPrint();
852 0 : PrintF("\n");
853 0 : return obj; // return TOS
854 : }
855 :
856 3422 : RUNTIME_FUNCTION(Runtime_HaveSameMap) {
857 : SealHandleScope shs(isolate);
858 : DCHECK_EQ(2, args.length());
859 3422 : CONVERT_ARG_CHECKED(JSObject, obj1, 0);
860 3422 : CONVERT_ARG_CHECKED(JSObject, obj2, 1);
861 3422 : return isolate->heap()->ToBoolean(obj1->map() == obj2->map());
862 : }
863 :
864 :
865 286 : RUNTIME_FUNCTION(Runtime_InNewSpace) {
866 : SealHandleScope shs(isolate);
867 : DCHECK_EQ(1, args.length());
868 : CONVERT_ARG_CHECKED(Object, obj, 0);
869 : return isolate->heap()->ToBoolean(ObjectInYoungGeneration(obj));
870 : }
871 :
872 8428 : RUNTIME_FUNCTION(Runtime_IsAsmWasmCode) {
873 : SealHandleScope shs(isolate);
874 : DCHECK_EQ(1, args.length());
875 8428 : CONVERT_ARG_CHECKED(JSFunction, function, 0);
876 4214 : if (!function->shared()->HasAsmWasmData()) {
877 : // Doesn't have wasm data.
878 : return ReadOnlyRoots(isolate).false_value();
879 : }
880 6044 : if (function->shared()->HasBuiltinId() &&
881 3022 : function->shared()->builtin_id() == Builtins::kInstantiateAsmJs) {
882 : // Hasn't been compiled yet.
883 : return ReadOnlyRoots(isolate).false_value();
884 : }
885 : return ReadOnlyRoots(isolate).true_value();
886 : }
887 :
888 : namespace {
889 72 : bool DisallowCodegenFromStringsCallback(v8::Local<v8::Context> context,
890 : v8::Local<v8::String> source) {
891 72 : return false;
892 : }
893 : }
894 :
895 288 : RUNTIME_FUNCTION(Runtime_DisallowCodegenFromStrings) {
896 : SealHandleScope shs(isolate);
897 : DCHECK_EQ(1, args.length());
898 144 : CONVERT_BOOLEAN_ARG_CHECKED(flag, 0);
899 : v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
900 144 : v8_isolate->SetAllowCodeGenerationFromStringsCallback(
901 144 : flag ? DisallowCodegenFromStringsCallback : nullptr);
902 : return ReadOnlyRoots(isolate).undefined_value();
903 : }
904 :
905 272 : RUNTIME_FUNCTION(Runtime_DisallowWasmCodegen) {
906 : SealHandleScope shs(isolate);
907 : DCHECK_EQ(1, args.length());
908 136 : CONVERT_BOOLEAN_ARG_CHECKED(flag, 0);
909 : v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
910 136 : v8_isolate->SetAllowWasmCodeGenerationCallback(
911 136 : flag ? DisallowCodegenFromStringsCallback : nullptr);
912 : return ReadOnlyRoots(isolate).undefined_value();
913 : }
914 :
915 80 : RUNTIME_FUNCTION(Runtime_IsWasmCode) {
916 : SealHandleScope shs(isolate);
917 : DCHECK_EQ(1, args.length());
918 80 : CONVERT_ARG_CHECKED(JSFunction, function, 0);
919 80 : bool is_js_to_wasm = function->code()->kind() == Code::JS_TO_WASM_FUNCTION;
920 : return isolate->heap()->ToBoolean(is_js_to_wasm);
921 : }
922 :
923 16080 : RUNTIME_FUNCTION(Runtime_IsWasmTrapHandlerEnabled) {
924 : DisallowHeapAllocation no_gc;
925 : DCHECK_EQ(0, args.length());
926 : return isolate->heap()->ToBoolean(trap_handler::IsTrapHandlerEnabled());
927 : }
928 :
929 1616 : RUNTIME_FUNCTION(Runtime_IsThreadInWasm) {
930 : DisallowHeapAllocation no_gc;
931 : DCHECK_EQ(0, args.length());
932 : return isolate->heap()->ToBoolean(trap_handler::IsThreadInWasm());
933 : }
934 :
935 32064 : RUNTIME_FUNCTION(Runtime_GetWasmRecoveredTrapCount) {
936 : HandleScope scope(isolate);
937 : DCHECK_EQ(0, args.length());
938 16032 : size_t trap_count = trap_handler::GetRecoveredTrapCount();
939 32064 : return *isolate->factory()->NewNumberFromSize(trap_count);
940 : }
941 :
942 416 : RUNTIME_FUNCTION(Runtime_GetWasmExceptionId) {
943 : HandleScope scope(isolate);
944 : DCHECK_EQ(2, args.length());
945 208 : CONVERT_ARG_HANDLE_CHECKED(JSReceiver, exception, 0);
946 208 : CONVERT_ARG_HANDLE_CHECKED(WasmInstanceObject, instance, 1);
947 : Handle<Object> tag =
948 208 : WasmExceptionPackage::GetExceptionTag(isolate, exception);
949 208 : if (tag->IsWasmExceptionTag()) {
950 : Handle<FixedArray> exceptions_table(instance->exceptions_table(), isolate);
951 288 : for (int index = 0; index < exceptions_table->length(); ++index) {
952 248 : if (exceptions_table->get(index) == *tag) return Smi::FromInt(index);
953 : }
954 : }
955 : return ReadOnlyRoots(isolate).undefined_value();
956 : }
957 :
958 400 : RUNTIME_FUNCTION(Runtime_GetWasmExceptionValues) {
959 : HandleScope scope(isolate);
960 : DCHECK_EQ(1, args.length());
961 200 : CONVERT_ARG_HANDLE_CHECKED(JSReceiver, exception, 0);
962 : Handle<Object> values_obj =
963 200 : WasmExceptionPackage::GetExceptionValues(isolate, exception);
964 200 : CHECK(values_obj->IsFixedArray()); // Only called with correct input.
965 200 : Handle<FixedArray> values = Handle<FixedArray>::cast(values_obj);
966 400 : return *isolate->factory()->NewJSArrayWithElements(values);
967 : }
968 :
969 : namespace {
970 16 : bool EnableWasmThreads(v8::Local<v8::Context> context) { return true; }
971 :
972 16 : bool DisableWasmThreads(v8::Local<v8::Context> context) { return false; }
973 : } // namespace
974 :
975 : // This runtime function enables WebAssembly threads through an embedder
976 : // callback and thereby bypasses the value in FLAG_experimental_wasm_threads.
977 48 : RUNTIME_FUNCTION(Runtime_SetWasmThreadsEnabled) {
978 : DCHECK_EQ(1, args.length());
979 24 : CONVERT_BOOLEAN_ARG_CHECKED(flag, 0);
980 : v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
981 24 : v8_isolate->SetWasmThreadsEnabledCallback(flag ? EnableWasmThreads
982 24 : : DisableWasmThreads);
983 : return ReadOnlyRoots(isolate).undefined_value();
984 : }
985 :
986 : #define ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(Name) \
987 : RUNTIME_FUNCTION(Runtime_Has##Name) { \
988 : CONVERT_ARG_CHECKED(JSObject, obj, 0); \
989 : return isolate->heap()->ToBoolean(obj->Has##Name()); \
990 : }
991 :
992 252 : ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastElements)
993 3609076 : ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(SmiElements)
994 5409236 : ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ObjectElements)
995 5400000 : ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(SmiOrObjectElements)
996 5412268 : ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(DoubleElements)
997 19806760 : ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(HoleyElements)
998 2452 : ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(DictionaryElements)
999 420 : ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(PackedElements)
1000 252 : ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(SloppyArgumentsElements)
1001 : // Properties test sitting with elements tests - not fooling anyone.
1002 34556 : ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastProperties)
1003 :
1004 : #undef ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION
1005 :
1006 : #define FIXED_TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION(Type, type, TYPE, ctype) \
1007 : RUNTIME_FUNCTION(Runtime_HasFixed##Type##Elements) { \
1008 : CONVERT_ARG_CHECKED(JSObject, obj, 0); \
1009 : return isolate->heap()->ToBoolean(obj->HasFixed##Type##Elements()); \
1010 : }
1011 :
1012 1800 : TYPED_ARRAYS(FIXED_TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION)
1013 :
1014 : #undef FIXED_TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION
1015 :
1016 344 : RUNTIME_FUNCTION(Runtime_ArraySpeciesProtector) {
1017 : SealHandleScope shs(isolate);
1018 : DCHECK_EQ(0, args.length());
1019 : return isolate->heap()->ToBoolean(isolate->IsArraySpeciesLookupChainIntact());
1020 : }
1021 :
1022 400 : RUNTIME_FUNCTION(Runtime_MapIteratorProtector) {
1023 : SealHandleScope shs(isolate);
1024 : DCHECK_EQ(0, args.length());
1025 : return isolate->heap()->ToBoolean(isolate->IsMapIteratorLookupChainIntact());
1026 : }
1027 :
1028 400 : RUNTIME_FUNCTION(Runtime_SetIteratorProtector) {
1029 : SealHandleScope shs(isolate);
1030 : DCHECK_EQ(0, args.length());
1031 : return isolate->heap()->ToBoolean(isolate->IsSetIteratorLookupChainIntact());
1032 : }
1033 :
1034 208 : RUNTIME_FUNCTION(Runtime_StringIteratorProtector) {
1035 : SealHandleScope shs(isolate);
1036 : DCHECK_EQ(0, args.length());
1037 : return isolate->heap()->ToBoolean(
1038 : isolate->IsStringIteratorLookupChainIntact());
1039 : }
1040 :
1041 : // Take a compiled wasm module and serialize it into an array buffer, which is
1042 : // then returned.
1043 336 : RUNTIME_FUNCTION(Runtime_SerializeWasmModule) {
1044 : HandleScope scope(isolate);
1045 : DCHECK_EQ(1, args.length());
1046 168 : CONVERT_ARG_HANDLE_CHECKED(WasmModuleObject, module_obj, 0);
1047 :
1048 168 : wasm::NativeModule* native_module = module_obj->native_module();
1049 336 : wasm::WasmSerializer wasm_serializer(native_module);
1050 168 : size_t compiled_size = wasm_serializer.GetSerializedNativeModuleSize();
1051 168 : void* array_data = isolate->array_buffer_allocator()->Allocate(compiled_size);
1052 : Handle<JSArrayBuffer> array_buffer =
1053 168 : isolate->factory()->NewJSArrayBuffer(SharedFlag::kNotShared);
1054 168 : JSArrayBuffer::Setup(array_buffer, isolate, false, array_data, compiled_size);
1055 336 : if (!array_data ||
1056 168 : !wasm_serializer.SerializeNativeModule(
1057 : {reinterpret_cast<uint8_t*>(array_data), compiled_size})) {
1058 : return ReadOnlyRoots(isolate).undefined_value();
1059 : }
1060 : return *array_buffer;
1061 : }
1062 :
1063 : // Take an array buffer and attempt to reconstruct a compiled wasm module.
1064 : // Return undefined if unsuccessful.
1065 352 : RUNTIME_FUNCTION(Runtime_DeserializeWasmModule) {
1066 : HandleScope scope(isolate);
1067 : DCHECK_EQ(2, args.length());
1068 176 : CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, buffer, 0);
1069 176 : CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, wire_bytes, 1);
1070 176 : CHECK(!buffer->was_detached());
1071 176 : CHECK(!wire_bytes->WasDetached());
1072 :
1073 176 : Handle<JSArrayBuffer> wire_bytes_buffer = wire_bytes->GetBuffer();
1074 : Vector<const uint8_t> wire_bytes_vec{
1075 : reinterpret_cast<const uint8_t*>(wire_bytes_buffer->backing_store()) +
1076 : wire_bytes->byte_offset(),
1077 176 : wire_bytes->byte_length()};
1078 : Vector<uint8_t> buffer_vec{
1079 : reinterpret_cast<uint8_t*>(buffer->backing_store()),
1080 : buffer->byte_length()};
1081 :
1082 : // Note that {wasm::DeserializeNativeModule} will allocate. We assume the
1083 : // JSArrayBuffer backing store doesn't get relocated.
1084 : MaybeHandle<WasmModuleObject> maybe_module_object =
1085 176 : wasm::DeserializeNativeModule(isolate, buffer_vec, wire_bytes_vec);
1086 : Handle<WasmModuleObject> module_object;
1087 176 : if (!maybe_module_object.ToHandle(&module_object)) {
1088 : return ReadOnlyRoots(isolate).undefined_value();
1089 : }
1090 : return *module_object;
1091 : }
1092 :
1093 17658 : RUNTIME_FUNCTION(Runtime_HeapObjectVerify) {
1094 : HandleScope shs(isolate);
1095 : DCHECK_EQ(1, args.length());
1096 : CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
1097 : #ifdef VERIFY_HEAP
1098 : object->ObjectVerify(isolate);
1099 : #else
1100 : CHECK(object->IsObject());
1101 8829 : if (object->IsHeapObject()) {
1102 17604 : CHECK(HeapObject::cast(*object)->map()->IsMap());
1103 : } else {
1104 27 : CHECK(object->IsSmi());
1105 : }
1106 : #endif
1107 : return isolate->heap()->ToBoolean(true);
1108 : }
1109 :
1110 112 : RUNTIME_FUNCTION(Runtime_WasmGetNumberOfInstances) {
1111 : SealHandleScope shs(isolate);
1112 : DCHECK_EQ(1, args.length());
1113 56 : CONVERT_ARG_HANDLE_CHECKED(WasmModuleObject, module_obj, 0);
1114 : int instance_count = 0;
1115 56 : WeakArrayList weak_instance_list = module_obj->weak_instance_list();
1116 296 : for (int i = 0; i < weak_instance_list->length(); ++i) {
1117 240 : if (weak_instance_list->Get(i)->IsWeak()) instance_count++;
1118 : }
1119 : return Smi::FromInt(instance_count);
1120 : }
1121 :
1122 960 : RUNTIME_FUNCTION(Runtime_WasmNumInterpretedCalls) {
1123 : DCHECK_EQ(1, args.length());
1124 : HandleScope scope(isolate);
1125 480 : CONVERT_ARG_HANDLE_CHECKED(WasmInstanceObject, instance, 0);
1126 480 : if (!instance->has_debug_info()) return Object();
1127 280 : uint64_t num = instance->debug_info()->NumInterpretedCalls();
1128 560 : return *isolate->factory()->NewNumberFromSize(static_cast<size_t>(num));
1129 : }
1130 :
1131 208 : RUNTIME_FUNCTION(Runtime_RedirectToWasmInterpreter) {
1132 : DCHECK_EQ(2, args.length());
1133 : HandleScope scope(isolate);
1134 104 : CONVERT_ARG_HANDLE_CHECKED(WasmInstanceObject, instance, 0);
1135 208 : CONVERT_SMI_ARG_CHECKED(function_index, 1);
1136 : Handle<WasmDebugInfo> debug_info =
1137 104 : WasmInstanceObject::GetOrCreateDebugInfo(instance);
1138 208 : WasmDebugInfo::RedirectToInterpreter(debug_info,
1139 104 : Vector<int>(&function_index, 1));
1140 : return ReadOnlyRoots(isolate).undefined_value();
1141 : }
1142 :
1143 144 : RUNTIME_FUNCTION(Runtime_WasmTraceMemory) {
1144 : HandleScope scope(isolate);
1145 : DCHECK_EQ(1, args.length());
1146 72 : CONVERT_ARG_CHECKED(Smi, info_addr, 0);
1147 :
1148 : wasm::MemoryTracingInfo* info =
1149 72 : reinterpret_cast<wasm::MemoryTracingInfo*>(info_addr.ptr());
1150 :
1151 : // Find the caller wasm frame.
1152 72 : StackTraceFrameIterator it(isolate);
1153 : DCHECK(!it.done());
1154 : DCHECK(it.is_wasm());
1155 : WasmCompiledFrame* frame = WasmCompiledFrame::cast(it.frame());
1156 :
1157 : uint8_t* mem_start = reinterpret_cast<uint8_t*>(
1158 144 : frame->wasm_instance()->memory_object()->array_buffer()->backing_store());
1159 72 : int func_index = frame->function_index();
1160 72 : int pos = frame->position();
1161 : // TODO(titzer): eliminate dependency on WasmModule definition here.
1162 : int func_start =
1163 72 : frame->wasm_instance()->module()->functions[func_index].code.offset();
1164 72 : wasm::ExecutionTier tier = frame->wasm_code()->is_liftoff()
1165 : ? wasm::ExecutionTier::kBaseline
1166 72 : : wasm::ExecutionTier::kOptimized;
1167 72 : wasm::TraceMemoryOperation(tier, info, func_index, pos - func_start,
1168 72 : mem_start);
1169 : return ReadOnlyRoots(isolate).undefined_value();
1170 : }
1171 :
1172 32 : RUNTIME_FUNCTION(Runtime_WasmTierUpFunction) {
1173 : HandleScope scope(isolate);
1174 : DCHECK_EQ(2, args.length());
1175 16 : CONVERT_ARG_HANDLE_CHECKED(WasmInstanceObject, instance, 0);
1176 16 : CONVERT_SMI_ARG_CHECKED(function_index, 1);
1177 16 : auto* native_module = instance->module_object()->native_module();
1178 16 : isolate->wasm_engine()->CompileFunction(
1179 16 : isolate, native_module, function_index, wasm::ExecutionTier::kOptimized);
1180 16 : CHECK(!native_module->compilation_state()->failed());
1181 : return ReadOnlyRoots(isolate).undefined_value();
1182 : }
1183 :
1184 224 : RUNTIME_FUNCTION(Runtime_IsLiftoffFunction) {
1185 : HandleScope scope(isolate);
1186 : DCHECK_EQ(1, args.length());
1187 112 : CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
1188 112 : CHECK(WasmExportedFunction::IsWasmExportedFunction(*function));
1189 : Handle<WasmExportedFunction> exp_fun =
1190 : Handle<WasmExportedFunction>::cast(function);
1191 : wasm::NativeModule* native_module =
1192 224 : exp_fun->instance()->module_object()->native_module();
1193 112 : uint32_t func_index = exp_fun->function_index();
1194 : return isolate->heap()->ToBoolean(
1195 112 : native_module->has_code(func_index) &&
1196 : native_module->code(func_index)->is_liftoff());
1197 : }
1198 :
1199 36 : RUNTIME_FUNCTION(Runtime_CompleteInobjectSlackTracking) {
1200 : HandleScope scope(isolate);
1201 : DCHECK_EQ(1, args.length());
1202 :
1203 18 : CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
1204 18 : object->map()->CompleteInobjectSlackTracking(isolate);
1205 :
1206 : return ReadOnlyRoots(isolate).undefined_value();
1207 : }
1208 :
1209 96 : RUNTIME_FUNCTION(Runtime_FreezeWasmLazyCompilation) {
1210 : DCHECK_EQ(1, args.length());
1211 : DisallowHeapAllocation no_gc;
1212 48 : CONVERT_ARG_CHECKED(WasmInstanceObject, instance, 0);
1213 :
1214 96 : instance->module_object()->native_module()->set_lazy_compile_frozen(true);
1215 : return ReadOnlyRoots(isolate).undefined_value();
1216 : }
1217 :
1218 2412 : RUNTIME_FUNCTION(Runtime_WasmMemoryHasFullGuardRegion) {
1219 : DCHECK_EQ(1, args.length());
1220 : DisallowHeapAllocation no_gc;
1221 2412 : CONVERT_ARG_CHECKED(WasmMemoryObject, memory, 0);
1222 :
1223 1206 : return isolate->heap()->ToBoolean(memory->has_full_guard_region(isolate));
1224 : }
1225 :
1226 : } // namespace internal
1227 120216 : } // namespace v8
|