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