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