• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <memory>
6 #include <sstream>
7 
8 #include "src/api/api-inl.h"
9 #include "src/base/platform/mutex.h"
10 #include "src/codegen/assembler-inl.h"
11 #include "src/codegen/compiler.h"
12 #include "src/codegen/pending-optimization-table.h"
13 #include "src/compiler-dispatcher/optimizing-compile-dispatcher.h"
14 #include "src/debug/debug-evaluate.h"
15 #include "src/deoptimizer/deoptimizer.h"
16 #include "src/execution/arguments-inl.h"
17 #include "src/execution/frames-inl.h"
18 #include "src/execution/isolate-inl.h"
19 #include "src/execution/protectors-inl.h"
20 #include "src/execution/runtime-profiler.h"
21 #include "src/heap/heap-inl.h"  // For ToBoolean. TODO(jkummerow): Drop.
22 #include "src/heap/heap-write-barrier-inl.h"
23 #include "src/ic/stub-cache.h"
24 #include "src/logging/counters.h"
25 #include "src/objects/heap-object-inl.h"
26 #include "src/objects/js-array-inl.h"
27 #include "src/objects/js-function-inl.h"
28 #include "src/objects/js-regexp-inl.h"
29 #include "src/objects/smi.h"
30 #include "src/regexp/regexp.h"
31 #include "src/runtime/runtime-utils.h"
32 #include "src/snapshot/snapshot.h"
33 #include "src/trap-handler/trap-handler.h"
34 #include "src/utils/ostreams.h"
35 #include "src/wasm/memory-tracing.h"
36 #include "src/wasm/module-compiler.h"
37 #include "src/wasm/wasm-code-manager.h"
38 #include "src/wasm/wasm-engine.h"
39 #include "src/wasm/wasm-module.h"
40 #include "src/wasm/wasm-objects-inl.h"
41 #include "src/wasm/wasm-serialization.h"
42 
43 namespace v8 {
44 namespace internal {
45 
46 namespace {
47 struct WasmCompileControls {
48   uint32_t MaxWasmBufferSize = std::numeric_limits<uint32_t>::max();
49   bool AllowAnySizeForAsync = true;
50 };
51 using WasmCompileControlsMap = std::map<v8::Isolate*, WasmCompileControls>;
52 
53 // We need per-isolate controls, because we sometimes run tests in multiple
54 // isolates concurrently. Methods need to hold the accompanying mutex on access.
55 // To avoid upsetting the static initializer count, we lazy initialize this.
56 DEFINE_LAZY_LEAKY_OBJECT_GETTER(WasmCompileControlsMap,
57                                 GetPerIsolateWasmControls)
58 base::LazyMutex g_PerIsolateWasmControlsMutex = LAZY_MUTEX_INITIALIZER;
59 
IsWasmCompileAllowed(v8::Isolate * isolate,v8::Local<v8::Value> value,bool is_async)60 bool IsWasmCompileAllowed(v8::Isolate* isolate, v8::Local<v8::Value> value,
61                           bool is_async) {
62   base::MutexGuard guard(g_PerIsolateWasmControlsMutex.Pointer());
63   DCHECK_GT(GetPerIsolateWasmControls()->count(isolate), 0);
64   const WasmCompileControls& ctrls = GetPerIsolateWasmControls()->at(isolate);
65   return (is_async && ctrls.AllowAnySizeForAsync) ||
66          (value->IsArrayBuffer() &&
67           v8::Local<v8::ArrayBuffer>::Cast(value)->ByteLength() <=
68               ctrls.MaxWasmBufferSize) ||
69          (value->IsArrayBufferView() &&
70           v8::Local<v8::ArrayBufferView>::Cast(value)->ByteLength() <=
71               ctrls.MaxWasmBufferSize);
72 }
73 
74 // Use the compile controls for instantiation, too
IsWasmInstantiateAllowed(v8::Isolate * isolate,v8::Local<v8::Value> module_or_bytes,bool is_async)75 bool IsWasmInstantiateAllowed(v8::Isolate* isolate,
76                               v8::Local<v8::Value> module_or_bytes,
77                               bool is_async) {
78   base::MutexGuard guard(g_PerIsolateWasmControlsMutex.Pointer());
79   DCHECK_GT(GetPerIsolateWasmControls()->count(isolate), 0);
80   const WasmCompileControls& ctrls = GetPerIsolateWasmControls()->at(isolate);
81   if (is_async && ctrls.AllowAnySizeForAsync) return true;
82   if (!module_or_bytes->IsWasmModuleObject()) {
83     return IsWasmCompileAllowed(isolate, module_or_bytes, is_async);
84   }
85   v8::Local<v8::WasmModuleObject> module =
86       v8::Local<v8::WasmModuleObject>::Cast(module_or_bytes);
87   return static_cast<uint32_t>(
88              module->GetCompiledModule().GetWireBytesRef().size()) <=
89          ctrls.MaxWasmBufferSize;
90 }
91 
NewRangeException(v8::Isolate * isolate,const char * message)92 v8::Local<v8::Value> NewRangeException(v8::Isolate* isolate,
93                                        const char* message) {
94   return v8::Exception::RangeError(
95       v8::String::NewFromOneByte(isolate,
96                                  reinterpret_cast<const uint8_t*>(message))
97           .ToLocalChecked());
98 }
99 
ThrowRangeException(v8::Isolate * isolate,const char * message)100 void ThrowRangeException(v8::Isolate* isolate, const char* message) {
101   isolate->ThrowException(NewRangeException(isolate, message));
102 }
103 
WasmModuleOverride(const v8::FunctionCallbackInfo<v8::Value> & args)104 bool WasmModuleOverride(const v8::FunctionCallbackInfo<v8::Value>& args) {
105   if (IsWasmCompileAllowed(args.GetIsolate(), args[0], false)) return false;
106   ThrowRangeException(args.GetIsolate(), "Sync compile not allowed");
107   return true;
108 }
109 
WasmInstanceOverride(const v8::FunctionCallbackInfo<v8::Value> & args)110 bool WasmInstanceOverride(const v8::FunctionCallbackInfo<v8::Value>& args) {
111   if (IsWasmInstantiateAllowed(args.GetIsolate(), args[0], false)) return false;
112   ThrowRangeException(args.GetIsolate(), "Sync instantiate not allowed");
113   return true;
114 }
115 
CrashUnlessFuzzing(Isolate * isolate)116 V8_WARN_UNUSED_RESULT Object CrashUnlessFuzzing(Isolate* isolate) {
117   CHECK(FLAG_fuzzing);
118   return ReadOnlyRoots(isolate).undefined_value();
119 }
120 
121 // Assert that the given argument is a number within the Int32 range
122 // and convert it to int32_t.  If the argument is not an Int32 we crash if not
123 // in fuzzing mode.
124 #define CONVERT_INT32_ARG_FUZZ_SAFE(name, index)                   \
125   if (!args[index].IsNumber()) return CrashUnlessFuzzing(isolate); \
126   int32_t name = 0;                                                \
127   if (!args[index].ToInt32(&name)) return CrashUnlessFuzzing(isolate);
128 
129 // Cast the given object to a boolean and store it in a variable with
130 // the given name.  If the object is not a boolean we crash if not in
131 // fuzzing mode.
132 #define CONVERT_BOOLEAN_ARG_FUZZ_SAFE(name, index)                  \
133   if (!args[index].IsBoolean()) return CrashUnlessFuzzing(isolate); \
134   bool name = args[index].IsTrue(isolate);
135 
136 }  // namespace
137 
RUNTIME_FUNCTION(Runtime_ClearMegamorphicStubCache)138 RUNTIME_FUNCTION(Runtime_ClearMegamorphicStubCache) {
139   HandleScope scope(isolate);
140   DCHECK_EQ(0, args.length());
141   isolate->load_stub_cache()->Clear();
142   isolate->store_stub_cache()->Clear();
143   return ReadOnlyRoots(isolate).undefined_value();
144 }
145 
RUNTIME_FUNCTION(Runtime_ConstructDouble)146 RUNTIME_FUNCTION(Runtime_ConstructDouble) {
147   HandleScope scope(isolate);
148   DCHECK_EQ(2, args.length());
149   CONVERT_NUMBER_CHECKED(uint32_t, hi, Uint32, args[0]);
150   CONVERT_NUMBER_CHECKED(uint32_t, lo, Uint32, args[1]);
151   uint64_t result = (static_cast<uint64_t>(hi) << 32) | lo;
152   return *isolate->factory()->NewNumber(uint64_to_double(result));
153 }
154 
RUNTIME_FUNCTION(Runtime_ConstructConsString)155 RUNTIME_FUNCTION(Runtime_ConstructConsString) {
156   HandleScope scope(isolate);
157   DCHECK_EQ(2, args.length());
158   CONVERT_ARG_HANDLE_CHECKED(String, left, 0);
159   CONVERT_ARG_HANDLE_CHECKED(String, right, 1);
160 
161   CHECK(left->IsOneByteRepresentation());
162   CHECK(right->IsOneByteRepresentation());
163 
164   const bool kIsOneByte = true;
165   const int length = left->length() + right->length();
166   return *isolate->factory()->NewConsString(left, right, length, kIsOneByte);
167 }
168 
RUNTIME_FUNCTION(Runtime_ConstructSlicedString)169 RUNTIME_FUNCTION(Runtime_ConstructSlicedString) {
170   HandleScope scope(isolate);
171   DCHECK_EQ(2, args.length());
172   CONVERT_ARG_HANDLE_CHECKED(String, string, 0);
173   CONVERT_ARG_HANDLE_CHECKED(Smi, index, 1);
174 
175   CHECK(string->IsOneByteRepresentation());
176   CHECK_LT(index->value(), string->length());
177 
178   Handle<String> sliced_string = isolate->factory()->NewSubString(
179       string, index->value(), string->length());
180   CHECK(sliced_string->IsSlicedString());
181   return *sliced_string;
182 }
183 
RUNTIME_FUNCTION(Runtime_DeoptimizeFunction)184 RUNTIME_FUNCTION(Runtime_DeoptimizeFunction) {
185   HandleScope scope(isolate);
186   DCHECK_EQ(1, args.length());
187 
188   CONVERT_ARG_HANDLE_CHECKED(Object, function_object, 0);
189   if (!function_object->IsJSFunction()) return CrashUnlessFuzzing(isolate);
190   Handle<JSFunction> function = Handle<JSFunction>::cast(function_object);
191 
192   if (function->HasAttachedOptimizedCode()) {
193     Deoptimizer::DeoptimizeFunction(*function);
194   }
195 
196   return ReadOnlyRoots(isolate).undefined_value();
197 }
198 
RUNTIME_FUNCTION(Runtime_DeoptimizeNow)199 RUNTIME_FUNCTION(Runtime_DeoptimizeNow) {
200   HandleScope scope(isolate);
201   DCHECK_EQ(0, args.length());
202 
203   Handle<JSFunction> function;
204 
205   // Find the JavaScript function on the top of the stack.
206   JavaScriptFrameIterator it(isolate);
207   if (!it.done()) function = handle(it.frame()->function(), isolate);
208   if (function.is_null()) return CrashUnlessFuzzing(isolate);
209 
210   if (function->HasAttachedOptimizedCode()) {
211     Deoptimizer::DeoptimizeFunction(*function);
212   }
213 
214   return ReadOnlyRoots(isolate).undefined_value();
215 }
216 
RUNTIME_FUNCTION(Runtime_RunningInSimulator)217 RUNTIME_FUNCTION(Runtime_RunningInSimulator) {
218   SealHandleScope shs(isolate);
219   DCHECK_EQ(0, args.length());
220 #if defined(USE_SIMULATOR)
221   return ReadOnlyRoots(isolate).true_value();
222 #else
223   return ReadOnlyRoots(isolate).false_value();
224 #endif
225 }
226 
RUNTIME_FUNCTION(Runtime_RuntimeEvaluateREPL)227 RUNTIME_FUNCTION(Runtime_RuntimeEvaluateREPL) {
228   HandleScope scope(isolate);
229   DCHECK_EQ(1, args.length());
230   CONVERT_ARG_HANDLE_CHECKED(String, source, 0);
231   Handle<Object> result;
232   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
233       isolate, result,
234       DebugEvaluate::Global(isolate, source,
235                             debug::EvaluateGlobalMode::kDefault,
236                             REPLMode::kYes));
237 
238   return *result;
239 }
240 
RUNTIME_FUNCTION(Runtime_ICsAreEnabled)241 RUNTIME_FUNCTION(Runtime_ICsAreEnabled) {
242   SealHandleScope shs(isolate);
243   DCHECK_EQ(0, args.length());
244   return isolate->heap()->ToBoolean(FLAG_use_ic);
245 }
246 
RUNTIME_FUNCTION(Runtime_IsConcurrentRecompilationSupported)247 RUNTIME_FUNCTION(Runtime_IsConcurrentRecompilationSupported) {
248   SealHandleScope shs(isolate);
249   DCHECK_EQ(0, args.length());
250   return isolate->heap()->ToBoolean(
251       isolate->concurrent_recompilation_enabled());
252 }
253 
RUNTIME_FUNCTION(Runtime_DynamicMapChecksEnabled)254 RUNTIME_FUNCTION(Runtime_DynamicMapChecksEnabled) {
255   SealHandleScope shs(isolate);
256   DCHECK_EQ(0, args.length());
257   return isolate->heap()->ToBoolean(FLAG_turboprop_dynamic_map_checks);
258 }
259 
RUNTIME_FUNCTION(Runtime_OptimizeFunctionOnNextCall)260 RUNTIME_FUNCTION(Runtime_OptimizeFunctionOnNextCall) {
261   HandleScope scope(isolate);
262 
263   if (args.length() != 1 && args.length() != 2) {
264     return CrashUnlessFuzzing(isolate);
265   }
266 
267   CONVERT_ARG_HANDLE_CHECKED(Object, function_object, 0);
268   if (!function_object->IsJSFunction()) return CrashUnlessFuzzing(isolate);
269   Handle<JSFunction> function = Handle<JSFunction>::cast(function_object);
270 
271   // The following conditions were lifted (in part) from the DCHECK inside
272   // JSFunction::MarkForOptimization().
273 
274   if (!function->shared().allows_lazy_compilation()) {
275     return CrashUnlessFuzzing(isolate);
276   }
277 
278   // If function isn't compiled, compile it now.
279   IsCompiledScope is_compiled_scope(
280       function->shared().is_compiled_scope(isolate));
281   if (!is_compiled_scope.is_compiled() &&
282       !Compiler::Compile(function, Compiler::CLEAR_EXCEPTION,
283                          &is_compiled_scope)) {
284     return CrashUnlessFuzzing(isolate);
285   }
286 
287   if (!FLAG_opt) return ReadOnlyRoots(isolate).undefined_value();
288 
289   if (function->shared().optimization_disabled() &&
290       function->shared().disable_optimization_reason() ==
291           BailoutReason::kNeverOptimize) {
292     return CrashUnlessFuzzing(isolate);
293   }
294 
295   if (function->shared().HasAsmWasmData()) return CrashUnlessFuzzing(isolate);
296 
297   if (FLAG_testing_d8_test_runner) {
298     PendingOptimizationTable::MarkedForOptimization(isolate, function);
299   }
300 
301   if (function->HasAvailableOptimizedCode()) {
302     DCHECK(function->HasAttachedOptimizedCode() ||
303            function->ChecksOptimizationMarker());
304     if (FLAG_testing_d8_test_runner) {
305       PendingOptimizationTable::FunctionWasOptimized(isolate, function);
306     }
307     return ReadOnlyRoots(isolate).undefined_value();
308   }
309 
310   ConcurrencyMode concurrency_mode = ConcurrencyMode::kNotConcurrent;
311   if (args.length() == 2) {
312     CONVERT_ARG_HANDLE_CHECKED(Object, type, 1);
313     if (!type->IsString()) return CrashUnlessFuzzing(isolate);
314     if (Handle<String>::cast(type)->IsOneByteEqualTo(
315             StaticCharVector("concurrent")) &&
316         isolate->concurrent_recompilation_enabled()) {
317       concurrency_mode = ConcurrencyMode::kConcurrent;
318     }
319   }
320   if (FLAG_trace_opt) {
321     PrintF("[manually marking ");
322     function->ShortPrint();
323     PrintF(" for %s optimization]\n",
324            concurrency_mode == ConcurrencyMode::kConcurrent ? "concurrent"
325                                                             : "non-concurrent");
326   }
327 
328   // This function may not have been lazily compiled yet, even though its shared
329   // function has.
330   if (!function->is_compiled()) {
331     DCHECK(function->shared().IsInterpreted());
332     function->set_code(*BUILTIN_CODE(isolate, InterpreterEntryTrampoline));
333   }
334 
335   JSFunction::EnsureFeedbackVector(function, &is_compiled_scope);
336   function->MarkForOptimization(concurrency_mode);
337 
338   return ReadOnlyRoots(isolate).undefined_value();
339 }
340 
341 namespace {
342 
EnsureFeedbackVector(Handle<JSFunction> function)343 bool EnsureFeedbackVector(Handle<JSFunction> function) {
344   // Check function allows lazy compilation.
345   if (!function->shared().allows_lazy_compilation()) return false;
346 
347   if (function->has_feedback_vector()) return true;
348 
349   // If function isn't compiled, compile it now.
350   IsCompiledScope is_compiled_scope(
351       function->shared().is_compiled_scope(function->GetIsolate()));
352   // If the JSFunction isn't compiled but it has a initialized feedback cell
353   // then no need to compile. CompileLazy builtin would handle these cases by
354   // installing the code from SFI. Calling compile here may cause another
355   // optimization if FLAG_always_opt is set.
356   bool needs_compilation =
357       !function->is_compiled() && !function->has_closure_feedback_cell_array();
358   if (needs_compilation &&
359       !Compiler::Compile(function, Compiler::CLEAR_EXCEPTION,
360                          &is_compiled_scope)) {
361     return false;
362   }
363 
364   // Ensure function has a feedback vector to hold type feedback for
365   // optimization.
366   JSFunction::EnsureFeedbackVector(function, &is_compiled_scope);
367   return true;
368 }
369 
370 }  // namespace
371 
RUNTIME_FUNCTION(Runtime_EnsureFeedbackVectorForFunction)372 RUNTIME_FUNCTION(Runtime_EnsureFeedbackVectorForFunction) {
373   HandleScope scope(isolate);
374   DCHECK_EQ(1, args.length());
375   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
376   EnsureFeedbackVector(function);
377   return ReadOnlyRoots(isolate).undefined_value();
378 }
379 
RUNTIME_FUNCTION(Runtime_PrepareFunctionForOptimization)380 RUNTIME_FUNCTION(Runtime_PrepareFunctionForOptimization) {
381   HandleScope scope(isolate);
382   if ((args.length() != 1 && args.length() != 2) || !args[0].IsJSFunction()) {
383     return CrashUnlessFuzzing(isolate);
384   }
385   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
386 
387   bool allow_heuristic_optimization = false;
388   if (args.length() == 2) {
389     CONVERT_ARG_HANDLE_CHECKED(Object, sync_object, 1);
390     if (!sync_object->IsString()) return CrashUnlessFuzzing(isolate);
391     Handle<String> sync = Handle<String>::cast(sync_object);
392     if (sync->IsOneByteEqualTo(
393             StaticCharVector("allow heuristic optimization"))) {
394       allow_heuristic_optimization = true;
395     }
396   }
397 
398   if (!EnsureFeedbackVector(function)) {
399     return CrashUnlessFuzzing(isolate);
400   }
401 
402   // If optimization is disabled for the function, return without making it
403   // pending optimize for test.
404   if (function->shared().optimization_disabled() &&
405       function->shared().disable_optimization_reason() ==
406           BailoutReason::kNeverOptimize) {
407     return CrashUnlessFuzzing(isolate);
408   }
409 
410   if (function->shared().HasAsmWasmData()) return CrashUnlessFuzzing(isolate);
411 
412   // Hold onto the bytecode array between marking and optimization to ensure
413   // it's not flushed.
414   if (FLAG_testing_d8_test_runner) {
415     PendingOptimizationTable::PreparedForOptimization(
416         isolate, function, allow_heuristic_optimization);
417   }
418 
419   return ReadOnlyRoots(isolate).undefined_value();
420 }
421 
RUNTIME_FUNCTION(Runtime_OptimizeOsr)422 RUNTIME_FUNCTION(Runtime_OptimizeOsr) {
423   HandleScope scope(isolate);
424   DCHECK(args.length() == 0 || args.length() == 1);
425 
426   Handle<JSFunction> function;
427 
428   // The optional parameter determines the frame being targeted.
429   int stack_depth = 0;
430   if (args.length() == 1) {
431     if (!args[0].IsSmi()) return CrashUnlessFuzzing(isolate);
432     stack_depth = args.smi_at(0);
433   }
434 
435   // Find the JavaScript function on the top of the stack.
436   JavaScriptFrameIterator it(isolate);
437   while (!it.done() && stack_depth--) it.Advance();
438   if (!it.done()) function = handle(it.frame()->function(), isolate);
439   if (function.is_null()) return CrashUnlessFuzzing(isolate);
440 
441   if (!FLAG_opt) return ReadOnlyRoots(isolate).undefined_value();
442 
443   if (function->shared().optimization_disabled() &&
444       function->shared().disable_optimization_reason() ==
445           BailoutReason::kNeverOptimize) {
446     return CrashUnlessFuzzing(isolate);
447   }
448 
449   if (FLAG_testing_d8_test_runner) {
450     PendingOptimizationTable::MarkedForOptimization(isolate, function);
451   }
452 
453   if (function->HasAvailableOptimizedCode()) {
454     DCHECK(function->HasAttachedOptimizedCode() ||
455            function->ChecksOptimizationMarker());
456     // If function is already optimized, remove the bytecode array from the
457     // pending optimize for test table and return.
458     if (FLAG_testing_d8_test_runner) {
459       PendingOptimizationTable::FunctionWasOptimized(isolate, function);
460     }
461     return ReadOnlyRoots(isolate).undefined_value();
462   }
463 
464   // Ensure that the function is marked for non-concurrent optimization, so that
465   // subsequent runs don't also optimize.
466   if (FLAG_trace_osr) {
467     CodeTracer::Scope scope(isolate->GetCodeTracer());
468     PrintF(scope.file(), "[OSR - OptimizeOsr marking ");
469     function->ShortPrint(scope.file());
470     PrintF(scope.file(), " for non-concurrent optimization]\n");
471   }
472   IsCompiledScope is_compiled_scope(
473       function->shared().is_compiled_scope(isolate));
474   JSFunction::EnsureFeedbackVector(function, &is_compiled_scope);
475   function->MarkForOptimization(ConcurrencyMode::kNotConcurrent);
476 
477   // Make the profiler arm all back edges in unoptimized code.
478   if (it.frame()->type() == StackFrame::INTERPRETED) {
479     isolate->runtime_profiler()->AttemptOnStackReplacement(
480         InterpretedFrame::cast(it.frame()),
481         AbstractCode::kMaxLoopNestingMarker);
482   }
483 
484   return ReadOnlyRoots(isolate).undefined_value();
485 }
486 
487 
RUNTIME_FUNCTION(Runtime_NeverOptimizeFunction)488 RUNTIME_FUNCTION(Runtime_NeverOptimizeFunction) {
489   HandleScope scope(isolate);
490   DCHECK_EQ(1, args.length());
491   CONVERT_ARG_HANDLE_CHECKED(Object, function_object, 0);
492   if (!function_object->IsJSFunction()) return CrashUnlessFuzzing(isolate);
493   Handle<JSFunction> function = Handle<JSFunction>::cast(function_object);
494   SharedFunctionInfo sfi = function->shared();
495   if (sfi.abstract_code().kind() != CodeKind::INTERPRETED_FUNCTION &&
496       sfi.abstract_code().kind() != CodeKind::BUILTIN) {
497     return CrashUnlessFuzzing(isolate);
498   }
499   sfi.DisableOptimization(BailoutReason::kNeverOptimize);
500   return ReadOnlyRoots(isolate).undefined_value();
501 }
502 
RUNTIME_FUNCTION(Runtime_GetOptimizationStatus)503 RUNTIME_FUNCTION(Runtime_GetOptimizationStatus) {
504   HandleScope scope(isolate);
505   DCHECK(args.length() == 1 || args.length() == 2);
506   int status = 0;
507   if (FLAG_lite_mode || FLAG_jitless) {
508     // Both jitless and lite modes cannot optimize. Unit tests should handle
509     // these the same way. In the future, the two flags may become synonyms.
510     status |= static_cast<int>(OptimizationStatus::kLiteMode);
511   }
512   if (!isolate->use_optimizer()) {
513     status |= static_cast<int>(OptimizationStatus::kNeverOptimize);
514   }
515   if (FLAG_always_opt || FLAG_prepare_always_opt) {
516     status |= static_cast<int>(OptimizationStatus::kAlwaysOptimize);
517   }
518   if (FLAG_deopt_every_n_times) {
519     status |= static_cast<int>(OptimizationStatus::kMaybeDeopted);
520   }
521 
522   CONVERT_ARG_HANDLE_CHECKED(Object, function_object, 0);
523   if (function_object->IsUndefined()) return Smi::FromInt(status);
524   if (!function_object->IsJSFunction()) return CrashUnlessFuzzing(isolate);
525   Handle<JSFunction> function = Handle<JSFunction>::cast(function_object);
526 
527   status |= static_cast<int>(OptimizationStatus::kIsFunction);
528 
529   bool sync_with_compiler_thread = true;
530   if (args.length() == 2) {
531     CONVERT_ARG_HANDLE_CHECKED(Object, sync_object, 1);
532     if (!sync_object->IsString()) return CrashUnlessFuzzing(isolate);
533     Handle<String> sync = Handle<String>::cast(sync_object);
534     if (sync->IsOneByteEqualTo(StaticCharVector("no sync"))) {
535       sync_with_compiler_thread = false;
536     } else if (sync->IsOneByteEqualTo(StaticCharVector("sync")) ||
537                sync->length() == 0) {
538       DCHECK(sync_with_compiler_thread);
539     } else {
540       return CrashUnlessFuzzing(isolate);
541     }
542   }
543 
544   if (isolate->concurrent_recompilation_enabled() &&
545       sync_with_compiler_thread) {
546     while (function->IsInOptimizationQueue()) {
547       isolate->optimizing_compile_dispatcher()->InstallOptimizedFunctions();
548       base::OS::Sleep(base::TimeDelta::FromMilliseconds(50));
549     }
550   }
551 
552   if (function->IsMarkedForOptimization()) {
553     status |= static_cast<int>(OptimizationStatus::kMarkedForOptimization);
554   } else if (function->IsMarkedForConcurrentOptimization()) {
555     status |=
556         static_cast<int>(OptimizationStatus::kMarkedForConcurrentOptimization);
557   } else if (function->IsInOptimizationQueue()) {
558     status |= static_cast<int>(OptimizationStatus::kOptimizingConcurrently);
559   }
560 
561   if (function->HasAttachedOptimizedCode()) {
562     if (function->code().marked_for_deoptimization()) {
563       status |= static_cast<int>(OptimizationStatus::kMarkedForDeoptimization);
564     } else {
565       status |= static_cast<int>(OptimizationStatus::kOptimized);
566     }
567     if (function->code().is_turbofanned()) {
568       status |= static_cast<int>(OptimizationStatus::kTurboFanned);
569     }
570   }
571   if (function->ActiveTierIsIgnition()) {
572     status |= static_cast<int>(OptimizationStatus::kInterpreted);
573   }
574 
575   // Additionally, detect activations of this frame on the stack, and report the
576   // status of the topmost frame.
577   JavaScriptFrame* frame = nullptr;
578   JavaScriptFrameIterator it(isolate);
579   while (!it.done()) {
580     if (it.frame()->function() == *function) {
581       frame = it.frame();
582       break;
583     }
584     it.Advance();
585   }
586   if (frame != nullptr) {
587     status |= static_cast<int>(OptimizationStatus::kIsExecuting);
588     if (frame->is_optimized()) {
589       status |=
590           static_cast<int>(OptimizationStatus::kTopmostFrameIsTurboFanned);
591     }
592   }
593 
594   return Smi::FromInt(status);
595 }
596 
RUNTIME_FUNCTION(Runtime_UnblockConcurrentRecompilation)597 RUNTIME_FUNCTION(Runtime_UnblockConcurrentRecompilation) {
598   DCHECK_EQ(0, args.length());
599   CHECK(FLAG_block_concurrent_recompilation);
600   CHECK(isolate->concurrent_recompilation_enabled());
601   isolate->optimizing_compile_dispatcher()->Unblock();
602   return ReadOnlyRoots(isolate).undefined_value();
603 }
604 
ReturnNull(const v8::FunctionCallbackInfo<v8::Value> & args)605 static void ReturnNull(const v8::FunctionCallbackInfo<v8::Value>& args) {
606   args.GetReturnValue().SetNull();
607 }
608 
RUNTIME_FUNCTION(Runtime_GetUndetectable)609 RUNTIME_FUNCTION(Runtime_GetUndetectable) {
610   HandleScope scope(isolate);
611   DCHECK_EQ(0, args.length());
612   v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
613   Local<v8::ObjectTemplate> desc = v8::ObjectTemplate::New(v8_isolate);
614   desc->MarkAsUndetectable();
615   desc->SetCallAsFunctionHandler(ReturnNull);
616   Local<v8::Object> obj =
617       desc->NewInstance(v8_isolate->GetCurrentContext()).ToLocalChecked();
618   return *Utils::OpenHandle(*obj);
619 }
620 
call_as_function(const v8::FunctionCallbackInfo<v8::Value> & args)621 static void call_as_function(const v8::FunctionCallbackInfo<v8::Value>& args) {
622   double v1 =
623       args[0]->NumberValue(args.GetIsolate()->GetCurrentContext()).ToChecked();
624   double v2 =
625       args[1]->NumberValue(args.GetIsolate()->GetCurrentContext()).ToChecked();
626   args.GetReturnValue().Set(v8::Number::New(args.GetIsolate(), v1 - v2));
627 }
628 
629 // Returns a callable object. The object returns the difference of its two
630 // parameters when it is called.
RUNTIME_FUNCTION(Runtime_GetCallable)631 RUNTIME_FUNCTION(Runtime_GetCallable) {
632   HandleScope scope(isolate);
633   DCHECK_EQ(0, args.length());
634   v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
635   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(v8_isolate);
636   Local<ObjectTemplate> instance_template = t->InstanceTemplate();
637   instance_template->SetCallAsFunctionHandler(call_as_function);
638   v8_isolate->GetCurrentContext();
639   Local<v8::Object> instance =
640       t->GetFunction(v8_isolate->GetCurrentContext())
641           .ToLocalChecked()
642           ->NewInstance(v8_isolate->GetCurrentContext())
643           .ToLocalChecked();
644   return *Utils::OpenHandle(*instance);
645 }
646 
RUNTIME_FUNCTION(Runtime_ClearFunctionFeedback)647 RUNTIME_FUNCTION(Runtime_ClearFunctionFeedback) {
648   HandleScope scope(isolate);
649   DCHECK_EQ(1, args.length());
650   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
651   function->ClearTypeFeedbackInfo();
652   return ReadOnlyRoots(isolate).undefined_value();
653 }
654 
RUNTIME_FUNCTION(Runtime_SetWasmCompileControls)655 RUNTIME_FUNCTION(Runtime_SetWasmCompileControls) {
656   HandleScope scope(isolate);
657   v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
658   CHECK_EQ(args.length(), 2);
659   CONVERT_ARG_HANDLE_CHECKED(Smi, block_size, 0);
660   CONVERT_BOOLEAN_ARG_CHECKED(allow_async, 1);
661   base::MutexGuard guard(g_PerIsolateWasmControlsMutex.Pointer());
662   WasmCompileControls& ctrl = (*GetPerIsolateWasmControls())[v8_isolate];
663   ctrl.AllowAnySizeForAsync = allow_async;
664   ctrl.MaxWasmBufferSize = static_cast<uint32_t>(block_size->value());
665   v8_isolate->SetWasmModuleCallback(WasmModuleOverride);
666   return ReadOnlyRoots(isolate).undefined_value();
667 }
668 
RUNTIME_FUNCTION(Runtime_SetWasmInstantiateControls)669 RUNTIME_FUNCTION(Runtime_SetWasmInstantiateControls) {
670   HandleScope scope(isolate);
671   v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
672   CHECK_EQ(args.length(), 0);
673   v8_isolate->SetWasmInstanceCallback(WasmInstanceOverride);
674   return ReadOnlyRoots(isolate).undefined_value();
675 }
676 
RUNTIME_FUNCTION(Runtime_NotifyContextDisposed)677 RUNTIME_FUNCTION(Runtime_NotifyContextDisposed) {
678   HandleScope scope(isolate);
679   DCHECK_EQ(0, args.length());
680   isolate->heap()->NotifyContextDisposed(true);
681   return ReadOnlyRoots(isolate).undefined_value();
682 }
683 
684 
RUNTIME_FUNCTION(Runtime_SetAllocationTimeout)685 RUNTIME_FUNCTION(Runtime_SetAllocationTimeout) {
686   SealHandleScope shs(isolate);
687   DCHECK(args.length() == 2 || args.length() == 3);
688 #ifdef V8_ENABLE_ALLOCATION_TIMEOUT
689   CONVERT_INT32_ARG_FUZZ_SAFE(timeout, 1);
690   isolate->heap()->set_allocation_timeout(timeout);
691 #endif
692 #ifdef DEBUG
693   CONVERT_INT32_ARG_FUZZ_SAFE(interval, 0);
694   FLAG_gc_interval = interval;
695   if (args.length() == 3) {
696     // Enable/disable inline allocation if requested.
697     CONVERT_BOOLEAN_ARG_FUZZ_SAFE(inline_allocation, 2);
698     if (inline_allocation) {
699       isolate->heap()->EnableInlineAllocation();
700     } else {
701       isolate->heap()->DisableInlineAllocation();
702     }
703   }
704 #endif
705   return ReadOnlyRoots(isolate).undefined_value();
706 }
707 
708 namespace {
709 
FixedArrayLenFromSize(int size)710 int FixedArrayLenFromSize(int size) {
711   return Min((size - FixedArray::kHeaderSize) / kTaggedSize,
712              FixedArray::kMaxRegularLength);
713 }
714 
FillUpOneNewSpacePage(Isolate * isolate,Heap * heap)715 void FillUpOneNewSpacePage(Isolate* isolate, Heap* heap) {
716   PauseAllocationObserversScope pause_observers(heap);
717   NewSpace* space = heap->new_space();
718   // We cannot rely on `space->limit()` to point to the end of the current page
719   // in the case where inline allocations are disabled, it actually points to
720   // the current allocation pointer.
721   DCHECK_IMPLIES(space->heap()->inline_allocation_disabled(),
722                  space->limit() == space->top());
723   int space_remaining =
724       static_cast<int>(space->to_space().page_high() - space->top());
725   while (space_remaining > 0) {
726     int length = FixedArrayLenFromSize(space_remaining);
727     if (length > 0) {
728       Handle<FixedArray> padding =
729           isolate->factory()->NewFixedArray(length, AllocationType::kYoung);
730       DCHECK(heap->new_space()->Contains(*padding));
731       space_remaining -= padding->Size();
732     } else {
733       // Not enough room to create another fixed array. Create a filler.
734       heap->CreateFillerObjectAt(*heap->new_space()->allocation_top_address(),
735                                  space_remaining, ClearRecordedSlots::kNo);
736       break;
737     }
738   }
739 }
740 
741 }  // namespace
742 
RUNTIME_FUNCTION(Runtime_SimulateNewspaceFull)743 RUNTIME_FUNCTION(Runtime_SimulateNewspaceFull) {
744   HandleScope scope(isolate);
745   Heap* heap = isolate->heap();
746   NewSpace* space = heap->new_space();
747   AlwaysAllocateScopeForTesting always_allocate(heap);
748   do {
749     FillUpOneNewSpacePage(isolate, heap);
750   } while (space->AddFreshPage());
751 
752   return ReadOnlyRoots(isolate).undefined_value();
753 }
754 
DebugPrintImpl(MaybeObject maybe_object)755 static void DebugPrintImpl(MaybeObject maybe_object) {
756   StdoutStream os;
757   if (maybe_object->IsCleared()) {
758     os << "[weak cleared]";
759   } else {
760     Object object = maybe_object.GetHeapObjectOrSmi();
761     bool weak = maybe_object.IsWeak();
762 
763 #ifdef OBJECT_PRINT
764     os << "DebugPrint: ";
765     if (weak) os << "[weak] ";
766     object.Print(os);
767     if (object.IsHeapObject()) {
768       HeapObject::cast(object).map().Print(os);
769     }
770 #else
771     if (weak) os << "[weak] ";
772     // ShortPrint is available in release mode. Print is not.
773     os << Brief(object);
774 #endif
775   }
776   os << std::endl;
777 }
778 
RUNTIME_FUNCTION(Runtime_DebugPrint)779 RUNTIME_FUNCTION(Runtime_DebugPrint) {
780   SealHandleScope shs(isolate);
781   DCHECK_EQ(1, args.length());
782 
783   MaybeObject maybe_object(*args.address_of_arg_at(0));
784   DebugPrintImpl(maybe_object);
785   return args[0];
786 }
787 
RUNTIME_FUNCTION(Runtime_DebugPrintPtr)788 RUNTIME_FUNCTION(Runtime_DebugPrintPtr) {
789   SealHandleScope shs(isolate);
790   StdoutStream os;
791   DCHECK_EQ(1, args.length());
792 
793   MaybeObject maybe_object(*args.address_of_arg_at(0));
794   if (!maybe_object.IsCleared()) {
795     Object object = maybe_object.GetHeapObjectOrSmi();
796     size_t pointer;
797     if (object.ToIntegerIndex(&pointer)) {
798       MaybeObject from_pointer(static_cast<Address>(pointer));
799       DebugPrintImpl(from_pointer);
800     }
801   }
802   // We don't allow the converted pointer to leak out to JavaScript.
803   return args[0];
804 }
805 
RUNTIME_FUNCTION(Runtime_PrintWithNameForAssert)806 RUNTIME_FUNCTION(Runtime_PrintWithNameForAssert) {
807   SealHandleScope shs(isolate);
808   DCHECK_EQ(2, args.length());
809 
810   CONVERT_ARG_CHECKED(String, name, 0);
811 
812   PrintF(" * ");
813   StringCharacterStream stream(name);
814   while (stream.HasMore()) {
815     uint16_t character = stream.GetNext();
816     PrintF("%c", character);
817   }
818   PrintF(": ");
819   args[1].ShortPrint();
820   PrintF("\n");
821 
822   return ReadOnlyRoots(isolate).undefined_value();
823 }
824 
RUNTIME_FUNCTION(Runtime_DebugTrace)825 RUNTIME_FUNCTION(Runtime_DebugTrace) {
826   SealHandleScope shs(isolate);
827   DCHECK_EQ(0, args.length());
828   isolate->PrintStack(stdout);
829   return ReadOnlyRoots(isolate).undefined_value();
830 }
831 
RUNTIME_FUNCTION(Runtime_DebugTrackRetainingPath)832 RUNTIME_FUNCTION(Runtime_DebugTrackRetainingPath) {
833   HandleScope scope(isolate);
834   DCHECK_LE(1, args.length());
835   DCHECK_GE(2, args.length());
836   CHECK(FLAG_track_retaining_path);
837   CONVERT_ARG_HANDLE_CHECKED(HeapObject, object, 0);
838   RetainingPathOption option = RetainingPathOption::kDefault;
839   if (args.length() == 2) {
840     CONVERT_ARG_HANDLE_CHECKED(String, str, 1);
841     const char track_ephemeron_path[] = "track-ephemeron-path";
842     if (str->IsOneByteEqualTo(StaticCharVector(track_ephemeron_path))) {
843       option = RetainingPathOption::kTrackEphemeronPath;
844     } else {
845       CHECK_EQ(str->length(), 0);
846     }
847   }
848   isolate->heap()->AddRetainingPathTarget(object, option);
849   return ReadOnlyRoots(isolate).undefined_value();
850 }
851 
852 // This will not allocate (flatten the string), but it may run
853 // very slowly for very deeply nested ConsStrings.  For debugging use only.
RUNTIME_FUNCTION(Runtime_GlobalPrint)854 RUNTIME_FUNCTION(Runtime_GlobalPrint) {
855   SealHandleScope shs(isolate);
856   DCHECK_EQ(1, args.length());
857 
858   CONVERT_ARG_CHECKED(String, string, 0);
859   StringCharacterStream stream(string);
860   while (stream.HasMore()) {
861     uint16_t character = stream.GetNext();
862     PrintF("%c", character);
863   }
864   return string;
865 }
866 
867 
RUNTIME_FUNCTION(Runtime_SystemBreak)868 RUNTIME_FUNCTION(Runtime_SystemBreak) {
869   // The code below doesn't create handles, but when breaking here in GDB
870   // having a handle scope might be useful.
871   HandleScope scope(isolate);
872   DCHECK_EQ(0, args.length());
873   base::OS::DebugBreak();
874   return ReadOnlyRoots(isolate).undefined_value();
875 }
876 
877 
RUNTIME_FUNCTION(Runtime_SetForceSlowPath)878 RUNTIME_FUNCTION(Runtime_SetForceSlowPath) {
879   SealHandleScope shs(isolate);
880   DCHECK_EQ(1, args.length());
881   CONVERT_ARG_CHECKED(Object, arg, 0);
882   if (arg.IsTrue(isolate)) {
883     isolate->set_force_slow_path(true);
884   } else {
885     DCHECK(arg.IsFalse(isolate));
886     isolate->set_force_slow_path(false);
887   }
888   return ReadOnlyRoots(isolate).undefined_value();
889 }
890 
RUNTIME_FUNCTION(Runtime_Abort)891 RUNTIME_FUNCTION(Runtime_Abort) {
892   SealHandleScope shs(isolate);
893   DCHECK_EQ(1, args.length());
894   CONVERT_SMI_ARG_CHECKED(message_id, 0);
895   const char* message = GetAbortReason(static_cast<AbortReason>(message_id));
896   base::OS::PrintError("abort: %s\n", message);
897   isolate->PrintStack(stderr);
898   base::OS::Abort();
899   UNREACHABLE();
900 }
901 
RUNTIME_FUNCTION(Runtime_AbortJS)902 RUNTIME_FUNCTION(Runtime_AbortJS) {
903   HandleScope scope(isolate);
904   DCHECK_EQ(1, args.length());
905   CONVERT_ARG_HANDLE_CHECKED(String, message, 0);
906   if (FLAG_disable_abortjs) {
907     base::OS::PrintError("[disabled] abort: %s\n", message->ToCString().get());
908     return Object();
909   }
910   base::OS::PrintError("abort: %s\n", message->ToCString().get());
911   isolate->PrintStack(stderr);
912   base::OS::Abort();
913   UNREACHABLE();
914 }
915 
RUNTIME_FUNCTION(Runtime_AbortCSAAssert)916 RUNTIME_FUNCTION(Runtime_AbortCSAAssert) {
917   HandleScope scope(isolate);
918   DCHECK_EQ(1, args.length());
919   CONVERT_ARG_HANDLE_CHECKED(String, message, 0);
920   base::OS::PrintError("abort: CSA_ASSERT failed: %s\n",
921                        message->ToCString().get());
922   isolate->PrintStack(stderr);
923   base::OS::Abort();
924   UNREACHABLE();
925 }
926 
RUNTIME_FUNCTION(Runtime_DisassembleFunction)927 RUNTIME_FUNCTION(Runtime_DisassembleFunction) {
928   HandleScope scope(isolate);
929 #ifdef DEBUG
930   DCHECK_EQ(1, args.length());
931   // Get the function and make sure it is compiled.
932   CONVERT_ARG_HANDLE_CHECKED(JSFunction, func, 0);
933   IsCompiledScope is_compiled_scope;
934   CHECK(func->is_compiled() ||
935         Compiler::Compile(func, Compiler::KEEP_EXCEPTION, &is_compiled_scope));
936   StdoutStream os;
937   func->code().Print(os);
938   os << std::endl;
939 #endif  // DEBUG
940   return ReadOnlyRoots(isolate).undefined_value();
941 }
942 
943 namespace {
944 
StackSize(Isolate * isolate)945 int StackSize(Isolate* isolate) {
946   int n = 0;
947   for (JavaScriptFrameIterator it(isolate); !it.done(); it.Advance()) n++;
948   return n;
949 }
950 
PrintIndentation(int stack_size)951 void PrintIndentation(int stack_size) {
952   const int max_display = 80;
953   if (stack_size <= max_display) {
954     PrintF("%4d:%*s", stack_size, stack_size, "");
955   } else {
956     PrintF("%4d:%*s", stack_size, max_display, "...");
957   }
958 }
959 
960 }  // namespace
961 
RUNTIME_FUNCTION(Runtime_TraceEnter)962 RUNTIME_FUNCTION(Runtime_TraceEnter) {
963   SealHandleScope shs(isolate);
964   DCHECK_EQ(0, args.length());
965   PrintIndentation(StackSize(isolate));
966   JavaScriptFrame::PrintTop(isolate, stdout, true, false);
967   PrintF(" {\n");
968   return ReadOnlyRoots(isolate).undefined_value();
969 }
970 
RUNTIME_FUNCTION(Runtime_TraceExit)971 RUNTIME_FUNCTION(Runtime_TraceExit) {
972   SealHandleScope shs(isolate);
973   DCHECK_EQ(1, args.length());
974   CONVERT_ARG_CHECKED(Object, obj, 0);
975   PrintIndentation(StackSize(isolate));
976   PrintF("} -> ");
977   obj.ShortPrint();
978   PrintF("\n");
979   return obj;  // return TOS
980 }
981 
982 namespace {
983 
WasmStackSize(Isolate * isolate)984 int WasmStackSize(Isolate* isolate) {
985   // TODO(wasm): Fix this for mixed JS/Wasm stacks with both --trace and
986   // --trace-wasm.
987   int n = 0;
988   for (StackTraceFrameIterator it(isolate); !it.done(); it.Advance()) {
989     if (it.is_wasm()) n++;
990   }
991   return n;
992 }
993 
994 }  // namespace
995 
RUNTIME_FUNCTION(Runtime_WasmTraceEnter)996 RUNTIME_FUNCTION(Runtime_WasmTraceEnter) {
997   HandleScope shs(isolate);
998   DCHECK_EQ(0, args.length());
999   PrintIndentation(WasmStackSize(isolate));
1000 
1001   // Find the caller wasm frame.
1002   wasm::WasmCodeRefScope wasm_code_ref_scope;
1003   StackTraceFrameIterator it(isolate);
1004   DCHECK(!it.done());
1005   DCHECK(it.is_wasm());
1006   WasmFrame* frame = WasmFrame::cast(it.frame());
1007 
1008   // Find the function name.
1009   int func_index = frame->function_index();
1010   const wasm::WasmModule* module = frame->wasm_instance().module();
1011   wasm::ModuleWireBytes wire_bytes =
1012       wasm::ModuleWireBytes(frame->native_module()->wire_bytes());
1013   wasm::WireBytesRef name_ref =
1014       module->lazily_generated_names.LookupFunctionName(
1015           wire_bytes, func_index, VectorOf(module->export_table));
1016   wasm::WasmName name = wire_bytes.GetNameOrNull(name_ref);
1017 
1018   wasm::WasmCode* code = frame->wasm_code();
1019   PrintF(code->is_liftoff() ? "~" : "*");
1020 
1021   if (name.empty()) {
1022     PrintF("wasm-function[%d] {\n", func_index);
1023   } else {
1024     PrintF("wasm-function[%d] \"%.*s\" {\n", func_index, name.length(),
1025            name.begin());
1026   }
1027 
1028   return ReadOnlyRoots(isolate).undefined_value();
1029 }
1030 
RUNTIME_FUNCTION(Runtime_WasmTraceExit)1031 RUNTIME_FUNCTION(Runtime_WasmTraceExit) {
1032   HandleScope shs(isolate);
1033   DCHECK_EQ(1, args.length());
1034   CONVERT_ARG_CHECKED(Smi, value_addr_smi, 0);
1035 
1036   PrintIndentation(WasmStackSize(isolate));
1037   PrintF("}");
1038 
1039   // Find the caller wasm frame.
1040   wasm::WasmCodeRefScope wasm_code_ref_scope;
1041   StackTraceFrameIterator it(isolate);
1042   DCHECK(!it.done());
1043   DCHECK(it.is_wasm());
1044   WasmFrame* frame = WasmFrame::cast(it.frame());
1045   int func_index = frame->function_index();
1046   const wasm::FunctionSig* sig =
1047       frame->wasm_instance().module()->functions[func_index].sig;
1048 
1049   size_t num_returns = sig->return_count();
1050   if (num_returns == 1) {
1051     wasm::ValueType return_type = sig->GetReturn(0);
1052     switch (return_type.kind()) {
1053       case wasm::ValueType::kI32: {
1054         int32_t value = ReadUnalignedValue<int32_t>(value_addr_smi.ptr());
1055         PrintF(" -> %d\n", value);
1056         break;
1057       }
1058       case wasm::ValueType::kI64: {
1059         int64_t value = ReadUnalignedValue<int64_t>(value_addr_smi.ptr());
1060         PrintF(" -> %" PRId64 "\n", value);
1061         break;
1062       }
1063       case wasm::ValueType::kF32: {
1064         float_t value = ReadUnalignedValue<float_t>(value_addr_smi.ptr());
1065         PrintF(" -> %f\n", value);
1066         break;
1067       }
1068       case wasm::ValueType::kF64: {
1069         double_t value = ReadUnalignedValue<double_t>(value_addr_smi.ptr());
1070         PrintF(" -> %f\n", value);
1071         break;
1072       }
1073       default:
1074         PrintF(" -> Unsupported type\n");
1075         break;
1076     }
1077   } else {
1078     // TODO(wasm) Handle multiple return values.
1079     PrintF("\n");
1080   }
1081 
1082   return ReadOnlyRoots(isolate).undefined_value();
1083 }
1084 
RUNTIME_FUNCTION(Runtime_HaveSameMap)1085 RUNTIME_FUNCTION(Runtime_HaveSameMap) {
1086   SealHandleScope shs(isolate);
1087   DCHECK_EQ(2, args.length());
1088   CONVERT_ARG_CHECKED(JSObject, obj1, 0);
1089   CONVERT_ARG_CHECKED(JSObject, obj2, 1);
1090   return isolate->heap()->ToBoolean(obj1.map() == obj2.map());
1091 }
1092 
RUNTIME_FUNCTION(Runtime_InLargeObjectSpace)1093 RUNTIME_FUNCTION(Runtime_InLargeObjectSpace) {
1094   SealHandleScope shs(isolate);
1095   DCHECK_EQ(1, args.length());
1096   CONVERT_ARG_CHECKED(HeapObject, obj, 0);
1097   return isolate->heap()->ToBoolean(
1098       isolate->heap()->new_lo_space()->Contains(obj) ||
1099       isolate->heap()->code_lo_space()->Contains(obj) ||
1100       isolate->heap()->lo_space()->Contains(obj));
1101 }
1102 
RUNTIME_FUNCTION(Runtime_HasElementsInALargeObjectSpace)1103 RUNTIME_FUNCTION(Runtime_HasElementsInALargeObjectSpace) {
1104   SealHandleScope shs(isolate);
1105   DCHECK_EQ(1, args.length());
1106   CONVERT_ARG_CHECKED(JSArray, array, 0);
1107   FixedArrayBase elements = array.elements();
1108   return isolate->heap()->ToBoolean(
1109       isolate->heap()->new_lo_space()->Contains(elements) ||
1110       isolate->heap()->lo_space()->Contains(elements));
1111 }
1112 
RUNTIME_FUNCTION(Runtime_InYoungGeneration)1113 RUNTIME_FUNCTION(Runtime_InYoungGeneration) {
1114   SealHandleScope shs(isolate);
1115   DCHECK_EQ(1, args.length());
1116   CONVERT_ARG_CHECKED(Object, obj, 0);
1117   return isolate->heap()->ToBoolean(ObjectInYoungGeneration(obj));
1118 }
1119 
RUNTIME_FUNCTION(Runtime_IsAsmWasmCode)1120 RUNTIME_FUNCTION(Runtime_IsAsmWasmCode) {
1121   SealHandleScope shs(isolate);
1122   DCHECK_EQ(1, args.length());
1123   CONVERT_ARG_CHECKED(JSFunction, function, 0);
1124   if (!function.shared().HasAsmWasmData()) {
1125     return ReadOnlyRoots(isolate).false_value();
1126   }
1127   if (function.shared().HasBuiltinId() &&
1128       function.shared().builtin_id() == Builtins::kInstantiateAsmJs) {
1129     // Hasn't been compiled yet.
1130     return ReadOnlyRoots(isolate).false_value();
1131   }
1132   return ReadOnlyRoots(isolate).true_value();
1133 }
1134 
1135 namespace {
1136 
DisallowCodegenFromStringsCallback(v8::Local<v8::Context> context,v8::Local<v8::Value> source,bool is_code_kind)1137 v8::ModifyCodeGenerationFromStringsResult DisallowCodegenFromStringsCallback(
1138     v8::Local<v8::Context> context, v8::Local<v8::Value> source,
1139     bool is_code_kind) {
1140   return {false, {}};
1141 }
1142 
DisallowWasmCodegenFromStringsCallback(v8::Local<v8::Context> context,v8::Local<v8::String> source)1143 bool DisallowWasmCodegenFromStringsCallback(v8::Local<v8::Context> context,
1144                                             v8::Local<v8::String> source) {
1145   return false;
1146 }
1147 
1148 }  // namespace
1149 
RUNTIME_FUNCTION(Runtime_DisallowCodegenFromStrings)1150 RUNTIME_FUNCTION(Runtime_DisallowCodegenFromStrings) {
1151   SealHandleScope shs(isolate);
1152   DCHECK_EQ(1, args.length());
1153   CONVERT_BOOLEAN_ARG_CHECKED(flag, 0);
1154   v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
1155   v8_isolate->SetModifyCodeGenerationFromStringsCallback(
1156       flag ? DisallowCodegenFromStringsCallback : nullptr);
1157   return ReadOnlyRoots(isolate).undefined_value();
1158 }
1159 
RUNTIME_FUNCTION(Runtime_DisallowWasmCodegen)1160 RUNTIME_FUNCTION(Runtime_DisallowWasmCodegen) {
1161   SealHandleScope shs(isolate);
1162   DCHECK_EQ(1, args.length());
1163   CONVERT_BOOLEAN_ARG_CHECKED(flag, 0);
1164   v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
1165   v8_isolate->SetAllowWasmCodeGenerationCallback(
1166       flag ? DisallowWasmCodegenFromStringsCallback : nullptr);
1167   return ReadOnlyRoots(isolate).undefined_value();
1168 }
1169 
RUNTIME_FUNCTION(Runtime_IsWasmCode)1170 RUNTIME_FUNCTION(Runtime_IsWasmCode) {
1171   SealHandleScope shs(isolate);
1172   DCHECK_EQ(1, args.length());
1173   CONVERT_ARG_CHECKED(JSFunction, function, 0);
1174   bool is_js_to_wasm =
1175       function.code().kind() == CodeKind::JS_TO_WASM_FUNCTION ||
1176       (function.code().is_builtin() &&
1177        function.code().builtin_index() == Builtins::kGenericJSToWasmWrapper);
1178   return isolate->heap()->ToBoolean(is_js_to_wasm);
1179 }
1180 
RUNTIME_FUNCTION(Runtime_IsWasmTrapHandlerEnabled)1181 RUNTIME_FUNCTION(Runtime_IsWasmTrapHandlerEnabled) {
1182   DisallowHeapAllocation no_gc;
1183   DCHECK_EQ(0, args.length());
1184   return isolate->heap()->ToBoolean(trap_handler::IsTrapHandlerEnabled());
1185 }
1186 
RUNTIME_FUNCTION(Runtime_IsThreadInWasm)1187 RUNTIME_FUNCTION(Runtime_IsThreadInWasm) {
1188   DisallowHeapAllocation no_gc;
1189   DCHECK_EQ(0, args.length());
1190   return isolate->heap()->ToBoolean(trap_handler::IsThreadInWasm());
1191 }
1192 
RUNTIME_FUNCTION(Runtime_GetWasmRecoveredTrapCount)1193 RUNTIME_FUNCTION(Runtime_GetWasmRecoveredTrapCount) {
1194   HandleScope scope(isolate);
1195   DCHECK_EQ(0, args.length());
1196   size_t trap_count = trap_handler::GetRecoveredTrapCount();
1197   return *isolate->factory()->NewNumberFromSize(trap_count);
1198 }
1199 
RUNTIME_FUNCTION(Runtime_GetWasmExceptionId)1200 RUNTIME_FUNCTION(Runtime_GetWasmExceptionId) {
1201   HandleScope scope(isolate);
1202   DCHECK_EQ(2, args.length());
1203   CONVERT_ARG_HANDLE_CHECKED(WasmExceptionPackage, exception, 0);
1204   CONVERT_ARG_HANDLE_CHECKED(WasmInstanceObject, instance, 1);
1205   Handle<Object> tag =
1206       WasmExceptionPackage::GetExceptionTag(isolate, exception);
1207   CHECK(tag->IsWasmExceptionTag());
1208   Handle<FixedArray> exceptions_table(instance->exceptions_table(), isolate);
1209   for (int index = 0; index < exceptions_table->length(); ++index) {
1210     if (exceptions_table->get(index) == *tag) return Smi::FromInt(index);
1211   }
1212   UNREACHABLE();
1213 }
1214 
RUNTIME_FUNCTION(Runtime_GetWasmExceptionValues)1215 RUNTIME_FUNCTION(Runtime_GetWasmExceptionValues) {
1216   HandleScope scope(isolate);
1217   DCHECK_EQ(1, args.length());
1218   CONVERT_ARG_HANDLE_CHECKED(WasmExceptionPackage, exception, 0);
1219   Handle<Object> values_obj =
1220       WasmExceptionPackage::GetExceptionValues(isolate, exception);
1221   CHECK(values_obj->IsFixedArray());  // Only called with correct input.
1222   Handle<FixedArray> values = Handle<FixedArray>::cast(values_obj);
1223   return *isolate->factory()->NewJSArrayWithElements(values);
1224 }
1225 
1226 namespace {
EnableWasmThreads(v8::Local<v8::Context> context)1227 bool EnableWasmThreads(v8::Local<v8::Context> context) { return true; }
DisableWasmThreads(v8::Local<v8::Context> context)1228 bool DisableWasmThreads(v8::Local<v8::Context> context) { return false; }
1229 }  // namespace
1230 
1231 // This runtime function enables WebAssembly threads through an embedder
1232 // callback and thereby bypasses the value in FLAG_experimental_wasm_threads.
RUNTIME_FUNCTION(Runtime_SetWasmThreadsEnabled)1233 RUNTIME_FUNCTION(Runtime_SetWasmThreadsEnabled) {
1234   DCHECK_EQ(1, args.length());
1235   CONVERT_BOOLEAN_ARG_CHECKED(flag, 0);
1236   v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
1237   v8_isolate->SetWasmThreadsEnabledCallback(flag ? EnableWasmThreads
1238                                                  : DisableWasmThreads);
1239   return ReadOnlyRoots(isolate).undefined_value();
1240 }
1241 
RUNTIME_FUNCTION(Runtime_RegexpHasBytecode)1242 RUNTIME_FUNCTION(Runtime_RegexpHasBytecode) {
1243   SealHandleScope shs(isolate);
1244   DCHECK_EQ(2, args.length());
1245   CONVERT_ARG_CHECKED(JSRegExp, regexp, 0);
1246   CONVERT_BOOLEAN_ARG_CHECKED(is_latin1, 1);
1247   bool result;
1248   if (regexp.TypeTag() == JSRegExp::IRREGEXP) {
1249     result = regexp.Bytecode(is_latin1).IsByteArray();
1250   } else {
1251     result = false;
1252   }
1253   return isolate->heap()->ToBoolean(result);
1254 }
1255 
RUNTIME_FUNCTION(Runtime_RegexpHasNativeCode)1256 RUNTIME_FUNCTION(Runtime_RegexpHasNativeCode) {
1257   SealHandleScope shs(isolate);
1258   DCHECK_EQ(2, args.length());
1259   CONVERT_ARG_CHECKED(JSRegExp, regexp, 0);
1260   CONVERT_BOOLEAN_ARG_CHECKED(is_latin1, 1);
1261   bool result;
1262   if (regexp.TypeTag() == JSRegExp::IRREGEXP) {
1263     result = regexp.Code(is_latin1).IsCode();
1264   } else {
1265     result = false;
1266   }
1267   return isolate->heap()->ToBoolean(result);
1268 }
1269 
RUNTIME_FUNCTION(Runtime_RegexpTypeTag)1270 RUNTIME_FUNCTION(Runtime_RegexpTypeTag) {
1271   HandleScope shs(isolate);
1272   DCHECK_EQ(1, args.length());
1273   CONVERT_ARG_CHECKED(JSRegExp, regexp, 0);
1274   const char* type_str;
1275   switch (regexp.TypeTag()) {
1276     case JSRegExp::NOT_COMPILED:
1277       type_str = "NOT_COMPILED";
1278       break;
1279     case JSRegExp::ATOM:
1280       type_str = "ATOM";
1281       break;
1282     case JSRegExp::IRREGEXP:
1283       type_str = "IRREGEXP";
1284       break;
1285     case JSRegExp::EXPERIMENTAL:
1286       type_str = "EXPERIMENTAL";
1287       break;
1288   }
1289   return *isolate->factory()->NewStringFromAsciiChecked(type_str);
1290 }
1291 
RUNTIME_FUNCTION(Runtime_RegexpIsUnmodified)1292 RUNTIME_FUNCTION(Runtime_RegexpIsUnmodified) {
1293   HandleScope shs(isolate);
1294   DCHECK_EQ(1, args.length());
1295   CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 0);
1296   return isolate->heap()->ToBoolean(
1297       RegExp::IsUnmodifiedRegExp(isolate, regexp));
1298 }
1299 
1300 #define ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(Name)      \
1301   RUNTIME_FUNCTION(Runtime_Has##Name) {                 \
1302     CONVERT_ARG_CHECKED(JSObject, obj, 0);              \
1303     return isolate->heap()->ToBoolean(obj.Has##Name()); \
1304   }
1305 
1306 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastElements)
ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(SmiElements)1307 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(SmiElements)
1308 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ObjectElements)
1309 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(SmiOrObjectElements)
1310 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(DoubleElements)
1311 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(HoleyElements)
1312 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(DictionaryElements)
1313 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(PackedElements)
1314 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(SloppyArgumentsElements)
1315 // Properties test sitting with elements tests - not fooling anyone.
1316 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastProperties)
1317 
1318 #undef ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION
1319 
1320 #define FIXED_TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION(Type, type, TYPE, ctype) \
1321   RUNTIME_FUNCTION(Runtime_HasFixed##Type##Elements) {                     \
1322     CONVERT_ARG_CHECKED(JSObject, obj, 0);                                 \
1323     return isolate->heap()->ToBoolean(obj.HasFixed##Type##Elements());     \
1324   }
1325 
1326 TYPED_ARRAYS(FIXED_TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION)
1327 
1328 #undef FIXED_TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION
1329 
1330 RUNTIME_FUNCTION(Runtime_ArraySpeciesProtector) {
1331   SealHandleScope shs(isolate);
1332   DCHECK_EQ(0, args.length());
1333   return isolate->heap()->ToBoolean(
1334       Protectors::IsArraySpeciesLookupChainIntact(isolate));
1335 }
1336 
RUNTIME_FUNCTION(Runtime_MapIteratorProtector)1337 RUNTIME_FUNCTION(Runtime_MapIteratorProtector) {
1338   SealHandleScope shs(isolate);
1339   DCHECK_EQ(0, args.length());
1340   return isolate->heap()->ToBoolean(
1341       Protectors::IsMapIteratorLookupChainIntact(isolate));
1342 }
1343 
RUNTIME_FUNCTION(Runtime_SetIteratorProtector)1344 RUNTIME_FUNCTION(Runtime_SetIteratorProtector) {
1345   SealHandleScope shs(isolate);
1346   DCHECK_EQ(0, args.length());
1347   return isolate->heap()->ToBoolean(
1348       Protectors::IsSetIteratorLookupChainIntact(isolate));
1349 }
1350 
RUNTIME_FUNCTION(Runtime_StringIteratorProtector)1351 RUNTIME_FUNCTION(Runtime_StringIteratorProtector) {
1352   SealHandleScope shs(isolate);
1353   DCHECK_EQ(0, args.length());
1354   return isolate->heap()->ToBoolean(
1355       Protectors::IsStringIteratorLookupChainIntact(isolate));
1356 }
1357 
1358 // For use by tests and fuzzers. It
1359 //
1360 // 1. serializes a snapshot of the current isolate,
1361 // 2. deserializes the snapshot,
1362 // 3. and runs VerifyHeap on the resulting isolate.
1363 //
1364 // The current isolate should not be modified by this call and can keep running
1365 // once it completes.
RUNTIME_FUNCTION(Runtime_SerializeDeserializeNow)1366 RUNTIME_FUNCTION(Runtime_SerializeDeserializeNow) {
1367   HandleScope scope(isolate);
1368   DCHECK_EQ(0, args.length());
1369   Snapshot::SerializeDeserializeAndVerifyForTesting(isolate,
1370                                                     isolate->native_context());
1371   return ReadOnlyRoots(isolate).undefined_value();
1372 }
1373 
1374 // Wait until the given module is fully tiered up, then serialize it into an
1375 // array buffer.
RUNTIME_FUNCTION(Runtime_SerializeWasmModule)1376 RUNTIME_FUNCTION(Runtime_SerializeWasmModule) {
1377   HandleScope scope(isolate);
1378   DCHECK_EQ(1, args.length());
1379   CONVERT_ARG_HANDLE_CHECKED(WasmModuleObject, module_obj, 0);
1380 
1381   wasm::NativeModule* native_module = module_obj->native_module();
1382   native_module->compilation_state()->WaitForTopTierFinished();
1383   DCHECK(!native_module->compilation_state()->failed());
1384 
1385   wasm::WasmSerializer wasm_serializer(native_module);
1386   size_t byte_length = wasm_serializer.GetSerializedNativeModuleSize();
1387 
1388   Handle<JSArrayBuffer> array_buffer =
1389       isolate->factory()
1390           ->NewJSArrayBufferAndBackingStore(byte_length,
1391                                             InitializedFlag::kUninitialized)
1392           .ToHandleChecked();
1393 
1394   CHECK(wasm_serializer.SerializeNativeModule(
1395       {static_cast<uint8_t*>(array_buffer->backing_store()), byte_length}));
1396   return *array_buffer;
1397 }
1398 
1399 // Take an array buffer and attempt to reconstruct a compiled wasm module.
1400 // Return undefined if unsuccessful.
RUNTIME_FUNCTION(Runtime_DeserializeWasmModule)1401 RUNTIME_FUNCTION(Runtime_DeserializeWasmModule) {
1402   HandleScope scope(isolate);
1403   DCHECK_EQ(2, args.length());
1404   CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, buffer, 0);
1405   CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, wire_bytes, 1);
1406   CHECK(!buffer->was_detached());
1407   CHECK(!wire_bytes->WasDetached());
1408 
1409   Handle<JSArrayBuffer> wire_bytes_buffer = wire_bytes->GetBuffer();
1410   Vector<const uint8_t> wire_bytes_vec{
1411       reinterpret_cast<const uint8_t*>(wire_bytes_buffer->backing_store()) +
1412           wire_bytes->byte_offset(),
1413       wire_bytes->byte_length()};
1414   Vector<uint8_t> buffer_vec{
1415       reinterpret_cast<uint8_t*>(buffer->backing_store()),
1416       buffer->byte_length()};
1417 
1418   // Note that {wasm::DeserializeNativeModule} will allocate. We assume the
1419   // JSArrayBuffer backing store doesn't get relocated.
1420   MaybeHandle<WasmModuleObject> maybe_module_object =
1421       wasm::DeserializeNativeModule(isolate, buffer_vec, wire_bytes_vec, {});
1422   Handle<WasmModuleObject> module_object;
1423   if (!maybe_module_object.ToHandle(&module_object)) {
1424     return ReadOnlyRoots(isolate).undefined_value();
1425   }
1426   return *module_object;
1427 }
1428 
RUNTIME_FUNCTION(Runtime_HeapObjectVerify)1429 RUNTIME_FUNCTION(Runtime_HeapObjectVerify) {
1430   HandleScope shs(isolate);
1431   DCHECK_EQ(1, args.length());
1432   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
1433 #ifdef VERIFY_HEAP
1434   object->ObjectVerify(isolate);
1435 #else
1436   CHECK(object->IsObject());
1437   if (object->IsHeapObject()) {
1438     CHECK(HeapObject::cast(*object).map().IsMap());
1439   } else {
1440     CHECK(object->IsSmi());
1441   }
1442 #endif
1443   return isolate->heap()->ToBoolean(true);
1444 }
1445 
RUNTIME_FUNCTION(Runtime_ArrayBufferMaxByteLength)1446 RUNTIME_FUNCTION(Runtime_ArrayBufferMaxByteLength) {
1447   HandleScope shs(isolate);
1448   DCHECK_EQ(0, args.length());
1449   return *isolate->factory()->NewNumber(JSArrayBuffer::kMaxByteLength);
1450 }
1451 
RUNTIME_FUNCTION(Runtime_TypedArrayMaxLength)1452 RUNTIME_FUNCTION(Runtime_TypedArrayMaxLength) {
1453   HandleScope shs(isolate);
1454   DCHECK_EQ(0, args.length());
1455   return *isolate->factory()->NewNumber(JSTypedArray::kMaxLength);
1456 }
1457 
RUNTIME_FUNCTION(Runtime_WasmGetNumberOfInstances)1458 RUNTIME_FUNCTION(Runtime_WasmGetNumberOfInstances) {
1459   SealHandleScope shs(isolate);
1460   DCHECK_EQ(1, args.length());
1461   CONVERT_ARG_HANDLE_CHECKED(WasmModuleObject, module_obj, 0);
1462   int instance_count = 0;
1463   WeakArrayList weak_instance_list =
1464       module_obj->script().wasm_weak_instance_list();
1465   for (int i = 0; i < weak_instance_list.length(); ++i) {
1466     if (weak_instance_list.Get(i)->IsWeak()) instance_count++;
1467   }
1468   return Smi::FromInt(instance_count);
1469 }
1470 
RUNTIME_FUNCTION(Runtime_WasmNumCodeSpaces)1471 RUNTIME_FUNCTION(Runtime_WasmNumCodeSpaces) {
1472   DCHECK_EQ(1, args.length());
1473   HandleScope scope(isolate);
1474   CONVERT_ARG_HANDLE_CHECKED(JSObject, argument, 0);
1475   Handle<WasmModuleObject> module;
1476   if (argument->IsWasmInstanceObject()) {
1477     module = handle(Handle<WasmInstanceObject>::cast(argument)->module_object(),
1478                     isolate);
1479   } else if (argument->IsWasmModuleObject()) {
1480     module = Handle<WasmModuleObject>::cast(argument);
1481   }
1482   size_t num_spaces =
1483       module->native_module()->GetNumberOfCodeSpacesForTesting();
1484   return *isolate->factory()->NewNumberFromSize(num_spaces);
1485 }
1486 
RUNTIME_FUNCTION(Runtime_WasmTraceMemory)1487 RUNTIME_FUNCTION(Runtime_WasmTraceMemory) {
1488   HandleScope scope(isolate);
1489   DCHECK_EQ(1, args.length());
1490   CONVERT_ARG_CHECKED(Smi, info_addr, 0);
1491 
1492   wasm::MemoryTracingInfo* info =
1493       reinterpret_cast<wasm::MemoryTracingInfo*>(info_addr.ptr());
1494 
1495   // Find the caller wasm frame.
1496   wasm::WasmCodeRefScope wasm_code_ref_scope;
1497   StackTraceFrameIterator it(isolate);
1498   DCHECK(!it.done());
1499   DCHECK(it.is_wasm());
1500   WasmFrame* frame = WasmFrame::cast(it.frame());
1501 
1502   uint8_t* mem_start = reinterpret_cast<uint8_t*>(
1503       frame->wasm_instance().memory_object().array_buffer().backing_store());
1504   int func_index = frame->function_index();
1505   int pos = frame->position();
1506   // TODO(titzer): eliminate dependency on WasmModule definition here.
1507   int func_start =
1508       frame->wasm_instance().module()->functions[func_index].code.offset();
1509   wasm::ExecutionTier tier = frame->wasm_code()->is_liftoff()
1510                                  ? wasm::ExecutionTier::kLiftoff
1511                                  : wasm::ExecutionTier::kTurbofan;
1512   wasm::TraceMemoryOperation(tier, info, func_index, pos - func_start,
1513                              mem_start);
1514   return ReadOnlyRoots(isolate).undefined_value();
1515 }
1516 
RUNTIME_FUNCTION(Runtime_WasmTierUpFunction)1517 RUNTIME_FUNCTION(Runtime_WasmTierUpFunction) {
1518   HandleScope scope(isolate);
1519   DCHECK_EQ(2, args.length());
1520   CONVERT_ARG_HANDLE_CHECKED(WasmInstanceObject, instance, 0);
1521   CONVERT_SMI_ARG_CHECKED(function_index, 1);
1522   auto* native_module = instance->module_object().native_module();
1523   isolate->wasm_engine()->CompileFunction(
1524       isolate, native_module, function_index, wasm::ExecutionTier::kTurbofan);
1525   CHECK(!native_module->compilation_state()->failed());
1526   return ReadOnlyRoots(isolate).undefined_value();
1527 }
1528 
RUNTIME_FUNCTION(Runtime_WasmTierDownModule)1529 RUNTIME_FUNCTION(Runtime_WasmTierDownModule) {
1530   HandleScope scope(isolate);
1531   DCHECK_EQ(1, args.length());
1532   CONVERT_ARG_HANDLE_CHECKED(WasmInstanceObject, instance, 0);
1533   auto* native_module = instance->module_object().native_module();
1534   native_module->SetTieringState(wasm::kTieredDown);
1535   native_module->RecompileForTiering();
1536   CHECK(!native_module->compilation_state()->failed());
1537   return ReadOnlyRoots(isolate).undefined_value();
1538 }
1539 
RUNTIME_FUNCTION(Runtime_WasmTierUpModule)1540 RUNTIME_FUNCTION(Runtime_WasmTierUpModule) {
1541   HandleScope scope(isolate);
1542   DCHECK_EQ(1, args.length());
1543   CONVERT_ARG_HANDLE_CHECKED(WasmInstanceObject, instance, 0);
1544   auto* native_module = instance->module_object().native_module();
1545   native_module->SetTieringState(wasm::kTieredUp);
1546   native_module->RecompileForTiering();
1547   CHECK(!native_module->compilation_state()->failed());
1548   return ReadOnlyRoots(isolate).undefined_value();
1549 }
1550 
RUNTIME_FUNCTION(Runtime_IsLiftoffFunction)1551 RUNTIME_FUNCTION(Runtime_IsLiftoffFunction) {
1552   HandleScope scope(isolate);
1553   DCHECK_EQ(1, args.length());
1554   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
1555   CHECK(WasmExportedFunction::IsWasmExportedFunction(*function));
1556   Handle<WasmExportedFunction> exp_fun =
1557       Handle<WasmExportedFunction>::cast(function);
1558   wasm::NativeModule* native_module =
1559       exp_fun->instance().module_object().native_module();
1560   uint32_t func_index = exp_fun->function_index();
1561   wasm::WasmCodeRefScope code_ref_scope;
1562   wasm::WasmCode* code = native_module->GetCode(func_index);
1563   return isolate->heap()->ToBoolean(code && code->is_liftoff());
1564 }
1565 
RUNTIME_FUNCTION(Runtime_CompleteInobjectSlackTracking)1566 RUNTIME_FUNCTION(Runtime_CompleteInobjectSlackTracking) {
1567   HandleScope scope(isolate);
1568   DCHECK_EQ(1, args.length());
1569 
1570   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
1571   object->map().CompleteInobjectSlackTracking(isolate);
1572 
1573   return ReadOnlyRoots(isolate).undefined_value();
1574 }
1575 
RUNTIME_FUNCTION(Runtime_FreezeWasmLazyCompilation)1576 RUNTIME_FUNCTION(Runtime_FreezeWasmLazyCompilation) {
1577   DCHECK_EQ(1, args.length());
1578   DisallowHeapAllocation no_gc;
1579   CONVERT_ARG_CHECKED(WasmInstanceObject, instance, 0);
1580 
1581   instance.module_object().native_module()->set_lazy_compile_frozen(true);
1582   return ReadOnlyRoots(isolate).undefined_value();
1583 }
1584 
RUNTIME_FUNCTION(Runtime_TurbofanStaticAssert)1585 RUNTIME_FUNCTION(Runtime_TurbofanStaticAssert) {
1586   SealHandleScope shs(isolate);
1587   // Always lowered to StaticAssert node in Turbofan, so we never get here in
1588   // compiled code.
1589   return ReadOnlyRoots(isolate).undefined_value();
1590 }
1591 
RUNTIME_FUNCTION(Runtime_IsBeingInterpreted)1592 RUNTIME_FUNCTION(Runtime_IsBeingInterpreted) {
1593   SealHandleScope shs(isolate);
1594   // Always lowered to false in Turbofan, so we never get here in compiled code.
1595   return ReadOnlyRoots(isolate).true_value();
1596 }
1597 
RUNTIME_FUNCTION(Runtime_EnableCodeLoggingForTesting)1598 RUNTIME_FUNCTION(Runtime_EnableCodeLoggingForTesting) {
1599   // The {NoopListener} currently does nothing on any callback, but reports
1600   // {true} on {is_listening_to_code_events()}. Feel free to add assertions to
1601   // any method to further test the code logging callbacks.
1602   class NoopListener final : public CodeEventListener {
1603     void CodeCreateEvent(LogEventsAndTags tag, Handle<AbstractCode> code,
1604                          const char* name) final {}
1605     void CodeCreateEvent(LogEventsAndTags tag, Handle<AbstractCode> code,
1606                          Handle<Name> name) final {}
1607     void CodeCreateEvent(LogEventsAndTags tag, Handle<AbstractCode> code,
1608                          Handle<SharedFunctionInfo> shared,
1609                          Handle<Name> script_name) final {}
1610     void CodeCreateEvent(LogEventsAndTags tag, Handle<AbstractCode> code,
1611                          Handle<SharedFunctionInfo> shared,
1612                          Handle<Name> script_name, int line, int column) final {
1613     }
1614     void CodeCreateEvent(LogEventsAndTags tag, const wasm::WasmCode* code,
1615                          wasm::WasmName name) final {}
1616 
1617     void CallbackEvent(Handle<Name> name, Address entry_point) final {}
1618     void GetterCallbackEvent(Handle<Name> name, Address entry_point) final {}
1619     void SetterCallbackEvent(Handle<Name> name, Address entry_point) final {}
1620     void RegExpCodeCreateEvent(Handle<AbstractCode> code,
1621                                Handle<String> source) final {}
1622     void CodeMoveEvent(AbstractCode from, AbstractCode to) final {}
1623     void SharedFunctionInfoMoveEvent(Address from, Address to) final {}
1624     void CodeMovingGCEvent() final {}
1625     void CodeDisableOptEvent(Handle<AbstractCode> code,
1626                              Handle<SharedFunctionInfo> shared) final {}
1627     void CodeDeoptEvent(Handle<Code> code, DeoptimizeKind kind, Address pc,
1628                         int fp_to_sp_delta, bool reuse_code) final {}
1629     void CodeDependencyChangeEvent(Handle<Code> code,
1630                                    Handle<SharedFunctionInfo> shared,
1631                                    const char* reason) final {}
1632 
1633     bool is_listening_to_code_events() final { return true; }
1634   };
1635   static base::LeakyObject<NoopListener> noop_listener;
1636   isolate->wasm_engine()->EnableCodeLogging(isolate);
1637   isolate->code_event_dispatcher()->AddListener(noop_listener.get());
1638   return ReadOnlyRoots(isolate).undefined_value();
1639 }
1640 
RUNTIME_FUNCTION(Runtime_NewRegExpWithBacktrackLimit)1641 RUNTIME_FUNCTION(Runtime_NewRegExpWithBacktrackLimit) {
1642   HandleScope scope(isolate);
1643   DCHECK_EQ(3, args.length());
1644 
1645   CONVERT_ARG_HANDLE_CHECKED(String, pattern, 0);
1646   CONVERT_ARG_HANDLE_CHECKED(String, flags_string, 1);
1647   CONVERT_UINT32_ARG_CHECKED(backtrack_limit, 2);
1648 
1649   bool success = false;
1650   JSRegExp::Flags flags =
1651       JSRegExp::FlagsFromString(isolate, flags_string, &success);
1652   CHECK(success);
1653 
1654   RETURN_RESULT_OR_FAILURE(
1655       isolate, JSRegExp::New(isolate, pattern, flags, backtrack_limit));
1656 }
1657 
1658 }  // namespace internal
1659 }  // namespace v8
1660