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