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 <fstream>
6#include <memory>
7
8#include "include/v8-function.h"
9#include "src/api/api-inl.h"
10#include "src/base/numbers/double.h"
11#include "src/base/platform/mutex.h"
12#include "src/codegen/assembler-inl.h"
13#include "src/codegen/compiler.h"
14#include "src/codegen/pending-optimization-table.h"
15#include "src/compiler-dispatcher/lazy-compile-dispatcher.h"
16#include "src/compiler-dispatcher/optimizing-compile-dispatcher.h"
17#include "src/debug/debug-evaluate.h"
18#include "src/deoptimizer/deoptimizer.h"
19#include "src/execution/arguments-inl.h"
20#include "src/execution/frames-inl.h"
21#include "src/execution/isolate-inl.h"
22#include "src/execution/protectors-inl.h"
23#include "src/execution/tiering-manager.h"
24#include "src/heap/heap-inl.h"  // For ToBoolean. TODO(jkummerow): Drop.
25#include "src/heap/heap-write-barrier-inl.h"
26#include "src/ic/stub-cache.h"
27#include "src/logging/counters.h"
28#include "src/objects/heap-object-inl.h"
29#include "src/objects/js-array-inl.h"
30#include "src/objects/js-collection-inl.h"
31#include "src/objects/js-function-inl.h"
32#include "src/objects/js-regexp-inl.h"
33#include "src/objects/managed-inl.h"
34#include "src/objects/smi.h"
35#include "src/profiler/heap-snapshot-generator.h"
36#include "src/regexp/regexp.h"
37#include "src/runtime/runtime-utils.h"
38#include "src/snapshot/snapshot.h"
39#include "src/web-snapshot/web-snapshot.h"
40
41#ifdef V8_ENABLE_MAGLEV
42#include "src/maglev/maglev.h"
43#endif  // V8_ENABLE_MAGLEV
44
45#if V8_ENABLE_WEBASSEMBLY
46#include "src/wasm/wasm-engine.h"
47#endif  // V8_ENABLE_WEBASSEMBLY
48
49namespace v8 {
50namespace internal {
51
52namespace {
53V8_WARN_UNUSED_RESULT Object CrashUnlessFuzzing(Isolate* isolate) {
54  CHECK(FLAG_fuzzing);
55  return ReadOnlyRoots(isolate).undefined_value();
56}
57
58V8_WARN_UNUSED_RESULT bool CrashUnlessFuzzingReturnFalse(Isolate* isolate) {
59  CHECK(FLAG_fuzzing);
60  return false;
61}
62
63// Returns |value| unless correctness-fuzzer-supressions is enabled,
64// otherwise returns undefined_value.
65V8_WARN_UNUSED_RESULT Object ReturnFuzzSafe(Object value, Isolate* isolate) {
66  return FLAG_correctness_fuzzer_suppressions
67             ? ReadOnlyRoots(isolate).undefined_value()
68             : value;
69}
70
71// Assert that the given argument is a number within the Int32 range
72// and convert it to int32_t.  If the argument is not an Int32 we crash if not
73// in fuzzing mode.
74#define CONVERT_INT32_ARG_FUZZ_SAFE(name, index)                   \
75  if (!args[index].IsNumber()) return CrashUnlessFuzzing(isolate); \
76  int32_t name = 0;                                                \
77  if (!args[index].ToInt32(&name)) return CrashUnlessFuzzing(isolate);
78
79// Cast the given object to a boolean and store it in a variable with
80// the given name.  If the object is not a boolean we crash if not in
81// fuzzing mode.
82#define CONVERT_BOOLEAN_ARG_FUZZ_SAFE(name, index)                  \
83  if (!args[index].IsBoolean()) return CrashUnlessFuzzing(isolate); \
84  bool name = args[index].IsTrue(isolate);
85
86bool IsAsmWasmFunction(Isolate* isolate, JSFunction function) {
87  DisallowGarbageCollection no_gc;
88#if V8_ENABLE_WEBASSEMBLY
89  // For simplicity we include invalid asm.js functions whose code hasn't yet
90  // been updated to CompileLazy but is still the InstantiateAsmJs builtin.
91  return function.shared().HasAsmWasmData() ||
92         function.code().builtin_id() == Builtin::kInstantiateAsmJs;
93#else
94  return false;
95#endif  // V8_ENABLE_WEBASSEMBLY
96}
97
98}  // namespace
99
100RUNTIME_FUNCTION(Runtime_ClearMegamorphicStubCache) {
101  HandleScope scope(isolate);
102  DCHECK_EQ(0, args.length());
103  isolate->load_stub_cache()->Clear();
104  isolate->store_stub_cache()->Clear();
105  return ReadOnlyRoots(isolate).undefined_value();
106}
107
108RUNTIME_FUNCTION(Runtime_ConstructDouble) {
109  HandleScope scope(isolate);
110  DCHECK_EQ(2, args.length());
111  uint32_t hi = NumberToUint32(args[0]);
112  uint32_t lo = NumberToUint32(args[1]);
113  uint64_t result = (static_cast<uint64_t>(hi) << 32) | lo;
114  return *isolate->factory()->NewNumber(base::uint64_to_double(result));
115}
116
117RUNTIME_FUNCTION(Runtime_ConstructConsString) {
118  HandleScope scope(isolate);
119  DCHECK_EQ(2, args.length());
120  Handle<String> left = args.at<String>(0);
121  Handle<String> right = args.at<String>(1);
122
123  CHECK(left->IsOneByteRepresentation());
124  CHECK(right->IsOneByteRepresentation());
125
126  const bool kIsOneByte = true;
127  const int length = left->length() + right->length();
128  return *isolate->factory()->NewConsString(left, right, length, kIsOneByte);
129}
130
131RUNTIME_FUNCTION(Runtime_ConstructSlicedString) {
132  HandleScope scope(isolate);
133  DCHECK_EQ(2, args.length());
134  Handle<String> string = args.at<String>(0);
135  int index = args.smi_value_at(1);
136
137  CHECK(string->IsOneByteRepresentation());
138  CHECK_LT(index, string->length());
139
140  Handle<String> sliced_string =
141      isolate->factory()->NewSubString(string, index, string->length());
142  CHECK(sliced_string->IsSlicedString());
143  return *sliced_string;
144}
145
146RUNTIME_FUNCTION(Runtime_DeoptimizeFunction) {
147  HandleScope scope(isolate);
148  DCHECK_EQ(1, args.length());
149
150  Handle<Object> function_object = args.at(0);
151  if (!function_object->IsJSFunction()) return CrashUnlessFuzzing(isolate);
152  Handle<JSFunction> function = Handle<JSFunction>::cast(function_object);
153
154  if (function->HasAttachedOptimizedCode()) {
155    Deoptimizer::DeoptimizeFunction(*function);
156  }
157
158  return ReadOnlyRoots(isolate).undefined_value();
159}
160
161RUNTIME_FUNCTION(Runtime_DeoptimizeNow) {
162  HandleScope scope(isolate);
163  DCHECK_EQ(0, args.length());
164
165  Handle<JSFunction> function;
166
167  // Find the JavaScript function on the top of the stack.
168  JavaScriptFrameIterator it(isolate);
169  if (!it.done()) function = handle(it.frame()->function(), isolate);
170  if (function.is_null()) return CrashUnlessFuzzing(isolate);
171
172  if (function->HasAttachedOptimizedCode()) {
173    Deoptimizer::DeoptimizeFunction(*function);
174  }
175
176  return ReadOnlyRoots(isolate).undefined_value();
177}
178
179RUNTIME_FUNCTION(Runtime_RunningInSimulator) {
180  SealHandleScope shs(isolate);
181  DCHECK_EQ(0, args.length());
182#if defined(USE_SIMULATOR)
183  return ReadOnlyRoots(isolate).true_value();
184#else
185  return ReadOnlyRoots(isolate).false_value();
186#endif
187}
188
189RUNTIME_FUNCTION(Runtime_RuntimeEvaluateREPL) {
190  HandleScope scope(isolate);
191  DCHECK_EQ(1, args.length());
192  Handle<String> source = args.at<String>(0);
193  Handle<Object> result;
194  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
195      isolate, result,
196      DebugEvaluate::Global(isolate, source,
197                            debug::EvaluateGlobalMode::kDefault,
198                            REPLMode::kYes));
199
200  return *result;
201}
202
203RUNTIME_FUNCTION(Runtime_ICsAreEnabled) {
204  SealHandleScope shs(isolate);
205  DCHECK_EQ(0, args.length());
206  return isolate->heap()->ToBoolean(FLAG_use_ic);
207}
208
209RUNTIME_FUNCTION(Runtime_IsConcurrentRecompilationSupported) {
210  SealHandleScope shs(isolate);
211  DCHECK_EQ(0, args.length());
212  return isolate->heap()->ToBoolean(
213      isolate->concurrent_recompilation_enabled());
214}
215
216RUNTIME_FUNCTION(Runtime_IsAtomicsWaitAllowed) {
217  SealHandleScope shs(isolate);
218  DCHECK_EQ(0, args.length());
219  return isolate->heap()->ToBoolean(isolate->allow_atomics_wait());
220}
221
222namespace {
223
224template <CodeKind code_kind>
225bool CanOptimizeFunction(Handle<JSFunction> function, Isolate* isolate,
226                         IsCompiledScope* is_compiled_scope);
227
228template <>
229bool CanOptimizeFunction<CodeKind::TURBOFAN>(
230    Handle<JSFunction> function, Isolate* isolate,
231    IsCompiledScope* is_compiled_scope) {
232  // The following conditions were lifted (in part) from the DCHECK inside
233  // JSFunction::MarkForOptimization().
234
235  if (!function->shared().allows_lazy_compilation()) {
236    return CrashUnlessFuzzingReturnFalse(isolate);
237  }
238
239  // If function isn't compiled, compile it now.
240  if (!is_compiled_scope->is_compiled() &&
241      !Compiler::Compile(isolate, function, Compiler::CLEAR_EXCEPTION,
242                         is_compiled_scope)) {
243    return CrashUnlessFuzzingReturnFalse(isolate);
244  }
245
246  if (!FLAG_opt) return false;
247
248  if (function->shared().optimization_disabled() &&
249      function->shared().disabled_optimization_reason() ==
250          BailoutReason::kNeverOptimize) {
251    return CrashUnlessFuzzingReturnFalse(isolate);
252  }
253
254  if (IsAsmWasmFunction(isolate, *function)) {
255    return CrashUnlessFuzzingReturnFalse(isolate);
256  }
257
258  if (FLAG_testing_d8_test_runner) {
259    PendingOptimizationTable::MarkedForOptimization(isolate, function);
260  }
261
262  CodeKind kind = CodeKindForTopTier();
263  if (function->HasAvailableOptimizedCode() ||
264      function->HasAvailableCodeKind(kind)) {
265    DCHECK(function->HasAttachedOptimizedCode() ||
266           function->ChecksTieringState());
267    if (FLAG_testing_d8_test_runner) {
268      PendingOptimizationTable::FunctionWasOptimized(isolate, function);
269    }
270    return false;
271  }
272
273  return true;
274}
275
276#ifdef V8_ENABLE_MAGLEV
277template <>
278bool CanOptimizeFunction<CodeKind::MAGLEV>(Handle<JSFunction> function,
279                                           Isolate* isolate,
280                                           IsCompiledScope* is_compiled_scope) {
281  if (!FLAG_maglev) return false;
282
283  CHECK(!IsAsmWasmFunction(isolate, *function));
284
285  // TODO(v8:7700): Disabled optimization due to deopts?
286  // TODO(v8:7700): Already cached?
287
288  return function->GetActiveTier() < CodeKind::MAGLEV;
289}
290#endif  // V8_ENABLE_MAGLEV
291
292Object OptimizeFunctionOnNextCall(RuntimeArguments& args, Isolate* isolate) {
293  if (args.length() != 1 && args.length() != 2) {
294    return CrashUnlessFuzzing(isolate);
295  }
296
297  Handle<Object> function_object = args.at(0);
298  if (!function_object->IsJSFunction()) return CrashUnlessFuzzing(isolate);
299  Handle<JSFunction> function = Handle<JSFunction>::cast(function_object);
300
301  static constexpr CodeKind kCodeKind = CodeKind::TURBOFAN;
302
303  IsCompiledScope is_compiled_scope(
304      function->shared().is_compiled_scope(isolate));
305  if (!CanOptimizeFunction<kCodeKind>(function, isolate, &is_compiled_scope)) {
306    return ReadOnlyRoots(isolate).undefined_value();
307  }
308
309  ConcurrencyMode concurrency_mode = ConcurrencyMode::kSynchronous;
310  if (args.length() == 2) {
311    Handle<Object> type = args.at(1);
312    if (!type->IsString()) return CrashUnlessFuzzing(isolate);
313    if (Handle<String>::cast(type)->IsOneByteEqualTo(
314            base::StaticCharVector("concurrent")) &&
315        isolate->concurrent_recompilation_enabled()) {
316      concurrency_mode = ConcurrencyMode::kConcurrent;
317    }
318  }
319
320  // This function may not have been lazily compiled yet, even though its shared
321  // function has.
322  if (!function->is_compiled()) {
323    DCHECK(function->shared().HasBytecodeArray());
324    CodeT codet = *BUILTIN_CODE(isolate, InterpreterEntryTrampoline);
325    if (function->shared().HasBaselineCode()) {
326      codet = function->shared().baseline_code(kAcquireLoad);
327    }
328    function->set_code(codet);
329  }
330
331  TraceManualRecompile(*function, kCodeKind, concurrency_mode);
332  JSFunction::EnsureFeedbackVector(isolate, function, &is_compiled_scope);
333  function->MarkForOptimization(isolate, CodeKind::TURBOFAN, concurrency_mode);
334
335  return ReadOnlyRoots(isolate).undefined_value();
336}
337
338bool EnsureFeedbackVector(Isolate* isolate, Handle<JSFunction> function) {
339  // Check function allows lazy compilation.
340  if (!function->shared().allows_lazy_compilation()) return false;
341
342  if (function->has_feedback_vector()) return true;
343
344  // If function isn't compiled, compile it now.
345  IsCompiledScope is_compiled_scope(
346      function->shared().is_compiled_scope(function->GetIsolate()));
347  // If the JSFunction isn't compiled but it has a initialized feedback cell
348  // then no need to compile. CompileLazy builtin would handle these cases by
349  // installing the code from SFI. Calling compile here may cause another
350  // optimization if FLAG_always_opt is set.
351  bool needs_compilation =
352      !function->is_compiled() && !function->has_closure_feedback_cell_array();
353  if (needs_compilation &&
354      !Compiler::Compile(isolate, function, Compiler::CLEAR_EXCEPTION,
355                         &is_compiled_scope)) {
356    return false;
357  }
358
359  // Ensure function has a feedback vector to hold type feedback for
360  // optimization.
361  JSFunction::EnsureFeedbackVector(isolate, function, &is_compiled_scope);
362  return true;
363}
364
365}  // namespace
366
367RUNTIME_FUNCTION(Runtime_CompileBaseline) {
368  HandleScope scope(isolate);
369  if (args.length() != 1) {
370    return CrashUnlessFuzzing(isolate);
371  }
372  Handle<Object> function_object = args.at(0);
373  if (!function_object->IsJSFunction()) return CrashUnlessFuzzing(isolate);
374  Handle<JSFunction> function = Handle<JSFunction>::cast(function_object);
375
376  IsCompiledScope is_compiled_scope =
377      function->shared(isolate).is_compiled_scope(isolate);
378
379  if (!function->shared(isolate).IsUserJavaScript()) {
380    return CrashUnlessFuzzing(isolate);
381  }
382
383  // First compile the bytecode, if we have to.
384  if (!is_compiled_scope.is_compiled() &&
385      !Compiler::Compile(isolate, function, Compiler::CLEAR_EXCEPTION,
386                         &is_compiled_scope)) {
387    return CrashUnlessFuzzing(isolate);
388  }
389
390  if (!Compiler::CompileBaseline(isolate, function, Compiler::CLEAR_EXCEPTION,
391                                 &is_compiled_scope)) {
392    return CrashUnlessFuzzing(isolate);
393  }
394
395  return *function;
396}
397
398// TODO(v8:7700): Remove this function once we no longer need it to measure
399// maglev compile times. For normal tierup, OptimizeMaglevOnNextCall should be
400// used instead.
401#ifdef V8_ENABLE_MAGLEV
402RUNTIME_FUNCTION(Runtime_BenchMaglev) {
403  HandleScope scope(isolate);
404  DCHECK_EQ(args.length(), 2);
405  Handle<JSFunction> function = args.at<JSFunction>(0);
406  int count = args.smi_value_at(1);
407
408  Handle<CodeT> codet;
409  base::ElapsedTimer timer;
410  timer.Start();
411  codet = Maglev::Compile(isolate, function).ToHandleChecked();
412  for (int i = 1; i < count; ++i) {
413    HandleScope handle_scope(isolate);
414    Maglev::Compile(isolate, function);
415  }
416  PrintF("Maglev compile time: %g ms!\n",
417         timer.Elapsed().InMillisecondsF() / count);
418
419  function->set_code(*codet);
420
421  return ReadOnlyRoots(isolate).undefined_value();
422}
423#else
424RUNTIME_FUNCTION(Runtime_BenchMaglev) {
425  PrintF("Maglev is not enabled.\n");
426  return ReadOnlyRoots(isolate).undefined_value();
427}
428#endif  // V8_ENABLE_MAGLEV
429
430RUNTIME_FUNCTION(Runtime_ActiveTierIsMaglev) {
431  HandleScope scope(isolate);
432  DCHECK_EQ(args.length(), 1);
433  Handle<JSFunction> function = args.at<JSFunction>(0);
434  return isolate->heap()->ToBoolean(function->ActiveTierIsMaglev());
435}
436
437#ifdef V8_ENABLE_MAGLEV
438RUNTIME_FUNCTION(Runtime_OptimizeMaglevOnNextCall) {
439  HandleScope scope(isolate);
440  DCHECK_EQ(args.length(), 1);
441  Handle<JSFunction> function = args.at<JSFunction>(0);
442
443  static constexpr CodeKind kCodeKind = CodeKind::MAGLEV;
444
445  IsCompiledScope is_compiled_scope(
446      function->shared().is_compiled_scope(isolate));
447  if (!CanOptimizeFunction<kCodeKind>(function, isolate, &is_compiled_scope)) {
448    return ReadOnlyRoots(isolate).undefined_value();
449  }
450  DCHECK(is_compiled_scope.is_compiled());
451  DCHECK(function->is_compiled());
452
453  // TODO(v8:7700): Support concurrent compiles.
454  const ConcurrencyMode concurrency_mode = ConcurrencyMode::kSynchronous;
455
456  TraceManualRecompile(*function, kCodeKind, concurrency_mode);
457  JSFunction::EnsureFeedbackVector(isolate, function, &is_compiled_scope);
458  function->MarkForOptimization(isolate, kCodeKind, concurrency_mode);
459
460  return ReadOnlyRoots(isolate).undefined_value();
461}
462#else
463RUNTIME_FUNCTION(Runtime_OptimizeMaglevOnNextCall) {
464  PrintF("Maglev is not enabled.\n");
465  return ReadOnlyRoots(isolate).undefined_value();
466}
467#endif  // V8_ENABLE_MAGLEV
468
469// TODO(jgruber): Rename to OptimizeTurbofanOnNextCall.
470RUNTIME_FUNCTION(Runtime_OptimizeFunctionOnNextCall) {
471  HandleScope scope(isolate);
472  return OptimizeFunctionOnNextCall(args, isolate);
473}
474
475RUNTIME_FUNCTION(Runtime_EnsureFeedbackVectorForFunction) {
476  HandleScope scope(isolate);
477  DCHECK_EQ(1, args.length());
478  Handle<JSFunction> function = args.at<JSFunction>(0);
479  EnsureFeedbackVector(isolate, function);
480  return ReadOnlyRoots(isolate).undefined_value();
481}
482
483RUNTIME_FUNCTION(Runtime_PrepareFunctionForOptimization) {
484  HandleScope scope(isolate);
485  if ((args.length() != 1 && args.length() != 2) || !args[0].IsJSFunction()) {
486    return CrashUnlessFuzzing(isolate);
487  }
488  Handle<JSFunction> function = args.at<JSFunction>(0);
489
490  bool allow_heuristic_optimization = false;
491  if (args.length() == 2) {
492    Handle<Object> sync_object = args.at(1);
493    if (!sync_object->IsString()) return CrashUnlessFuzzing(isolate);
494    Handle<String> sync = Handle<String>::cast(sync_object);
495    if (sync->IsOneByteEqualTo(
496            base::StaticCharVector("allow heuristic optimization"))) {
497      allow_heuristic_optimization = true;
498    }
499  }
500
501  if (!EnsureFeedbackVector(isolate, function)) {
502    return CrashUnlessFuzzing(isolate);
503  }
504
505  // If optimization is disabled for the function, return without making it
506  // pending optimize for test.
507  if (function->shared().optimization_disabled() &&
508      function->shared().disabled_optimization_reason() ==
509          BailoutReason::kNeverOptimize) {
510    return CrashUnlessFuzzing(isolate);
511  }
512
513  if (IsAsmWasmFunction(isolate, *function)) return CrashUnlessFuzzing(isolate);
514
515  // Hold onto the bytecode array between marking and optimization to ensure
516  // it's not flushed.
517  if (FLAG_testing_d8_test_runner) {
518    PendingOptimizationTable::PreparedForOptimization(
519        isolate, function, allow_heuristic_optimization);
520  }
521
522  return ReadOnlyRoots(isolate).undefined_value();
523}
524
525namespace {
526
527void FinalizeOptimization(Isolate* isolate) {
528  DCHECK(isolate->concurrent_recompilation_enabled());
529  isolate->optimizing_compile_dispatcher()->AwaitCompileTasks();
530  isolate->optimizing_compile_dispatcher()->InstallOptimizedFunctions();
531  isolate->optimizing_compile_dispatcher()->set_finalize(true);
532}
533
534BytecodeOffset OffsetOfNextJumpLoop(Isolate* isolate, UnoptimizedFrame* frame) {
535  Handle<BytecodeArray> bytecode_array(frame->GetBytecodeArray(), isolate);
536  const int current_offset = frame->GetBytecodeOffset();
537
538  interpreter::BytecodeArrayIterator it(bytecode_array, current_offset);
539
540  // First, look for a loop that contains the current bytecode offset.
541  for (; !it.done(); it.Advance()) {
542    if (it.current_bytecode() != interpreter::Bytecode::kJumpLoop) {
543      continue;
544    }
545    if (!base::IsInRange(current_offset, it.GetJumpTargetOffset(),
546                         it.current_offset())) {
547      continue;
548    }
549
550    return BytecodeOffset(it.current_offset());
551  }
552
553  // Fall back to any loop after the current offset.
554  it.SetOffset(current_offset);
555  for (; !it.done(); it.Advance()) {
556    if (it.current_bytecode() == interpreter::Bytecode::kJumpLoop) {
557      return BytecodeOffset(it.current_offset());
558    }
559  }
560
561  return BytecodeOffset::None();
562}
563
564}  // namespace
565
566RUNTIME_FUNCTION(Runtime_OptimizeOsr) {
567  HandleScope handle_scope(isolate);
568  DCHECK(args.length() == 0 || args.length() == 1);
569
570  Handle<JSFunction> function;
571
572  // The optional parameter determines the frame being targeted.
573  int stack_depth = 0;
574  if (args.length() == 1) {
575    if (!args[0].IsSmi()) return CrashUnlessFuzzing(isolate);
576    stack_depth = args.smi_value_at(0);
577  }
578
579  // Find the JavaScript function on the top of the stack.
580  JavaScriptFrameIterator it(isolate);
581  while (!it.done() && stack_depth--) it.Advance();
582  if (!it.done()) function = handle(it.frame()->function(), isolate);
583  if (function.is_null()) return CrashUnlessFuzzing(isolate);
584
585  if (V8_UNLIKELY(!FLAG_opt) || V8_UNLIKELY(!FLAG_use_osr)) {
586    return ReadOnlyRoots(isolate).undefined_value();
587  }
588
589  if (!function->shared().allows_lazy_compilation()) {
590    return CrashUnlessFuzzing(isolate);
591  }
592
593  if (function->shared().optimization_disabled() &&
594      function->shared().disabled_optimization_reason() ==
595          BailoutReason::kNeverOptimize) {
596    return CrashUnlessFuzzing(isolate);
597  }
598
599  if (FLAG_testing_d8_test_runner) {
600    PendingOptimizationTable::MarkedForOptimization(isolate, function);
601  }
602
603  if (function->HasAvailableOptimizedCode()) {
604    DCHECK(function->HasAttachedOptimizedCode() ||
605           function->ChecksTieringState());
606    // If function is already optimized, remove the bytecode array from the
607    // pending optimize for test table and return.
608    if (FLAG_testing_d8_test_runner) {
609      PendingOptimizationTable::FunctionWasOptimized(isolate, function);
610    }
611    return ReadOnlyRoots(isolate).undefined_value();
612  }
613
614  if (!it.frame()->is_unoptimized()) {
615    // Nothing to be done.
616    return ReadOnlyRoots(isolate).undefined_value();
617  }
618
619  // Ensure that the function is marked for non-concurrent optimization, so that
620  // subsequent runs don't also optimize.
621  if (FLAG_trace_osr) {
622    CodeTracer::Scope scope(isolate->GetCodeTracer());
623    PrintF(scope.file(), "[OSR - OptimizeOsr marking ");
624    function->ShortPrint(scope.file());
625    PrintF(scope.file(), " for non-concurrent optimization]\n");
626  }
627  IsCompiledScope is_compiled_scope(
628      function->shared().is_compiled_scope(isolate));
629  JSFunction::EnsureFeedbackVector(isolate, function, &is_compiled_scope);
630  function->MarkForOptimization(isolate, CodeKind::TURBOFAN,
631                                ConcurrencyMode::kSynchronous);
632
633  isolate->tiering_manager()->RequestOsrAtNextOpportunity(*function);
634
635  // If concurrent OSR is enabled, the testing workflow is a bit tricky. We
636  // must guarantee that the next JumpLoop installs the finished OSR'd code
637  // object, but we still want to exercise concurrent code paths. To do so,
638  // we attempt to find the next JumpLoop, start an OSR job for it now, and
639  // immediately force finalization.
640  // If this succeeds and we correctly match up the next JumpLoop, once we
641  // reach the JumpLoop we'll hit the OSR cache and install the generated code.
642  // If not (e.g. because we enter a nested loop first), the next JumpLoop will
643  // see the cached OSR code with a mismatched offset, and trigger
644  // non-concurrent OSR compilation and installation.
645  if (isolate->concurrent_recompilation_enabled() && FLAG_concurrent_osr) {
646    const BytecodeOffset osr_offset =
647        OffsetOfNextJumpLoop(isolate, UnoptimizedFrame::cast(it.frame()));
648    if (osr_offset.IsNone()) {
649      // The loop may have been elided by bytecode generation (e.g. for
650      // patterns such as `do { ... } while (false);`.
651      return ReadOnlyRoots(isolate).undefined_value();
652    }
653
654    // Finalize first to ensure all pending tasks are done (since we can't
655    // queue more than one OSR job for each function).
656    FinalizeOptimization(isolate);
657
658    // Queue the job.
659    auto unused_result = Compiler::CompileOptimizedOSR(
660        isolate, function, osr_offset, UnoptimizedFrame::cast(it.frame()),
661        ConcurrencyMode::kConcurrent);
662    USE(unused_result);
663
664    // Finalize again to finish the queued job. The next call into
665    // Runtime::kCompileOptimizedOSR will pick up the cached Code object.
666    FinalizeOptimization(isolate);
667  }
668
669  return ReadOnlyRoots(isolate).undefined_value();
670}
671
672RUNTIME_FUNCTION(Runtime_BaselineOsr) {
673  HandleScope scope(isolate);
674  DCHECK_EQ(0, args.length());
675
676  // Find the JavaScript function on the top of the stack.
677  JavaScriptFrameIterator it(isolate);
678  Handle<JSFunction> function = handle(it.frame()->function(), isolate);
679  if (function.is_null()) return CrashUnlessFuzzing(isolate);
680  if (!FLAG_sparkplug || !FLAG_use_osr) {
681    return ReadOnlyRoots(isolate).undefined_value();
682  }
683  if (!it.frame()->is_unoptimized()) {
684    return ReadOnlyRoots(isolate).undefined_value();
685  }
686
687  IsCompiledScope is_compiled_scope(
688      function->shared().is_compiled_scope(isolate));
689  Compiler::CompileBaseline(isolate, function, Compiler::CLEAR_EXCEPTION,
690                            &is_compiled_scope);
691
692  return ReadOnlyRoots(isolate).undefined_value();
693}
694
695RUNTIME_FUNCTION(Runtime_NeverOptimizeFunction) {
696  HandleScope scope(isolate);
697  DCHECK_EQ(1, args.length());
698  Handle<Object> function_object = args.at(0);
699  if (!function_object->IsJSFunction()) return CrashUnlessFuzzing(isolate);
700  Handle<JSFunction> function = Handle<JSFunction>::cast(function_object);
701  Handle<SharedFunctionInfo> sfi(function->shared(), isolate);
702  if (sfi->abstract_code(isolate).kind() != CodeKind::INTERPRETED_FUNCTION &&
703      sfi->abstract_code(isolate).kind() != CodeKind::BUILTIN) {
704    return CrashUnlessFuzzing(isolate);
705  }
706  // Make sure to finish compilation if there is a parallel lazy compilation in
707  // progress, to make sure that the compilation finalization doesn't clobber
708  // the SharedFunctionInfo's disable_optimization field.
709  if (isolate->lazy_compile_dispatcher() &&
710      isolate->lazy_compile_dispatcher()->IsEnqueued(sfi)) {
711    isolate->lazy_compile_dispatcher()->FinishNow(sfi);
712  }
713
714  sfi->DisableOptimization(BailoutReason::kNeverOptimize);
715  return ReadOnlyRoots(isolate).undefined_value();
716}
717
718RUNTIME_FUNCTION(Runtime_GetOptimizationStatus) {
719  HandleScope scope(isolate);
720  DCHECK_EQ(args.length(), 1);
721
722  int status = 0;
723  if (FLAG_lite_mode || FLAG_jitless) {
724    // Both jitless and lite modes cannot optimize. Unit tests should handle
725    // these the same way. In the future, the two flags may become synonyms.
726    status |= static_cast<int>(OptimizationStatus::kLiteMode);
727  }
728  if (!isolate->use_optimizer()) {
729    status |= static_cast<int>(OptimizationStatus::kNeverOptimize);
730  }
731  if (FLAG_always_opt || FLAG_prepare_always_opt) {
732    status |= static_cast<int>(OptimizationStatus::kAlwaysOptimize);
733  }
734  if (FLAG_deopt_every_n_times) {
735    status |= static_cast<int>(OptimizationStatus::kMaybeDeopted);
736  }
737
738  Handle<Object> function_object = args.at(0);
739  if (function_object->IsUndefined()) return Smi::FromInt(status);
740  if (!function_object->IsJSFunction()) return CrashUnlessFuzzing(isolate);
741
742  Handle<JSFunction> function = Handle<JSFunction>::cast(function_object);
743  status |= static_cast<int>(OptimizationStatus::kIsFunction);
744
745  switch (function->tiering_state()) {
746    case TieringState::kRequestTurbofan_Synchronous:
747      status |= static_cast<int>(OptimizationStatus::kMarkedForOptimization);
748      break;
749    case TieringState::kRequestTurbofan_Concurrent:
750      status |= static_cast<int>(
751          OptimizationStatus::kMarkedForConcurrentOptimization);
752      break;
753    case TieringState::kInProgress:
754      status |= static_cast<int>(OptimizationStatus::kOptimizingConcurrently);
755      break;
756    case TieringState::kNone:
757    case TieringState::kRequestMaglev_Synchronous:
758    case TieringState::kRequestMaglev_Concurrent:
759      // TODO(v8:7700): Maglev support.
760      break;
761  }
762
763  if (function->HasAttachedOptimizedCode()) {
764    CodeT code = function->code();
765    if (code.marked_for_deoptimization()) {
766      status |= static_cast<int>(OptimizationStatus::kMarkedForDeoptimization);
767    } else {
768      status |= static_cast<int>(OptimizationStatus::kOptimized);
769    }
770    if (code.is_maglevved()) {
771      status |= static_cast<int>(OptimizationStatus::kMaglevved);
772    } else if (code.is_turbofanned()) {
773      status |= static_cast<int>(OptimizationStatus::kTurboFanned);
774    }
775  }
776  if (function->HasAttachedCodeKind(CodeKind::BASELINE)) {
777    status |= static_cast<int>(OptimizationStatus::kBaseline);
778  }
779  if (function->ActiveTierIsIgnition()) {
780    status |= static_cast<int>(OptimizationStatus::kInterpreted);
781  }
782
783  // Additionally, detect activations of this frame on the stack, and report the
784  // status of the topmost frame.
785  JavaScriptFrame* frame = nullptr;
786  JavaScriptFrameIterator it(isolate);
787  while (!it.done()) {
788    if (it.frame()->function() == *function) {
789      frame = it.frame();
790      break;
791    }
792    it.Advance();
793  }
794  if (frame != nullptr) {
795    status |= static_cast<int>(OptimizationStatus::kIsExecuting);
796    if (frame->is_optimized()) {
797      status |=
798          static_cast<int>(OptimizationStatus::kTopmostFrameIsTurboFanned);
799    } else if (frame->is_interpreted()) {
800      status |=
801          static_cast<int>(OptimizationStatus::kTopmostFrameIsInterpreted);
802    } else if (frame->is_baseline()) {
803      status |= static_cast<int>(OptimizationStatus::kTopmostFrameIsBaseline);
804    }
805  }
806
807  return Smi::FromInt(status);
808}
809
810RUNTIME_FUNCTION(Runtime_DisableOptimizationFinalization) {
811  DCHECK_EQ(0, args.length());
812  if (isolate->concurrent_recompilation_enabled()) {
813    isolate->optimizing_compile_dispatcher()->AwaitCompileTasks();
814    isolate->optimizing_compile_dispatcher()->InstallOptimizedFunctions();
815    isolate->stack_guard()->ClearInstallCode();
816    isolate->optimizing_compile_dispatcher()->set_finalize(false);
817  }
818  return ReadOnlyRoots(isolate).undefined_value();
819}
820
821RUNTIME_FUNCTION(Runtime_WaitForBackgroundOptimization) {
822  DCHECK_EQ(0, args.length());
823  if (isolate->concurrent_recompilation_enabled()) {
824    isolate->optimizing_compile_dispatcher()->AwaitCompileTasks();
825  }
826  return ReadOnlyRoots(isolate).undefined_value();
827}
828
829RUNTIME_FUNCTION(Runtime_FinalizeOptimization) {
830  DCHECK_EQ(0, args.length());
831  if (isolate->concurrent_recompilation_enabled()) {
832    FinalizeOptimization(isolate);
833  }
834  return ReadOnlyRoots(isolate).undefined_value();
835}
836
837static void ReturnNull(const v8::FunctionCallbackInfo<v8::Value>& args) {
838  args.GetReturnValue().SetNull();
839}
840
841RUNTIME_FUNCTION(Runtime_GetUndetectable) {
842  HandleScope scope(isolate);
843  DCHECK_EQ(0, args.length());
844  v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
845  Local<v8::ObjectTemplate> desc = v8::ObjectTemplate::New(v8_isolate);
846  desc->MarkAsUndetectable();
847  desc->SetCallAsFunctionHandler(ReturnNull);
848  Local<v8::Object> obj =
849      desc->NewInstance(v8_isolate->GetCurrentContext()).ToLocalChecked();
850  return *Utils::OpenHandle(*obj);
851}
852
853static void call_as_function(const v8::FunctionCallbackInfo<v8::Value>& args) {
854  double v1 =
855      args[0]->NumberValue(args.GetIsolate()->GetCurrentContext()).ToChecked();
856  double v2 =
857      args[1]->NumberValue(args.GetIsolate()->GetCurrentContext()).ToChecked();
858  args.GetReturnValue().Set(v8::Number::New(args.GetIsolate(), v1 - v2));
859}
860
861// Returns a callable object. The object returns the difference of its two
862// parameters when it is called.
863RUNTIME_FUNCTION(Runtime_GetCallable) {
864  HandleScope scope(isolate);
865  DCHECK_EQ(0, args.length());
866  v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
867  Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(v8_isolate);
868  Local<ObjectTemplate> instance_template = t->InstanceTemplate();
869  instance_template->SetCallAsFunctionHandler(call_as_function);
870  v8_isolate->GetCurrentContext();
871  Local<v8::Object> instance =
872      t->GetFunction(v8_isolate->GetCurrentContext())
873          .ToLocalChecked()
874          ->NewInstance(v8_isolate->GetCurrentContext())
875          .ToLocalChecked();
876  return *Utils::OpenHandle(*instance);
877}
878
879RUNTIME_FUNCTION(Runtime_ClearFunctionFeedback) {
880  HandleScope scope(isolate);
881  DCHECK_EQ(1, args.length());
882  Handle<JSFunction> function = args.at<JSFunction>(0);
883  function->ClearTypeFeedbackInfo();
884  return ReadOnlyRoots(isolate).undefined_value();
885}
886
887RUNTIME_FUNCTION(Runtime_NotifyContextDisposed) {
888  HandleScope scope(isolate);
889  DCHECK_EQ(0, args.length());
890  isolate->heap()->NotifyContextDisposed(true);
891  return ReadOnlyRoots(isolate).undefined_value();
892}
893
894RUNTIME_FUNCTION(Runtime_SetAllocationTimeout) {
895  SealHandleScope shs(isolate);
896  DCHECK(args.length() == 2 || args.length() == 3);
897#ifdef V8_ENABLE_ALLOCATION_TIMEOUT
898  CONVERT_INT32_ARG_FUZZ_SAFE(timeout, 1);
899  isolate->heap()->set_allocation_timeout(timeout);
900#endif
901#ifdef DEBUG
902  CONVERT_INT32_ARG_FUZZ_SAFE(interval, 0);
903  FLAG_gc_interval = interval;
904  if (args.length() == 3) {
905    // Enable/disable inline allocation if requested.
906    CONVERT_BOOLEAN_ARG_FUZZ_SAFE(inline_allocation, 2);
907    if (inline_allocation) {
908      isolate->heap()->EnableInlineAllocation();
909    } else {
910      isolate->heap()->DisableInlineAllocation();
911    }
912  }
913#endif
914  return ReadOnlyRoots(isolate).undefined_value();
915}
916
917namespace {
918
919int FixedArrayLenFromSize(int size) {
920  return std::min({(size - FixedArray::kHeaderSize) / kTaggedSize,
921                   FixedArray::kMaxRegularLength});
922}
923
924void FillUpOneNewSpacePage(Isolate* isolate, Heap* heap) {
925  DCHECK(!FLAG_single_generation);
926  PauseAllocationObserversScope pause_observers(heap);
927  NewSpace* space = heap->new_space();
928  // We cannot rely on `space->limit()` to point to the end of the current page
929  // in the case where inline allocations are disabled, it actually points to
930  // the current allocation pointer.
931  DCHECK_IMPLIES(!space->IsInlineAllocationEnabled(),
932                 space->limit() == space->top());
933  int space_remaining =
934      static_cast<int>(space->to_space().page_high() - space->top());
935  while (space_remaining > 0) {
936    int length = FixedArrayLenFromSize(space_remaining);
937    if (length > 0) {
938      Handle<FixedArray> padding =
939          isolate->factory()->NewFixedArray(length, AllocationType::kYoung);
940      DCHECK(heap->new_space()->Contains(*padding));
941      space_remaining -= padding->Size();
942    } else {
943      // Not enough room to create another fixed array. Create a filler.
944      heap->CreateFillerObjectAt(*heap->new_space()->allocation_top_address(),
945                                 space_remaining, ClearRecordedSlots::kNo);
946      break;
947    }
948  }
949}
950
951}  // namespace
952
953RUNTIME_FUNCTION(Runtime_SimulateNewspaceFull) {
954  HandleScope scope(isolate);
955  Heap* heap = isolate->heap();
956  NewSpace* space = heap->new_space();
957  AlwaysAllocateScopeForTesting always_allocate(heap);
958  do {
959    FillUpOneNewSpacePage(isolate, heap);
960  } while (space->AddFreshPage());
961
962  return ReadOnlyRoots(isolate).undefined_value();
963}
964
965RUNTIME_FUNCTION(Runtime_ScheduleGCInStackCheck) {
966  SealHandleScope shs(isolate);
967  DCHECK_EQ(0, args.length());
968  isolate->RequestInterrupt(
969      [](v8::Isolate* isolate, void*) {
970        isolate->RequestGarbageCollectionForTesting(
971            v8::Isolate::kFullGarbageCollection);
972      },
973      nullptr);
974  return ReadOnlyRoots(isolate).undefined_value();
975}
976
977class FileOutputStream : public v8::OutputStream {
978 public:
979  explicit FileOutputStream(const char* filename) : os_(filename) {}
980  ~FileOutputStream() override { os_.close(); }
981
982  WriteResult WriteAsciiChunk(char* data, int size) override {
983    os_.write(data, size);
984    return kContinue;
985  }
986
987  void EndOfStream() override { os_.close(); }
988
989 private:
990  std::ofstream os_;
991};
992
993RUNTIME_FUNCTION(Runtime_TakeHeapSnapshot) {
994  if (FLAG_fuzzing) {
995    // We don't want to create snapshots in fuzzers.
996    return ReadOnlyRoots(isolate).undefined_value();
997  }
998
999  std::string filename = "heap.heapsnapshot";
1000
1001  if (args.length() >= 1) {
1002    HandleScope hs(isolate);
1003    Handle<String> filename_as_js_string = args.at<String>(0);
1004    std::unique_ptr<char[]> buffer = filename_as_js_string->ToCString();
1005    filename = std::string(buffer.get());
1006  }
1007
1008  HeapProfiler* heap_profiler = isolate->heap_profiler();
1009  // Since this API is intended for V8 devs, we do not treat globals as roots
1010  // here on purpose.
1011  HeapSnapshot* snapshot = heap_profiler->TakeSnapshot(
1012      /* control = */ nullptr, /* resolver = */ nullptr,
1013      /* treat_global_objects_as_roots = */ false,
1014      /* capture_numeric_value = */ true);
1015  FileOutputStream stream(filename.c_str());
1016  HeapSnapshotJSONSerializer serializer(snapshot);
1017  serializer.Serialize(&stream);
1018  return ReadOnlyRoots(isolate).undefined_value();
1019}
1020
1021static void DebugPrintImpl(MaybeObject maybe_object) {
1022  StdoutStream os;
1023  if (maybe_object->IsCleared()) {
1024    os << "[weak cleared]";
1025  } else {
1026    Object object = maybe_object.GetHeapObjectOrSmi();
1027    bool weak = maybe_object.IsWeak();
1028
1029#ifdef OBJECT_PRINT
1030    os << "DebugPrint: ";
1031    if (weak) os << "[weak] ";
1032    object.Print(os);
1033    if (object.IsHeapObject()) {
1034      HeapObject::cast(object).map().Print(os);
1035    }
1036#else
1037    if (weak) os << "[weak] ";
1038    // ShortPrint is available in release mode. Print is not.
1039    os << Brief(object);
1040#endif
1041  }
1042  os << std::endl;
1043}
1044
1045RUNTIME_FUNCTION(Runtime_DebugPrint) {
1046  SealHandleScope shs(isolate);
1047  DCHECK_EQ(1, args.length());
1048
1049  MaybeObject maybe_object(*args.address_of_arg_at(0));
1050  DebugPrintImpl(maybe_object);
1051  return args[0];
1052}
1053
1054RUNTIME_FUNCTION(Runtime_DebugPrintPtr) {
1055  SealHandleScope shs(isolate);
1056  StdoutStream os;
1057  DCHECK_EQ(1, args.length());
1058
1059  MaybeObject maybe_object(*args.address_of_arg_at(0));
1060  if (!maybe_object.IsCleared()) {
1061    Object object = maybe_object.GetHeapObjectOrSmi();
1062    size_t pointer;
1063    if (object.ToIntegerIndex(&pointer)) {
1064      MaybeObject from_pointer(static_cast<Address>(pointer));
1065      DebugPrintImpl(from_pointer);
1066    }
1067  }
1068  // We don't allow the converted pointer to leak out to JavaScript.
1069  return args[0];
1070}
1071
1072RUNTIME_FUNCTION(Runtime_PrintWithNameForAssert) {
1073  SealHandleScope shs(isolate);
1074  DCHECK_EQ(2, args.length());
1075
1076  auto name = String::cast(args[0]);
1077
1078  PrintF(" * ");
1079  StringCharacterStream stream(name);
1080  while (stream.HasMore()) {
1081    uint16_t character = stream.GetNext();
1082    PrintF("%c", character);
1083  }
1084  PrintF(": ");
1085  args[1].ShortPrint();
1086  PrintF("\n");
1087
1088  return ReadOnlyRoots(isolate).undefined_value();
1089}
1090
1091RUNTIME_FUNCTION(Runtime_DebugTrace) {
1092  SealHandleScope shs(isolate);
1093  DCHECK_EQ(0, args.length());
1094  isolate->PrintStack(stdout);
1095  return ReadOnlyRoots(isolate).undefined_value();
1096}
1097
1098RUNTIME_FUNCTION(Runtime_DebugTrackRetainingPath) {
1099  HandleScope scope(isolate);
1100  DCHECK_LE(1, args.length());
1101  DCHECK_GE(2, args.length());
1102  CHECK(FLAG_track_retaining_path);
1103  Handle<HeapObject> object = args.at<HeapObject>(0);
1104  RetainingPathOption option = RetainingPathOption::kDefault;
1105  if (args.length() == 2) {
1106    Handle<String> str = args.at<String>(1);
1107    const char track_ephemeron_path[] = "track-ephemeron-path";
1108    if (str->IsOneByteEqualTo(base::StaticCharVector(track_ephemeron_path))) {
1109      option = RetainingPathOption::kTrackEphemeronPath;
1110    } else {
1111      CHECK_EQ(str->length(), 0);
1112    }
1113  }
1114  isolate->heap()->AddRetainingPathTarget(object, option);
1115  return ReadOnlyRoots(isolate).undefined_value();
1116}
1117
1118// This will not allocate (flatten the string), but it may run
1119// very slowly for very deeply nested ConsStrings.  For debugging use only.
1120RUNTIME_FUNCTION(Runtime_GlobalPrint) {
1121  SealHandleScope shs(isolate);
1122  DCHECK_EQ(1, args.length());
1123
1124  auto string = String::cast(args[0]);
1125  StringCharacterStream stream(string);
1126  while (stream.HasMore()) {
1127    uint16_t character = stream.GetNext();
1128    PrintF("%c", character);
1129  }
1130  return string;
1131}
1132
1133RUNTIME_FUNCTION(Runtime_SystemBreak) {
1134  // The code below doesn't create handles, but when breaking here in GDB
1135  // having a handle scope might be useful.
1136  HandleScope scope(isolate);
1137  DCHECK_EQ(0, args.length());
1138  base::OS::DebugBreak();
1139  return ReadOnlyRoots(isolate).undefined_value();
1140}
1141
1142RUNTIME_FUNCTION(Runtime_SetForceSlowPath) {
1143  SealHandleScope shs(isolate);
1144  DCHECK_EQ(1, args.length());
1145  Object arg = args[0];
1146  if (arg.IsTrue(isolate)) {
1147    isolate->set_force_slow_path(true);
1148  } else {
1149    DCHECK(arg.IsFalse(isolate));
1150    isolate->set_force_slow_path(false);
1151  }
1152  return ReadOnlyRoots(isolate).undefined_value();
1153}
1154
1155RUNTIME_FUNCTION(Runtime_Abort) {
1156  SealHandleScope shs(isolate);
1157  DCHECK_EQ(1, args.length());
1158  int message_id = args.smi_value_at(0);
1159  const char* message = GetAbortReason(static_cast<AbortReason>(message_id));
1160  base::OS::PrintError("abort: %s\n", message);
1161  isolate->PrintStack(stderr);
1162  base::OS::Abort();
1163  UNREACHABLE();
1164}
1165
1166RUNTIME_FUNCTION(Runtime_AbortJS) {
1167  HandleScope scope(isolate);
1168  DCHECK_EQ(1, args.length());
1169  Handle<String> message = args.at<String>(0);
1170  if (FLAG_disable_abortjs) {
1171    base::OS::PrintError("[disabled] abort: %s\n", message->ToCString().get());
1172    return Object();
1173  }
1174  base::OS::PrintError("abort: %s\n", message->ToCString().get());
1175  isolate->PrintStack(stderr);
1176  base::OS::Abort();
1177  UNREACHABLE();
1178}
1179
1180RUNTIME_FUNCTION(Runtime_AbortCSADcheck) {
1181  HandleScope scope(isolate);
1182  DCHECK_EQ(1, args.length());
1183  Handle<String> message = args.at<String>(0);
1184  base::OS::PrintError("abort: CSA_DCHECK failed: %s\n",
1185                       message->ToCString().get());
1186  isolate->PrintStack(stderr);
1187  base::OS::Abort();
1188  UNREACHABLE();
1189}
1190
1191RUNTIME_FUNCTION(Runtime_DisassembleFunction) {
1192  HandleScope scope(isolate);
1193#ifdef DEBUG
1194  DCHECK_EQ(1, args.length());
1195  // Get the function and make sure it is compiled.
1196  Handle<JSFunction> func = args.at<JSFunction>(0);
1197  IsCompiledScope is_compiled_scope;
1198  if (!func->is_compiled() && func->HasAvailableOptimizedCode()) {
1199    func->set_code(func->feedback_vector().optimized_code());
1200  }
1201  CHECK(func->is_compiled() ||
1202        Compiler::Compile(isolate, func, Compiler::KEEP_EXCEPTION,
1203                          &is_compiled_scope));
1204  StdoutStream os;
1205  func->code().Print(os);
1206  os << std::endl;
1207#endif  // DEBUG
1208  return ReadOnlyRoots(isolate).undefined_value();
1209}
1210
1211namespace {
1212
1213int StackSize(Isolate* isolate) {
1214  int n = 0;
1215  for (JavaScriptFrameIterator it(isolate); !it.done(); it.Advance()) n++;
1216  return n;
1217}
1218
1219void PrintIndentation(int stack_size) {
1220  const int max_display = 80;
1221  if (stack_size <= max_display) {
1222    PrintF("%4d:%*s", stack_size, stack_size, "");
1223  } else {
1224    PrintF("%4d:%*s", stack_size, max_display, "...");
1225  }
1226}
1227
1228}  // namespace
1229
1230RUNTIME_FUNCTION(Runtime_TraceEnter) {
1231  SealHandleScope shs(isolate);
1232  DCHECK_EQ(0, args.length());
1233  PrintIndentation(StackSize(isolate));
1234  JavaScriptFrame::PrintTop(isolate, stdout, true, false);
1235  PrintF(" {\n");
1236  return ReadOnlyRoots(isolate).undefined_value();
1237}
1238
1239RUNTIME_FUNCTION(Runtime_TraceExit) {
1240  SealHandleScope shs(isolate);
1241  DCHECK_EQ(1, args.length());
1242  Object obj = args[0];
1243  PrintIndentation(StackSize(isolate));
1244  PrintF("} -> ");
1245  obj.ShortPrint();
1246  PrintF("\n");
1247  return obj;  // return TOS
1248}
1249
1250RUNTIME_FUNCTION(Runtime_HaveSameMap) {
1251  SealHandleScope shs(isolate);
1252  DCHECK_EQ(2, args.length());
1253  auto obj1 = JSObject::cast(args[0]);
1254  auto obj2 = JSObject::cast(args[1]);
1255  return isolate->heap()->ToBoolean(obj1.map() == obj2.map());
1256}
1257
1258RUNTIME_FUNCTION(Runtime_InLargeObjectSpace) {
1259  SealHandleScope shs(isolate);
1260  DCHECK_EQ(1, args.length());
1261  auto obj = HeapObject::cast(args[0]);
1262  return isolate->heap()->ToBoolean(
1263      isolate->heap()->new_lo_space()->Contains(obj) ||
1264      isolate->heap()->code_lo_space()->Contains(obj) ||
1265      isolate->heap()->lo_space()->Contains(obj));
1266}
1267
1268RUNTIME_FUNCTION(Runtime_HasElementsInALargeObjectSpace) {
1269  SealHandleScope shs(isolate);
1270  DCHECK_EQ(1, args.length());
1271  auto array = JSArray::cast(args[0]);
1272  FixedArrayBase elements = array.elements();
1273  return isolate->heap()->ToBoolean(
1274      isolate->heap()->new_lo_space()->Contains(elements) ||
1275      isolate->heap()->lo_space()->Contains(elements));
1276}
1277
1278RUNTIME_FUNCTION(Runtime_InYoungGeneration) {
1279  SealHandleScope shs(isolate);
1280  DCHECK_EQ(1, args.length());
1281  Object obj = args[0];
1282  return isolate->heap()->ToBoolean(ObjectInYoungGeneration(obj));
1283}
1284
1285// Force pretenuring for the allocation site the passed object belongs to.
1286RUNTIME_FUNCTION(Runtime_PretenureAllocationSite) {
1287  DisallowGarbageCollection no_gc;
1288
1289  if (args.length() != 1) return CrashUnlessFuzzing(isolate);
1290  Object arg = args[0];
1291  if (!arg.IsJSObject()) return CrashUnlessFuzzing(isolate);
1292  JSObject object = JSObject::cast(arg);
1293
1294  Heap* heap = object.GetHeap();
1295  if (!heap->InYoungGeneration(object)) {
1296    // Object is not in new space, thus there is no memento and nothing to do.
1297    return ReturnFuzzSafe(ReadOnlyRoots(isolate).false_value(), isolate);
1298  }
1299
1300  AllocationMemento memento =
1301      heap->FindAllocationMemento<Heap::kForRuntime>(object.map(), object);
1302  if (memento.is_null())
1303    return ReturnFuzzSafe(ReadOnlyRoots(isolate).false_value(), isolate);
1304  AllocationSite site = memento.GetAllocationSite();
1305  heap->PretenureAllocationSiteOnNextCollection(site);
1306  return ReturnFuzzSafe(ReadOnlyRoots(isolate).true_value(), isolate);
1307}
1308
1309namespace {
1310
1311v8::ModifyCodeGenerationFromStringsResult DisallowCodegenFromStringsCallback(
1312    v8::Local<v8::Context> context, v8::Local<v8::Value> source,
1313    bool is_code_kind) {
1314  return {false, {}};
1315}
1316
1317}  // namespace
1318
1319RUNTIME_FUNCTION(Runtime_DisallowCodegenFromStrings) {
1320  SealHandleScope shs(isolate);
1321  DCHECK_EQ(1, args.length());
1322  bool flag = Oddball::cast(args[0]).ToBool(isolate);
1323  v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
1324  v8_isolate->SetModifyCodeGenerationFromStringsCallback(
1325      flag ? DisallowCodegenFromStringsCallback : nullptr);
1326  return ReadOnlyRoots(isolate).undefined_value();
1327}
1328
1329RUNTIME_FUNCTION(Runtime_RegexpHasBytecode) {
1330  SealHandleScope shs(isolate);
1331  DCHECK_EQ(2, args.length());
1332  auto regexp = JSRegExp::cast(args[0]);
1333  bool is_latin1 = Oddball::cast(args[1]).ToBool(isolate);
1334  bool result;
1335  if (regexp.type_tag() == JSRegExp::IRREGEXP) {
1336    result = regexp.bytecode(is_latin1).IsByteArray();
1337  } else {
1338    result = false;
1339  }
1340  return isolate->heap()->ToBoolean(result);
1341}
1342
1343RUNTIME_FUNCTION(Runtime_RegexpHasNativeCode) {
1344  SealHandleScope shs(isolate);
1345  DCHECK_EQ(2, args.length());
1346  auto regexp = JSRegExp::cast(args[0]);
1347  bool is_latin1 = Oddball::cast(args[1]).ToBool(isolate);
1348  bool result;
1349  if (regexp.type_tag() == JSRegExp::IRREGEXP) {
1350    result = regexp.code(is_latin1).IsCodeT();
1351  } else {
1352    result = false;
1353  }
1354  return isolate->heap()->ToBoolean(result);
1355}
1356
1357RUNTIME_FUNCTION(Runtime_RegexpTypeTag) {
1358  HandleScope shs(isolate);
1359  DCHECK_EQ(1, args.length());
1360  auto regexp = JSRegExp::cast(args[0]);
1361  const char* type_str;
1362  switch (regexp.type_tag()) {
1363    case JSRegExp::NOT_COMPILED:
1364      type_str = "NOT_COMPILED";
1365      break;
1366    case JSRegExp::ATOM:
1367      type_str = "ATOM";
1368      break;
1369    case JSRegExp::IRREGEXP:
1370      type_str = "IRREGEXP";
1371      break;
1372    case JSRegExp::EXPERIMENTAL:
1373      type_str = "EXPERIMENTAL";
1374      break;
1375  }
1376  return *isolate->factory()->NewStringFromAsciiChecked(type_str);
1377}
1378
1379RUNTIME_FUNCTION(Runtime_RegexpIsUnmodified) {
1380  HandleScope shs(isolate);
1381  DCHECK_EQ(1, args.length());
1382  Handle<JSRegExp> regexp = args.at<JSRegExp>(0);
1383  return isolate->heap()->ToBoolean(
1384      RegExp::IsUnmodifiedRegExp(isolate, regexp));
1385}
1386
1387#define ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(Name) \
1388  RUNTIME_FUNCTION(Runtime_##Name) {               \
1389    auto obj = JSObject::cast(args[0]);            \
1390    return isolate->heap()->ToBoolean(obj.Name()); \
1391  }
1392
1393ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(HasFastElements)
1394ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(HasSmiElements)
1395ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(HasObjectElements)
1396ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(HasSmiOrObjectElements)
1397ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(HasDoubleElements)
1398ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(HasHoleyElements)
1399ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(HasDictionaryElements)
1400ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(HasPackedElements)
1401ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(HasSloppyArgumentsElements)
1402// Properties test sitting with elements tests - not fooling anyone.
1403ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(HasFastProperties)
1404
1405#undef ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION
1406
1407#define FIXED_TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION(Type, type, TYPE, ctype) \
1408  RUNTIME_FUNCTION(Runtime_HasFixed##Type##Elements) {                     \
1409    auto obj = JSObject::cast(args[0]);                                    \
1410    return isolate->heap()->ToBoolean(obj.HasFixed##Type##Elements());     \
1411  }
1412
1413TYPED_ARRAYS(FIXED_TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION)
1414
1415#undef FIXED_TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION
1416
1417RUNTIME_FUNCTION(Runtime_IsConcatSpreadableProtector) {
1418  SealHandleScope shs(isolate);
1419  DCHECK_EQ(0, args.length());
1420  return isolate->heap()->ToBoolean(
1421      Protectors::IsIsConcatSpreadableLookupChainIntact(isolate));
1422}
1423
1424RUNTIME_FUNCTION(Runtime_TypedArraySpeciesProtector) {
1425  SealHandleScope shs(isolate);
1426  DCHECK_EQ(0, args.length());
1427  return isolate->heap()->ToBoolean(
1428      Protectors::IsTypedArraySpeciesLookupChainIntact(isolate));
1429}
1430
1431RUNTIME_FUNCTION(Runtime_RegExpSpeciesProtector) {
1432  SealHandleScope shs(isolate);
1433  DCHECK_EQ(0, args.length());
1434  return isolate->heap()->ToBoolean(
1435      Protectors::IsRegExpSpeciesLookupChainIntact(isolate));
1436}
1437
1438RUNTIME_FUNCTION(Runtime_PromiseSpeciesProtector) {
1439  SealHandleScope shs(isolate);
1440  DCHECK_EQ(0, args.length());
1441  return isolate->heap()->ToBoolean(
1442      Protectors::IsPromiseSpeciesLookupChainIntact(isolate));
1443}
1444
1445RUNTIME_FUNCTION(Runtime_ArraySpeciesProtector) {
1446  SealHandleScope shs(isolate);
1447  DCHECK_EQ(0, args.length());
1448  return isolate->heap()->ToBoolean(
1449      Protectors::IsArraySpeciesLookupChainIntact(isolate));
1450}
1451
1452RUNTIME_FUNCTION(Runtime_MapIteratorProtector) {
1453  SealHandleScope shs(isolate);
1454  DCHECK_EQ(0, args.length());
1455  return isolate->heap()->ToBoolean(
1456      Protectors::IsMapIteratorLookupChainIntact(isolate));
1457}
1458
1459RUNTIME_FUNCTION(Runtime_SetIteratorProtector) {
1460  SealHandleScope shs(isolate);
1461  DCHECK_EQ(0, args.length());
1462  return isolate->heap()->ToBoolean(
1463      Protectors::IsSetIteratorLookupChainIntact(isolate));
1464}
1465
1466RUNTIME_FUNCTION(Runtime_StringIteratorProtector) {
1467  SealHandleScope shs(isolate);
1468  DCHECK_EQ(0, args.length());
1469  return isolate->heap()->ToBoolean(
1470      Protectors::IsStringIteratorLookupChainIntact(isolate));
1471}
1472
1473RUNTIME_FUNCTION(Runtime_ArrayIteratorProtector) {
1474  SealHandleScope shs(isolate);
1475  DCHECK_EQ(0, args.length());
1476  return isolate->heap()->ToBoolean(
1477      Protectors::IsArrayIteratorLookupChainIntact(isolate));
1478}
1479// For use by tests and fuzzers. It
1480//
1481// 1. serializes a snapshot of the current isolate,
1482// 2. deserializes the snapshot,
1483// 3. and runs VerifyHeap on the resulting isolate.
1484//
1485// The current isolate should not be modified by this call and can keep running
1486// once it completes.
1487RUNTIME_FUNCTION(Runtime_SerializeDeserializeNow) {
1488  HandleScope scope(isolate);
1489  DCHECK_EQ(0, args.length());
1490  Snapshot::SerializeDeserializeAndVerifyForTesting(isolate,
1491                                                    isolate->native_context());
1492  return ReadOnlyRoots(isolate).undefined_value();
1493}
1494
1495RUNTIME_FUNCTION(Runtime_HeapObjectVerify) {
1496  HandleScope shs(isolate);
1497  DCHECK_EQ(1, args.length());
1498  Handle<Object> object = args.at(0);
1499#ifdef VERIFY_HEAP
1500  object->ObjectVerify(isolate);
1501#else
1502  CHECK(object->IsObject());
1503  if (object->IsHeapObject()) {
1504    CHECK(HeapObject::cast(*object).map().IsMap());
1505  } else {
1506    CHECK(object->IsSmi());
1507  }
1508#endif
1509  return isolate->heap()->ToBoolean(true);
1510}
1511
1512RUNTIME_FUNCTION(Runtime_ArrayBufferMaxByteLength) {
1513  HandleScope shs(isolate);
1514  DCHECK_EQ(0, args.length());
1515  return *isolate->factory()->NewNumber(JSArrayBuffer::kMaxByteLength);
1516}
1517
1518RUNTIME_FUNCTION(Runtime_TypedArrayMaxLength) {
1519  HandleScope shs(isolate);
1520  DCHECK_EQ(0, args.length());
1521  return *isolate->factory()->NewNumber(JSTypedArray::kMaxLength);
1522}
1523
1524RUNTIME_FUNCTION(Runtime_CompleteInobjectSlackTracking) {
1525  HandleScope scope(isolate);
1526  DCHECK_EQ(1, args.length());
1527
1528  Handle<JSObject> object = args.at<JSObject>(0);
1529  MapUpdater::CompleteInobjectSlackTracking(isolate, object->map());
1530
1531  return ReadOnlyRoots(isolate).undefined_value();
1532}
1533
1534RUNTIME_FUNCTION(Runtime_TurbofanStaticAssert) {
1535  SealHandleScope shs(isolate);
1536  // Always lowered to StaticAssert node in Turbofan, so we never get here in
1537  // compiled code.
1538  return ReadOnlyRoots(isolate).undefined_value();
1539}
1540
1541RUNTIME_FUNCTION(Runtime_IsBeingInterpreted) {
1542  SealHandleScope shs(isolate);
1543  // Always lowered to false in Turbofan, so we never get here in compiled code.
1544  return ReadOnlyRoots(isolate).true_value();
1545}
1546
1547RUNTIME_FUNCTION(Runtime_EnableCodeLoggingForTesting) {
1548  // The {NoopListener} currently does nothing on any callback, but reports
1549  // {true} on {is_listening_to_code_events()}. Feel free to add assertions to
1550  // any method to further test the code logging callbacks.
1551  class NoopListener final : public CodeEventListener {
1552    void CodeCreateEvent(LogEventsAndTags tag, Handle<AbstractCode> code,
1553                         const char* name) final {}
1554    void CodeCreateEvent(LogEventsAndTags tag, Handle<AbstractCode> code,
1555                         Handle<Name> name) final {}
1556    void CodeCreateEvent(LogEventsAndTags tag, Handle<AbstractCode> code,
1557                         Handle<SharedFunctionInfo> shared,
1558                         Handle<Name> script_name) final {}
1559    void CodeCreateEvent(LogEventsAndTags tag, Handle<AbstractCode> code,
1560                         Handle<SharedFunctionInfo> shared,
1561                         Handle<Name> script_name, int line, int column) final {
1562    }
1563#if V8_ENABLE_WEBASSEMBLY
1564    void CodeCreateEvent(LogEventsAndTags tag, const wasm::WasmCode* code,
1565                         wasm::WasmName name, const char* source_url,
1566                         int code_offset, int script_id) final {}
1567#endif  // V8_ENABLE_WEBASSEMBLY
1568
1569    void CallbackEvent(Handle<Name> name, Address entry_point) final {}
1570    void GetterCallbackEvent(Handle<Name> name, Address entry_point) final {}
1571    void SetterCallbackEvent(Handle<Name> name, Address entry_point) final {}
1572    void RegExpCodeCreateEvent(Handle<AbstractCode> code,
1573                               Handle<String> source) final {}
1574    void CodeMoveEvent(AbstractCode from, AbstractCode to) final {}
1575    void SharedFunctionInfoMoveEvent(Address from, Address to) final {}
1576    void NativeContextMoveEvent(Address from, Address to) final {}
1577    void CodeMovingGCEvent() final {}
1578    void CodeDisableOptEvent(Handle<AbstractCode> code,
1579                             Handle<SharedFunctionInfo> shared) final {}
1580    void CodeDeoptEvent(Handle<Code> code, DeoptimizeKind kind, Address pc,
1581                        int fp_to_sp_delta) final {}
1582    void CodeDependencyChangeEvent(Handle<Code> code,
1583                                   Handle<SharedFunctionInfo> shared,
1584                                   const char* reason) final {}
1585    void WeakCodeClearEvent() final {}
1586
1587    bool is_listening_to_code_events() final { return true; }
1588  };
1589  static base::LeakyObject<NoopListener> noop_listener;
1590#if V8_ENABLE_WEBASSEMBLY
1591  wasm::GetWasmEngine()->EnableCodeLogging(isolate);
1592#endif  // V8_ENABLE_WEBASSEMBLY
1593  isolate->code_event_dispatcher()->AddListener(noop_listener.get());
1594  return ReadOnlyRoots(isolate).undefined_value();
1595}
1596
1597RUNTIME_FUNCTION(Runtime_NewRegExpWithBacktrackLimit) {
1598  HandleScope scope(isolate);
1599  DCHECK_EQ(3, args.length());
1600
1601  Handle<String> pattern = args.at<String>(0);
1602  Handle<String> flags_string = args.at<String>(1);
1603  uint32_t backtrack_limit = args.positive_smi_value_at(2);
1604
1605  JSRegExp::Flags flags =
1606      JSRegExp::FlagsFromString(isolate, flags_string).value();
1607
1608  RETURN_RESULT_OR_FAILURE(
1609      isolate, JSRegExp::New(isolate, pattern, flags, backtrack_limit));
1610}
1611
1612RUNTIME_FUNCTION(Runtime_Is64Bit) {
1613  SealHandleScope shs(isolate);
1614  DCHECK_EQ(0, args.length());
1615  return isolate->heap()->ToBoolean(kSystemPointerSize == 8);
1616}
1617
1618RUNTIME_FUNCTION(Runtime_BigIntMaxLengthBits) {
1619  HandleScope scope(isolate);
1620  DCHECK_EQ(0, args.length());
1621  return *isolate->factory()->NewNumber(BigInt::kMaxLengthBits);
1622}
1623
1624RUNTIME_FUNCTION(Runtime_IsSameHeapObject) {
1625  HandleScope scope(isolate);
1626  DCHECK_EQ(2, args.length());
1627  Handle<HeapObject> obj1 = args.at<HeapObject>(0);
1628  Handle<HeapObject> obj2 = args.at<HeapObject>(1);
1629  return isolate->heap()->ToBoolean(obj1->address() == obj2->address());
1630}
1631
1632RUNTIME_FUNCTION(Runtime_IsSharedString) {
1633  HandleScope scope(isolate);
1634  DCHECK_EQ(1, args.length());
1635  Handle<HeapObject> obj = args.at<HeapObject>(0);
1636  return isolate->heap()->ToBoolean(obj->IsString() &&
1637                                    Handle<String>::cast(obj)->IsShared());
1638}
1639
1640RUNTIME_FUNCTION(Runtime_WebSnapshotSerialize) {
1641  if (!FLAG_allow_natives_syntax) {
1642    return ReadOnlyRoots(isolate).undefined_value();
1643  }
1644  HandleScope scope(isolate);
1645  if (args.length() < 1 || args.length() > 2) {
1646    THROW_NEW_ERROR_RETURN_FAILURE(
1647        isolate, NewTypeError(MessageTemplate::kRuntimeWrongNumArgs));
1648  }
1649  Handle<Object> object = args.at(0);
1650  Handle<FixedArray> block_list = isolate->factory()->empty_fixed_array();
1651  Handle<JSArray> block_list_js_array;
1652  if (args.length() == 2) {
1653    if (!args[1].IsJSArray()) {
1654      THROW_NEW_ERROR_RETURN_FAILURE(
1655          isolate, NewTypeError(MessageTemplate::kInvalidArgument));
1656    }
1657    block_list_js_array = args.at<JSArray>(1);
1658    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1659        isolate, block_list,
1660        JSReceiver::GetOwnValues(block_list_js_array,
1661                                 PropertyFilter::ENUMERABLE_STRINGS));
1662  }
1663
1664  auto snapshot_data = std::make_shared<WebSnapshotData>();
1665  WebSnapshotSerializer serializer(isolate);
1666  if (!serializer.TakeSnapshot(object, block_list, *snapshot_data)) {
1667    DCHECK(isolate->has_pending_exception());
1668    return ReadOnlyRoots(isolate).exception();
1669  }
1670  if (!block_list_js_array.is_null() &&
1671      static_cast<uint32_t>(block_list->length()) <
1672          serializer.external_objects_count()) {
1673    Handle<FixedArray> externals = serializer.GetExternals();
1674    Handle<Map> map = JSObject::GetElementsTransitionMap(block_list_js_array,
1675                                                         PACKED_ELEMENTS);
1676    block_list_js_array->set_elements(*externals);
1677    block_list_js_array->set_length(Smi::FromInt(externals->length()));
1678    block_list_js_array->set_map(*map);
1679  }
1680  i::Handle<i::Object> managed_object = Managed<WebSnapshotData>::FromSharedPtr(
1681      isolate, snapshot_data->buffer_size, snapshot_data);
1682  return *managed_object;
1683}
1684
1685RUNTIME_FUNCTION(Runtime_WebSnapshotDeserialize) {
1686  if (!FLAG_allow_natives_syntax) {
1687    return ReadOnlyRoots(isolate).undefined_value();
1688  }
1689  HandleScope scope(isolate);
1690  if (args.length() == 0 || args.length() > 2) {
1691    THROW_NEW_ERROR_RETURN_FAILURE(
1692        isolate, NewTypeError(MessageTemplate::kRuntimeWrongNumArgs));
1693  }
1694  if (!args[0].IsForeign()) {
1695    THROW_NEW_ERROR_RETURN_FAILURE(
1696        isolate, NewTypeError(MessageTemplate::kInvalidArgument));
1697  }
1698  Handle<Foreign> foreign_data = args.at<Foreign>(0);
1699  Handle<FixedArray> injected_references =
1700      isolate->factory()->empty_fixed_array();
1701  if (args.length() == 2) {
1702    if (!args[1].IsJSArray()) {
1703      THROW_NEW_ERROR_RETURN_FAILURE(
1704          isolate, NewTypeError(MessageTemplate::kInvalidArgument));
1705    }
1706    auto js_array = args.at<JSArray>(1);
1707    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1708        isolate, injected_references,
1709        JSReceiver::GetOwnValues(js_array, PropertyFilter::ENUMERABLE_STRINGS));
1710  }
1711
1712  auto data = Managed<WebSnapshotData>::cast(*foreign_data).get();
1713  v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
1714  WebSnapshotDeserializer deserializer(v8_isolate, data->buffer,
1715                                       data->buffer_size);
1716  if (!deserializer.Deserialize(injected_references)) {
1717    DCHECK(isolate->has_pending_exception());
1718    return ReadOnlyRoots(isolate).exception();
1719  }
1720  Handle<Object> object;
1721  if (!deserializer.value().ToHandle(&object)) {
1722    THROW_NEW_ERROR_RETURN_FAILURE(
1723        isolate, NewTypeError(MessageTemplate::kWebSnapshotError));
1724  }
1725  return *object;
1726}
1727
1728RUNTIME_FUNCTION(Runtime_SharedGC) {
1729  SealHandleScope scope(isolate);
1730  isolate->heap()->CollectSharedGarbage(GarbageCollectionReason::kTesting);
1731  return ReadOnlyRoots(isolate).undefined_value();
1732}
1733
1734RUNTIME_FUNCTION(Runtime_GetWeakCollectionSize) {
1735  HandleScope scope(isolate);
1736  DCHECK_EQ(1, args.length());
1737  Handle<JSWeakCollection> collection = args.at<JSWeakCollection>(0);
1738
1739  return Smi::FromInt(
1740      EphemeronHashTable::cast(collection->table()).NumberOfElements());
1741}
1742
1743}  // namespace internal
1744}  // namespace v8
1745