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