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 :
9 : #include "src/arguments.h"
10 : #include "src/assembler-inl.h"
11 : #include "src/compiler-dispatcher/optimizing-compile-dispatcher.h"
12 : #include "src/compiler.h"
13 : #include "src/deoptimizer.h"
14 : #include "src/frames-inl.h"
15 : #include "src/full-codegen/full-codegen.h"
16 : #include "src/isolate-inl.h"
17 : #include "src/runtime-profiler.h"
18 : #include "src/snapshot/code-serializer.h"
19 : #include "src/snapshot/natives.h"
20 : #include "src/wasm/wasm-module.h"
21 : #include "src/wasm/wasm-objects.h"
22 :
23 : namespace {
24 14 : struct WasmCompileControls {
25 : uint32_t MaxWasmBufferSize = std::numeric_limits<uint32_t>::max();
26 : bool AllowAnySizeForAsync = true;
27 : };
28 :
29 : // We need per-isolate controls, because we sometimes run tests in multiple
30 : // isolates
31 : // concurrently.
32 : // To avoid upsetting the static initializer count, we lazy initialize this.
33 : v8::base::LazyInstance<std::map<v8::Isolate*, WasmCompileControls>>::type
34 : g_PerIsolateWasmControls = LAZY_INSTANCE_INITIALIZER;
35 :
36 120 : bool IsWasmCompileAllowed(v8::Isolate* isolate, v8::Local<v8::Value> value,
37 : bool is_async) {
38 : DCHECK_GT(g_PerIsolateWasmControls.Get().count(isolate), 0);
39 120 : const WasmCompileControls& ctrls = g_PerIsolateWasmControls.Get().at(isolate);
40 225 : return (is_async && ctrls.AllowAnySizeForAsync) ||
41 105 : (v8::Local<v8::ArrayBuffer>::Cast(value)->ByteLength() <=
42 120 : ctrls.MaxWasmBufferSize);
43 : }
44 :
45 : // Use the compile controls for instantiation, too
46 83 : bool IsWasmInstantiateAllowed(v8::Isolate* isolate,
47 : v8::Local<v8::Value> module_or_bytes,
48 : bool is_async) {
49 : DCHECK_GT(g_PerIsolateWasmControls.Get().count(isolate), 0);
50 83 : const WasmCompileControls& ctrls = g_PerIsolateWasmControls.Get().at(isolate);
51 83 : if (is_async && ctrls.AllowAnySizeForAsync) return true;
52 68 : if (!module_or_bytes->IsWebAssemblyCompiledModule()) {
53 30 : return IsWasmCompileAllowed(isolate, module_or_bytes, is_async);
54 : }
55 : v8::Local<v8::WasmCompiledModule> module =
56 : v8::Local<v8::WasmCompiledModule>::Cast(module_or_bytes);
57 114 : return static_cast<uint32_t>(module->GetWasmWireBytes()->Length()) <=
58 38 : ctrls.MaxWasmBufferSize;
59 : }
60 :
61 90 : v8::Local<v8::Value> NewRangeException(v8::Isolate* isolate,
62 : const char* message) {
63 : return v8::Exception::RangeError(
64 : v8::String::NewFromOneByte(isolate,
65 : reinterpret_cast<const uint8_t*>(message),
66 : v8::NewStringType::kNormal)
67 180 : .ToLocalChecked());
68 : }
69 :
70 60 : void ThrowRangeException(v8::Isolate* isolate, const char* message) {
71 60 : isolate->ThrowException(NewRangeException(isolate, message));
72 60 : }
73 :
74 30 : void RejectPromiseWithRangeError(
75 60 : const v8::FunctionCallbackInfo<v8::Value>& args, const char* message) {
76 : v8::Isolate* isolate = args.GetIsolate();
77 30 : v8::HandleScope scope(isolate);
78 :
79 30 : v8::Local<v8::Context> context = isolate->GetCurrentContext();
80 : v8::Local<v8::Promise::Resolver> resolver;
81 60 : if (!v8::Promise::Resolver::New(context).ToLocal(&resolver)) return;
82 : v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
83 30 : return_value.Set(resolver->GetPromise());
84 :
85 30 : auto maybe = resolver->Reject(context, NewRangeException(isolate, message));
86 60 : CHECK(!maybe.IsNothing());
87 30 : return;
88 : }
89 :
90 150 : bool WasmModuleOverride(const v8::FunctionCallbackInfo<v8::Value>& args) {
91 60 : if (IsWasmCompileAllowed(args.GetIsolate(), args[0], false)) return false;
92 30 : ThrowRangeException(args.GetIsolate(), "Sync compile not allowed");
93 30 : return true;
94 : }
95 :
96 60 : bool WasmCompileOverride(const v8::FunctionCallbackInfo<v8::Value>& args) {
97 30 : if (IsWasmCompileAllowed(args.GetIsolate(), args[0], true)) return false;
98 15 : RejectPromiseWithRangeError(args, "Async compile not allowed");
99 15 : return true;
100 : }
101 :
102 136 : bool WasmInstanceOverride(const v8::FunctionCallbackInfo<v8::Value>& args) {
103 53 : if (IsWasmInstantiateAllowed(args.GetIsolate(), args[0], false)) return false;
104 30 : ThrowRangeException(args.GetIsolate(), "Sync instantiate not allowed");
105 30 : return true;
106 : }
107 :
108 60 : bool WasmInstantiateOverride(const v8::FunctionCallbackInfo<v8::Value>& args) {
109 30 : if (IsWasmInstantiateAllowed(args.GetIsolate(), args[0], true)) return false;
110 15 : RejectPromiseWithRangeError(args, "Async instantiate not allowed");
111 15 : return true;
112 : }
113 :
114 45 : bool GetWasmFromArray(const v8::FunctionCallbackInfo<v8::Value>& args) {
115 15 : CHECK(args.Length() == 1);
116 15 : v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
117 : v8::Local<v8::Value> module =
118 30 : v8::Local<v8::Object>::Cast(args[0])->Get(context, 0).ToLocalChecked();
119 :
120 : v8::Local<v8::Promise::Resolver> resolver =
121 15 : v8::Promise::Resolver::New(context).ToLocalChecked();
122 15 : args.GetReturnValue().Set(resolver->GetPromise());
123 15 : USE(resolver->Resolve(context, module));
124 15 : return true;
125 : }
126 :
127 15 : bool NoExtension(const v8::FunctionCallbackInfo<v8::Value>&) { return false; }
128 :
129 : } // namespace
130 :
131 : namespace v8 {
132 : namespace internal {
133 :
134 1456 : RUNTIME_FUNCTION(Runtime_ConstructDouble) {
135 728 : HandleScope scope(isolate);
136 : DCHECK_EQ(2, args.length());
137 1456 : CONVERT_NUMBER_CHECKED(uint32_t, hi, Uint32, args[0]);
138 1456 : CONVERT_NUMBER_CHECKED(uint32_t, lo, Uint32, args[1]);
139 728 : uint64_t result = (static_cast<uint64_t>(hi) << 32) | lo;
140 1456 : return *isolate->factory()->NewNumber(uint64_to_double(result));
141 : }
142 :
143 30 : RUNTIME_FUNCTION(Runtime_ConstructConsString) {
144 15 : HandleScope scope(isolate);
145 : DCHECK_EQ(2, args.length());
146 30 : CONVERT_ARG_HANDLE_CHECKED(String, left, 0);
147 30 : CONVERT_ARG_HANDLE_CHECKED(String, right, 1);
148 :
149 15 : CHECK(left->IsOneByteRepresentation());
150 15 : CHECK(right->IsOneByteRepresentation());
151 :
152 : const bool kIsOneByte = true;
153 30 : const int length = left->length() + right->length();
154 30 : return *isolate->factory()->NewConsString(left, right, length, kIsOneByte);
155 : }
156 :
157 179548 : RUNTIME_FUNCTION(Runtime_DeoptimizeFunction) {
158 89774 : HandleScope scope(isolate);
159 : DCHECK_EQ(1, args.length());
160 :
161 : // This function is used by fuzzers to get coverage in compiler.
162 : // Ignore calls on non-function objects to avoid runtime errors.
163 89774 : CONVERT_ARG_HANDLE_CHECKED(Object, function_object, 0);
164 89774 : if (!function_object->IsJSFunction()) {
165 0 : return isolate->heap()->undefined_value();
166 : }
167 89774 : Handle<JSFunction> function = Handle<JSFunction>::cast(function_object);
168 :
169 : // If the function is not optimized, just return.
170 89774 : if (!function->IsOptimized()) return isolate->heap()->undefined_value();
171 :
172 : // TODO(turbofan): Deoptimization is not supported yet.
173 7877 : if (function->code()->is_turbofanned() &&
174 3520 : function->shared()->asm_function()) {
175 169 : return isolate->heap()->undefined_value();
176 : }
177 :
178 4188 : Deoptimizer::DeoptimizeFunction(*function);
179 :
180 4188 : return isolate->heap()->undefined_value();
181 : }
182 :
183 :
184 3003804 : RUNTIME_FUNCTION(Runtime_DeoptimizeNow) {
185 1501902 : HandleScope scope(isolate);
186 : DCHECK_EQ(0, args.length());
187 :
188 : Handle<JSFunction> function;
189 :
190 : // Find the JavaScript function on the top of the stack.
191 3003804 : JavaScriptFrameIterator it(isolate);
192 1501902 : if (!it.done()) function = Handle<JSFunction>(it.frame()->function());
193 1501902 : if (function.is_null()) return isolate->heap()->undefined_value();
194 :
195 : // If the function is not optimized, just return.
196 1501902 : if (!function->IsOptimized()) return isolate->heap()->undefined_value();
197 :
198 : // TODO(turbofan): Deoptimization is not supported yet.
199 1230 : if (function->code()->is_turbofanned() &&
200 569 : function->shared()->asm_function()) {
201 0 : return isolate->heap()->undefined_value();
202 : }
203 :
204 661 : Deoptimizer::DeoptimizeFunction(*function);
205 :
206 1502563 : return isolate->heap()->undefined_value();
207 : }
208 :
209 :
210 28 : RUNTIME_FUNCTION(Runtime_RunningInSimulator) {
211 : SealHandleScope shs(isolate);
212 : DCHECK_EQ(0, args.length());
213 : #if defined(USE_SIMULATOR)
214 : return isolate->heap()->true_value();
215 : #else
216 14 : return isolate->heap()->false_value();
217 : #endif
218 : }
219 :
220 :
221 160 : RUNTIME_FUNCTION(Runtime_IsConcurrentRecompilationSupported) {
222 : SealHandleScope shs(isolate);
223 : DCHECK_EQ(0, args.length());
224 : return isolate->heap()->ToBoolean(
225 80 : isolate->concurrent_recompilation_enabled());
226 : }
227 :
228 240 : RUNTIME_FUNCTION(Runtime_TypeProfile) {
229 120 : HandleScope scope(isolate);
230 : DCHECK_EQ(1, args.length());
231 :
232 120 : if (!FLAG_type_profile) {
233 0 : return isolate->heap()->undefined_value();
234 : }
235 :
236 240 : CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
237 120 : if (function->has_feedback_vector()) {
238 98 : FeedbackVector* vector = function->feedback_vector();
239 98 : if (vector->metadata()->HasTypeProfileSlot()) {
240 98 : FeedbackSlot slot = vector->GetTypeProfileSlot();
241 98 : CollectTypeProfileNexus nexus(vector, slot);
242 98 : return nexus.GetTypeProfile();
243 : }
244 : }
245 44 : return *isolate->factory()->NewJSObject(isolate->object_function());
246 : }
247 :
248 527902 : RUNTIME_FUNCTION(Runtime_OptimizeFunctionOnNextCall) {
249 263889 : HandleScope scope(isolate);
250 :
251 : // This function is used by fuzzers, ignore calls with bogus arguments count.
252 263889 : if (args.length() != 1 && args.length() != 2) {
253 0 : return isolate->heap()->undefined_value();
254 : }
255 :
256 : // This function is used by fuzzers to get coverage for optimizations
257 : // in compiler. Ignore calls on non-function objects to avoid runtime errors.
258 263889 : CONVERT_ARG_HANDLE_CHECKED(Object, function_object, 0);
259 263889 : if (!function_object->IsJSFunction()) {
260 0 : return isolate->heap()->undefined_value();
261 : }
262 263889 : Handle<JSFunction> function = Handle<JSFunction>::cast(function_object);
263 :
264 : // The following condition was lifted from the DCHECK inside
265 : // JSFunction::MarkForOptimization().
266 527778 : if (!(function->shared()->allows_lazy_compilation() ||
267 46 : (function->code()->kind() == Code::FUNCTION &&
268 263935 : !function->shared()->optimization_disabled()))) {
269 46 : return isolate->heap()->undefined_value();
270 : }
271 :
272 : // If function isn't compiled, compile it now.
273 265399 : if (!function->shared()->is_compiled() &&
274 1556 : !Compiler::Compile(function, Compiler::CLEAR_EXCEPTION)) {
275 0 : return isolate->heap()->undefined_value();
276 : }
277 :
278 : // If the function is already optimized, just return.
279 263843 : if (function->IsOptimized()) return isolate->heap()->undefined_value();
280 :
281 199900 : function->MarkForOptimization();
282 :
283 199900 : if (args.length() == 2) {
284 248 : CONVERT_ARG_HANDLE_CHECKED(String, type, 1);
285 372 : if (type->IsOneByteEqualTo(STATIC_CHAR_VECTOR("concurrent")) &&
286 124 : isolate->concurrent_recompilation_enabled()) {
287 124 : function->AttemptConcurrentOptimization();
288 : }
289 : }
290 :
291 199900 : return isolate->heap()->undefined_value();
292 : }
293 :
294 84789 : RUNTIME_FUNCTION(Runtime_OptimizeOsr) {
295 34995 : HandleScope scope(isolate);
296 : DCHECK(args.length() == 0 || args.length() == 1);
297 :
298 : Handle<JSFunction> function;
299 :
300 : // The optional parameter determines the frame being targeted.
301 34995 : int stack_depth = args.length() == 1 ? args.smi_at(0) : 0;
302 :
303 : // Find the JavaScript function on the top of the stack.
304 69990 : JavaScriptFrameIterator it(isolate);
305 294 : while (!it.done() && stack_depth--) it.Advance();
306 34995 : if (!it.done()) function = Handle<JSFunction>(it.frame()->function());
307 34995 : if (function.is_null()) return isolate->heap()->undefined_value();
308 :
309 : // If the function is already optimized, just return.
310 34995 : if (function->IsOptimized()) return isolate->heap()->undefined_value();
311 :
312 : // Make the profiler arm all back edges in unoptimized code.
313 44846 : if (it.frame()->type() == StackFrame::JAVA_SCRIPT ||
314 19763 : it.frame()->type() == StackFrame::INTERPRETED) {
315 : isolate->runtime_profiler()->AttemptOnStackReplacement(
316 29598 : it.frame(), AbstractCode::kMaxLoopNestingMarker);
317 : }
318 :
319 60078 : return isolate->heap()->undefined_value();
320 : }
321 :
322 :
323 4336 : RUNTIME_FUNCTION(Runtime_NeverOptimizeFunction) {
324 2168 : HandleScope scope(isolate);
325 : DCHECK_EQ(1, args.length());
326 4336 : CONVERT_ARG_CHECKED(JSFunction, function, 0);
327 : function->shared()->set_disable_optimization_reason(
328 2168 : kOptimizationDisabledForTest);
329 2168 : function->shared()->set_optimization_disabled(true);
330 2168 : return isolate->heap()->undefined_value();
331 : }
332 :
333 13806 : RUNTIME_FUNCTION(Runtime_GetOptimizationStatus) {
334 4592 : HandleScope scope(isolate);
335 : DCHECK(args.length() == 1 || args.length() == 2);
336 : int status = 0;
337 4592 : if (!isolate->use_crankshaft()) {
338 : status |= static_cast<int>(OptimizationStatus::kNeverOptimize);
339 : }
340 4592 : if (FLAG_always_opt || FLAG_prepare_always_opt) {
341 2242 : status |= static_cast<int>(OptimizationStatus::kAlwaysOptimize);
342 : }
343 4592 : if (FLAG_deopt_every_n_times) {
344 0 : status |= static_cast<int>(OptimizationStatus::kMaybeDeopted);
345 : }
346 :
347 : // This function is used by fuzzers to get coverage for optimizations
348 : // in compiler. Ignore calls on non-function objects to avoid runtime errors.
349 4592 : CONVERT_ARG_HANDLE_CHECKED(Object, function_object, 0);
350 4592 : if (!function_object->IsJSFunction()) {
351 14 : return Smi::FromInt(status);
352 : }
353 4578 : Handle<JSFunction> function = Handle<JSFunction>::cast(function_object);
354 4578 : status |= static_cast<int>(OptimizationStatus::kIsFunction);
355 :
356 : bool sync_with_compiler_thread = true;
357 4578 : if (args.length() == 2) {
358 4272 : CONVERT_ARG_HANDLE_CHECKED(Object, sync_object, 1);
359 4272 : if (!sync_object->IsString()) return isolate->heap()->undefined_value();
360 4272 : Handle<String> sync = Handle<String>::cast(sync_object);
361 8544 : if (sync->IsOneByteEqualTo(STATIC_CHAR_VECTOR("no sync"))) {
362 : sync_with_compiler_thread = false;
363 : }
364 : }
365 :
366 4578 : if (isolate->concurrent_recompilation_enabled() &&
367 : sync_with_compiler_thread) {
368 4270 : while (function->IsInOptimizationQueue()) {
369 44 : isolate->optimizing_compile_dispatcher()->InstallOptimizedFunctions();
370 44 : base::OS::Sleep(base::TimeDelta::FromMilliseconds(50));
371 : }
372 : }
373 4578 : if (function->IsOptimized()) {
374 3912 : status |= static_cast<int>(OptimizationStatus::kOptimized);
375 3912 : if (function->code()->is_turbofanned()) {
376 2437 : status |= static_cast<int>(OptimizationStatus::kTurboFanned);
377 : }
378 : }
379 4578 : if (function->IsInterpreted()) {
380 386 : status |= static_cast<int>(OptimizationStatus::kInterpreted);
381 : }
382 4578 : return Smi::FromInt(status);
383 : }
384 :
385 :
386 146 : RUNTIME_FUNCTION(Runtime_UnblockConcurrentRecompilation) {
387 : DCHECK_EQ(0, args.length());
388 146 : if (FLAG_block_concurrent_recompilation &&
389 73 : isolate->concurrent_recompilation_enabled()) {
390 58 : isolate->optimizing_compile_dispatcher()->Unblock();
391 : }
392 73 : return isolate->heap()->undefined_value();
393 : }
394 :
395 :
396 334416 : RUNTIME_FUNCTION(Runtime_GetOptimizationCount) {
397 167208 : HandleScope scope(isolate);
398 : DCHECK_EQ(1, args.length());
399 334416 : CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
400 167208 : return Smi::FromInt(function->shared()->opt_count());
401 : }
402 :
403 182 : RUNTIME_FUNCTION(Runtime_GetDeoptCount) {
404 91 : HandleScope scope(isolate);
405 : DCHECK_EQ(1, args.length());
406 182 : CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
407 91 : return Smi::FromInt(function->shared()->deopt_count());
408 : }
409 :
410 0 : static void ReturnThis(const v8::FunctionCallbackInfo<v8::Value>& args) {
411 : args.GetReturnValue().Set(args.This());
412 0 : }
413 :
414 390 : RUNTIME_FUNCTION(Runtime_GetUndetectable) {
415 195 : HandleScope scope(isolate);
416 : DCHECK_EQ(0, args.length());
417 : v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
418 :
419 195 : Local<v8::ObjectTemplate> desc = v8::ObjectTemplate::New(v8_isolate);
420 195 : desc->MarkAsUndetectable();
421 195 : desc->SetCallAsFunctionHandler(ReturnThis);
422 : Local<v8::Object> obj;
423 390 : if (!desc->NewInstance(v8_isolate->GetCurrentContext()).ToLocal(&obj)) {
424 : return nullptr;
425 : }
426 390 : return *Utils::OpenHandle(*obj);
427 : }
428 :
429 300 : static void call_as_function(const v8::FunctionCallbackInfo<v8::Value>& args) {
430 : double v1 = args[0]
431 150 : ->NumberValue(v8::Isolate::GetCurrent()->GetCurrentContext())
432 300 : .ToChecked();
433 : double v2 = args[1]
434 150 : ->NumberValue(v8::Isolate::GetCurrent()->GetCurrentContext())
435 300 : .ToChecked();
436 : args.GetReturnValue().Set(
437 150 : v8::Number::New(v8::Isolate::GetCurrent(), v1 - v2));
438 150 : }
439 :
440 : // Returns a callable object. The object returns the difference of its two
441 : // parameters when it is called.
442 30 : RUNTIME_FUNCTION(Runtime_GetCallable) {
443 15 : HandleScope scope(isolate);
444 : DCHECK_EQ(0, args.length());
445 : v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
446 15 : Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(v8_isolate);
447 15 : Local<ObjectTemplate> instance_template = t->InstanceTemplate();
448 15 : instance_template->SetCallAsFunctionHandler(call_as_function);
449 15 : v8_isolate->GetCurrentContext();
450 : Local<v8::Object> instance =
451 15 : t->GetFunction(v8_isolate->GetCurrentContext())
452 15 : .ToLocalChecked()
453 15 : ->NewInstance(v8_isolate->GetCurrentContext())
454 15 : .ToLocalChecked();
455 30 : return *Utils::OpenHandle(*instance);
456 : }
457 :
458 169936 : RUNTIME_FUNCTION(Runtime_ClearFunctionFeedback) {
459 84968 : HandleScope scope(isolate);
460 : DCHECK_EQ(1, args.length());
461 169936 : CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
462 84968 : function->ClearTypeFeedbackInfo();
463 84968 : Code* unoptimized = function->shared()->code();
464 84968 : if (unoptimized->kind() == Code::FUNCTION) {
465 34078 : unoptimized->ClearInlineCaches();
466 : }
467 84968 : return isolate->heap()->undefined_value();
468 : }
469 :
470 30 : RUNTIME_FUNCTION(Runtime_SetWasmCompileFromPromiseOverload) {
471 15 : isolate->set_wasm_compile_callback(GetWasmFromArray);
472 15 : return isolate->heap()->undefined_value();
473 : }
474 :
475 30 : RUNTIME_FUNCTION(Runtime_ResetWasmOverloads) {
476 15 : isolate->set_wasm_compile_callback(NoExtension);
477 15 : return isolate->heap()->undefined_value();
478 : }
479 :
480 30 : RUNTIME_FUNCTION(Runtime_CheckWasmWrapperElision) {
481 : // This only supports the case where the function being exported
482 : // calls an intermediate function, and the intermediate function
483 : // calls exactly one imported function
484 15 : HandleScope scope(isolate);
485 15 : CHECK(args.length() == 2);
486 : // It takes two parameters, the first one is the JSFunction,
487 : // The second one is the type
488 30 : CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
489 : // If type is 0, it means that it is supposed to be a direct call into a WASM
490 : // function
491 : // If type is 1, it means that it is supposed to have wrappers
492 30 : CONVERT_ARG_HANDLE_CHECKED(Smi, type, 1);
493 15 : Handle<Code> export_code = handle(function->code());
494 15 : CHECK(export_code->kind() == Code::JS_TO_WASM_FUNCTION);
495 15 : int const mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET);
496 : // check the type of the $export_fct
497 : Handle<Code> export_fct;
498 : int count = 0;
499 62 : for (RelocIterator it(*export_code, mask); !it.done(); it.next()) {
500 47 : RelocInfo* rinfo = it.rinfo();
501 : Address target_address = rinfo->target_address();
502 47 : Code* target = Code::GetCodeFromTargetAddress(target_address);
503 47 : if (target->kind() == Code::WASM_FUNCTION) {
504 15 : ++count;
505 : export_fct = handle(target);
506 : }
507 : }
508 15 : CHECK(count == 1);
509 : // check the type of the intermediate_fct
510 : Handle<Code> intermediate_fct;
511 : count = 0;
512 45 : for (RelocIterator it(*export_fct, mask); !it.done(); it.next()) {
513 30 : RelocInfo* rinfo = it.rinfo();
514 : Address target_address = rinfo->target_address();
515 30 : Code* target = Code::GetCodeFromTargetAddress(target_address);
516 30 : if (target->kind() == Code::WASM_FUNCTION) {
517 15 : ++count;
518 : intermediate_fct = handle(target);
519 : }
520 : }
521 15 : CHECK(count == 1);
522 : // check the type of the imported exported function, it should be also a WASM
523 : // function in our case
524 : Handle<Code> imported_fct;
525 15 : CHECK(type->value() == 0 || type->value() == 1);
526 :
527 : Code::Kind target_kind =
528 15 : type->value() == 0 ? Code::WASM_FUNCTION : Code::WASM_TO_JS_FUNCTION;
529 : count = 0;
530 45 : for (RelocIterator it(*intermediate_fct, mask); !it.done(); it.next()) {
531 30 : RelocInfo* rinfo = it.rinfo();
532 : Address target_address = rinfo->target_address();
533 30 : Code* target = Code::GetCodeFromTargetAddress(target_address);
534 30 : if (target->kind() == target_kind) {
535 15 : ++count;
536 : imported_fct = handle(target);
537 : }
538 : }
539 15 : CHECK_LE(count, 1);
540 15 : return isolate->heap()->ToBoolean(count == 1);
541 : }
542 :
543 240 : RUNTIME_FUNCTION(Runtime_SetWasmCompileControls) {
544 120 : HandleScope scope(isolate);
545 120 : v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
546 120 : CHECK(args.length() == 2);
547 240 : CONVERT_ARG_HANDLE_CHECKED(Smi, block_size, 0);
548 240 : CONVERT_BOOLEAN_ARG_CHECKED(allow_async, 1);
549 120 : WasmCompileControls& ctrl = (*g_PerIsolateWasmControls.Pointer())[v8_isolate];
550 120 : ctrl.AllowAnySizeForAsync = allow_async;
551 120 : ctrl.MaxWasmBufferSize = static_cast<uint32_t>(block_size->value());
552 120 : v8_isolate->SetWasmModuleCallback(WasmModuleOverride);
553 120 : v8_isolate->SetWasmCompileCallback(WasmCompileOverride);
554 120 : return isolate->heap()->undefined_value();
555 : }
556 :
557 30 : RUNTIME_FUNCTION(Runtime_SetWasmInstantiateControls) {
558 15 : HandleScope scope(isolate);
559 : v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
560 15 : CHECK(args.length() == 0);
561 15 : v8_isolate->SetWasmInstanceCallback(WasmInstanceOverride);
562 15 : v8_isolate->SetWasmInstantiateCallback(WasmInstantiateOverride);
563 15 : return isolate->heap()->undefined_value();
564 : }
565 :
566 178 : RUNTIME_FUNCTION(Runtime_NotifyContextDisposed) {
567 89 : HandleScope scope(isolate);
568 : DCHECK_EQ(0, args.length());
569 89 : isolate->heap()->NotifyContextDisposed(true);
570 89 : return isolate->heap()->undefined_value();
571 : }
572 :
573 :
574 974 : RUNTIME_FUNCTION(Runtime_SetAllocationTimeout) {
575 : SealHandleScope shs(isolate);
576 : DCHECK(args.length() == 2 || args.length() == 3);
577 : #ifdef DEBUG
578 : CONVERT_INT32_ARG_CHECKED(interval, 0);
579 : CONVERT_INT32_ARG_CHECKED(timeout, 1);
580 : isolate->heap()->set_allocation_timeout(timeout);
581 : FLAG_gc_interval = interval;
582 : if (args.length() == 3) {
583 : // Enable/disable inline allocation if requested.
584 : CONVERT_BOOLEAN_ARG_CHECKED(inline_allocation, 2);
585 : if (inline_allocation) {
586 : isolate->heap()->EnableInlineAllocation();
587 : } else {
588 : isolate->heap()->DisableInlineAllocation();
589 : }
590 : }
591 : #endif
592 487 : return isolate->heap()->undefined_value();
593 : }
594 :
595 :
596 2444 : RUNTIME_FUNCTION(Runtime_DebugPrint) {
597 : SealHandleScope shs(isolate);
598 : DCHECK_EQ(1, args.length());
599 :
600 2444 : OFStream os(stdout);
601 : #ifdef DEBUG
602 : if (args[0]->IsString() && isolate->context() != nullptr) {
603 : // If we have a string, assume it's a code "marker"
604 : // and print some interesting cpu debugging info.
605 : args[0]->Print(os);
606 : JavaScriptFrameIterator it(isolate);
607 : JavaScriptFrame* frame = it.frame();
608 : os << "fp = " << static_cast<void*>(frame->fp())
609 : << ", sp = " << static_cast<void*>(frame->sp())
610 : << ", caller_sp = " << static_cast<void*>(frame->caller_sp()) << ": ";
611 : } else {
612 : os << "DebugPrint: ";
613 : args[0]->Print(os);
614 : }
615 : if (args[0]->IsHeapObject()) {
616 : HeapObject::cast(args[0])->map()->Print(os);
617 : }
618 : #else
619 : // ShortPrint is available in release mode. Print is not.
620 1222 : os << Brief(args[0]);
621 : #endif
622 1222 : os << std::endl;
623 :
624 1222 : return args[0]; // return TOS
625 : }
626 :
627 :
628 28 : RUNTIME_FUNCTION(Runtime_DebugTrace) {
629 : SealHandleScope shs(isolate);
630 : DCHECK_EQ(0, args.length());
631 14 : isolate->PrintStack(stdout);
632 14 : return isolate->heap()->undefined_value();
633 : }
634 :
635 :
636 : // This will not allocate (flatten the string), but it may run
637 : // very slowly for very deeply nested ConsStrings. For debugging use only.
638 324 : RUNTIME_FUNCTION(Runtime_GlobalPrint) {
639 : SealHandleScope shs(isolate);
640 : DCHECK_EQ(1, args.length());
641 :
642 324 : CONVERT_ARG_CHECKED(String, string, 0);
643 162 : StringCharacterStream stream(string);
644 702 : while (stream.HasMore()) {
645 540 : uint16_t character = stream.GetNext();
646 540 : PrintF("%c", character);
647 : }
648 : return string;
649 : }
650 :
651 :
652 0 : RUNTIME_FUNCTION(Runtime_SystemBreak) {
653 : // The code below doesn't create handles, but when breaking here in GDB
654 : // having a handle scope might be useful.
655 0 : HandleScope scope(isolate);
656 : DCHECK_EQ(0, args.length());
657 0 : base::OS::DebugBreak();
658 0 : return isolate->heap()->undefined_value();
659 : }
660 :
661 :
662 : // Sets a v8 flag.
663 150 : RUNTIME_FUNCTION(Runtime_SetFlags) {
664 : SealHandleScope shs(isolate);
665 : DCHECK_EQ(1, args.length());
666 150 : CONVERT_ARG_CHECKED(String, arg, 0);
667 : std::unique_ptr<char[]> flags =
668 150 : arg->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
669 75 : FlagList::SetFlagsFromString(flags.get(), StrLength(flags.get()));
670 75 : return isolate->heap()->undefined_value();
671 : }
672 :
673 :
674 0 : RUNTIME_FUNCTION(Runtime_Abort) {
675 : SealHandleScope shs(isolate);
676 : DCHECK_EQ(1, args.length());
677 0 : CONVERT_SMI_ARG_CHECKED(message_id, 0);
678 : const char* message =
679 0 : GetBailoutReason(static_cast<BailoutReason>(message_id));
680 0 : base::OS::PrintError("abort: %s\n", message);
681 0 : isolate->PrintStack(stderr);
682 0 : base::OS::Abort();
683 : UNREACHABLE();
684 : return NULL;
685 : }
686 :
687 :
688 0 : RUNTIME_FUNCTION(Runtime_AbortJS) {
689 0 : HandleScope scope(isolate);
690 : DCHECK_EQ(1, args.length());
691 0 : CONVERT_ARG_HANDLE_CHECKED(String, message, 0);
692 0 : base::OS::PrintError("abort: %s\n", message->ToCString().get());
693 0 : isolate->PrintStack(stderr);
694 0 : base::OS::Abort();
695 : UNREACHABLE();
696 : return NULL;
697 : }
698 :
699 :
700 12 : RUNTIME_FUNCTION(Runtime_NativeScriptsCount) {
701 : DCHECK_EQ(0, args.length());
702 6 : return Smi::FromInt(Natives::GetBuiltinsCount());
703 : }
704 :
705 : // TODO(5510): remove this.
706 0 : RUNTIME_FUNCTION(Runtime_GetV8Version) {
707 0 : HandleScope scope(isolate);
708 : DCHECK_EQ(0, args.length());
709 :
710 0 : const char* version_string = v8::V8::GetVersion();
711 :
712 0 : return *isolate->factory()->NewStringFromAsciiChecked(version_string);
713 : }
714 :
715 :
716 30 : RUNTIME_FUNCTION(Runtime_DisassembleFunction) {
717 15 : HandleScope scope(isolate);
718 : #ifdef DEBUG
719 : DCHECK_EQ(1, args.length());
720 : // Get the function and make sure it is compiled.
721 : CONVERT_ARG_HANDLE_CHECKED(JSFunction, func, 0);
722 : if (!Compiler::Compile(func, Compiler::KEEP_EXCEPTION)) {
723 : return isolate->heap()->exception();
724 : }
725 : OFStream os(stdout);
726 : func->code()->Print(os);
727 : os << std::endl;
728 : #endif // DEBUG
729 15 : return isolate->heap()->undefined_value();
730 : }
731 :
732 : namespace {
733 :
734 0 : int StackSize(Isolate* isolate) {
735 : int n = 0;
736 0 : for (JavaScriptFrameIterator it(isolate); !it.done(); it.Advance()) n++;
737 0 : return n;
738 : }
739 :
740 0 : void PrintIndentation(Isolate* isolate) {
741 : const int nmax = 80;
742 0 : int n = StackSize(isolate);
743 0 : if (n <= nmax) {
744 0 : PrintF("%4d:%*s", n, n, "");
745 : } else {
746 0 : PrintF("%4d:%*s", n, nmax, "...");
747 : }
748 0 : }
749 :
750 : } // namespace
751 :
752 0 : RUNTIME_FUNCTION(Runtime_TraceEnter) {
753 : SealHandleScope shs(isolate);
754 : DCHECK_EQ(0, args.length());
755 0 : PrintIndentation(isolate);
756 0 : JavaScriptFrame::PrintTop(isolate, stdout, true, false);
757 0 : PrintF(" {\n");
758 0 : return isolate->heap()->undefined_value();
759 : }
760 :
761 :
762 0 : RUNTIME_FUNCTION(Runtime_TraceExit) {
763 : SealHandleScope shs(isolate);
764 : DCHECK_EQ(1, args.length());
765 0 : CONVERT_ARG_CHECKED(Object, obj, 0);
766 0 : PrintIndentation(isolate);
767 0 : PrintF("} -> ");
768 0 : obj->ShortPrint();
769 0 : PrintF("\n");
770 : return obj; // return TOS
771 : }
772 :
773 0 : RUNTIME_FUNCTION(Runtime_TraceTailCall) {
774 : SealHandleScope shs(isolate);
775 : DCHECK_EQ(0, args.length());
776 0 : PrintIndentation(isolate);
777 0 : PrintF("} -> tail call ->\n");
778 0 : return isolate->heap()->undefined_value();
779 : }
780 :
781 0 : RUNTIME_FUNCTION(Runtime_GetExceptionDetails) {
782 0 : HandleScope shs(isolate);
783 : DCHECK_EQ(1, args.length());
784 0 : CONVERT_ARG_HANDLE_CHECKED(JSObject, exception_obj, 0);
785 :
786 0 : Factory* factory = isolate->factory();
787 : Handle<JSMessageObject> message_obj =
788 0 : isolate->CreateMessage(exception_obj, nullptr);
789 :
790 0 : Handle<JSObject> message = factory->NewJSObject(isolate->object_function());
791 :
792 : Handle<String> key;
793 : Handle<Object> value;
794 :
795 0 : key = factory->NewStringFromAsciiChecked("start_pos");
796 0 : value = handle(Smi::FromInt(message_obj->start_position()), isolate);
797 0 : JSObject::SetProperty(message, key, value, STRICT).Assert();
798 :
799 0 : key = factory->NewStringFromAsciiChecked("end_pos");
800 0 : value = handle(Smi::FromInt(message_obj->end_position()), isolate);
801 0 : JSObject::SetProperty(message, key, value, STRICT).Assert();
802 :
803 0 : return *message;
804 : }
805 :
806 27672 : RUNTIME_FUNCTION(Runtime_HaveSameMap) {
807 : SealHandleScope shs(isolate);
808 : DCHECK_EQ(2, args.length());
809 27672 : CONVERT_ARG_CHECKED(JSObject, obj1, 0);
810 27672 : CONVERT_ARG_CHECKED(JSObject, obj2, 1);
811 13836 : return isolate->heap()->ToBoolean(obj1->map() == obj2->map());
812 : }
813 :
814 :
815 0 : RUNTIME_FUNCTION(Runtime_InNewSpace) {
816 : SealHandleScope shs(isolate);
817 : DCHECK_EQ(1, args.length());
818 0 : CONVERT_ARG_CHECKED(Object, obj, 0);
819 0 : return isolate->heap()->ToBoolean(isolate->heap()->InNewSpace(obj));
820 : }
821 :
822 13832 : RUNTIME_FUNCTION(Runtime_IsAsmWasmCode) {
823 : SealHandleScope shs(isolate);
824 : DCHECK_EQ(1, args.length());
825 13832 : CONVERT_ARG_CHECKED(JSFunction, function, 0);
826 6916 : if (!function->shared()->HasAsmWasmData()) {
827 : // Doesn't have wasm data.
828 1393 : return isolate->heap()->false_value();
829 : }
830 11046 : if (function->shared()->code() !=
831 5523 : isolate->builtins()->builtin(Builtins::kInstantiateAsmJs)) {
832 : // Hasn't been compiled yet.
833 0 : return isolate->heap()->false_value();
834 : }
835 5523 : return isolate->heap()->true_value();
836 : }
837 :
838 : namespace {
839 0 : bool DisallowCodegenFromStringsCallback(v8::Local<v8::Context> context) {
840 0 : return false;
841 : }
842 : }
843 :
844 30 : RUNTIME_FUNCTION(Runtime_DisallowCodegenFromStrings) {
845 : SealHandleScope shs(isolate);
846 : DCHECK_EQ(0, args.length());
847 : v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
848 : v8_isolate->SetAllowCodeGenerationFromStringsCallback(
849 15 : DisallowCodegenFromStringsCallback);
850 15 : return isolate->heap()->undefined_value();
851 : }
852 :
853 120 : RUNTIME_FUNCTION(Runtime_IsWasmCode) {
854 : SealHandleScope shs(isolate);
855 : DCHECK_EQ(1, args.length());
856 120 : CONVERT_ARG_CHECKED(JSFunction, function, 0);
857 60 : bool is_js_to_wasm = function->code()->kind() == Code::JS_TO_WASM_FUNCTION;
858 60 : return isolate->heap()->ToBoolean(is_js_to_wasm);
859 : }
860 :
861 : #define ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(Name) \
862 : RUNTIME_FUNCTION(Runtime_Has##Name) { \
863 : CONVERT_ARG_CHECKED(JSObject, obj, 0); \
864 : return isolate->heap()->ToBoolean(obj->Has##Name()); \
865 : }
866 :
867 3007342 : ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastSmiElements)
868 4529958 : ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastObjectElements)
869 4500000 : ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastSmiOrObjectElements)
870 4510274 : ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastDoubleElements)
871 16501492 : ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastHoleyElements)
872 704 : ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(DictionaryElements)
873 206 : ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(SloppyArgumentsElements)
874 0 : ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FixedTypedArrayElements)
875 : // Properties test sitting with elements tests - not fooling anyone.
876 17362 : ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastProperties)
877 :
878 : #undef ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION
879 :
880 :
881 : #define FIXED_TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION(Type, type, TYPE, ctype, s) \
882 : RUNTIME_FUNCTION(Runtime_HasFixed##Type##Elements) { \
883 : CONVERT_ARG_CHECKED(JSObject, obj, 0); \
884 : return isolate->heap()->ToBoolean(obj->HasFixed##Type##Elements()); \
885 : }
886 :
887 1260 : TYPED_ARRAYS(FIXED_TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION)
888 :
889 : #undef FIXED_TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION
890 :
891 :
892 224 : RUNTIME_FUNCTION(Runtime_SpeciesProtector) {
893 : SealHandleScope shs(isolate);
894 : DCHECK_EQ(0, args.length());
895 112 : return isolate->heap()->ToBoolean(isolate->IsArraySpeciesLookupChainIntact());
896 : }
897 :
898 : #define CONVERT_ARG_HANDLE_CHECKED_2(Type, name, index) \
899 : CHECK(Type::Is##Type(args[index])); \
900 : Handle<Type> name = args.at<Type>(index);
901 :
902 : // Take a compiled wasm module, serialize it and copy the buffer into an array
903 : // buffer, which is then returned.
904 270 : RUNTIME_FUNCTION(Runtime_SerializeWasmModule) {
905 90 : HandleScope shs(isolate);
906 : DCHECK_EQ(1, args.length());
907 90 : CONVERT_ARG_HANDLE_CHECKED_2(WasmModuleObject, module_obj, 0);
908 :
909 90 : Handle<WasmCompiledModule> orig(module_obj->compiled_module());
910 : std::unique_ptr<ScriptData> data =
911 180 : WasmCompiledModuleSerializer::SerializeWasmModule(isolate, orig);
912 90 : void* buff = isolate->array_buffer_allocator()->Allocate(data->length());
913 90 : Handle<JSArrayBuffer> ret = isolate->factory()->NewJSArrayBuffer();
914 90 : JSArrayBuffer::Setup(ret, isolate, false, buff, data->length());
915 90 : memcpy(buff, data->data(), data->length());
916 90 : return *ret;
917 : }
918 :
919 : // Take an array buffer and attempt to reconstruct a compiled wasm module.
920 : // Return undefined if unsuccessful.
921 210 : RUNTIME_FUNCTION(Runtime_DeserializeWasmModule) {
922 105 : HandleScope shs(isolate);
923 : DCHECK_EQ(2, args.length());
924 210 : CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, buffer, 0);
925 210 : CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, wire_bytes, 1);
926 :
927 105 : Address mem_start = static_cast<Address>(buffer->backing_store());
928 105 : int mem_size = static_cast<int>(buffer->byte_length()->Number());
929 :
930 : // DeserializeWasmModule will allocate. We assume JSArrayBuffer doesn't
931 : // get relocated.
932 210 : ScriptData sc(mem_start, mem_size);
933 105 : bool already_external = wire_bytes->is_external();
934 105 : if (!already_external) {
935 105 : wire_bytes->set_is_external(true);
936 105 : isolate->heap()->UnregisterArrayBuffer(*wire_bytes);
937 : }
938 : MaybeHandle<FixedArray> maybe_compiled_module =
939 : WasmCompiledModuleSerializer::DeserializeWasmModule(
940 : isolate, &sc,
941 : Vector<const uint8_t>(
942 105 : reinterpret_cast<uint8_t*>(wire_bytes->backing_store()),
943 210 : static_cast<int>(wire_bytes->byte_length()->Number())));
944 105 : if (!already_external) {
945 105 : wire_bytes->set_is_external(false);
946 105 : isolate->heap()->RegisterNewArrayBuffer(*wire_bytes);
947 : }
948 : Handle<FixedArray> compiled_module;
949 105 : if (!maybe_compiled_module.ToHandle(&compiled_module)) {
950 15 : return isolate->heap()->undefined_value();
951 : }
952 : return *WasmModuleObject::New(
953 285 : isolate, Handle<WasmCompiledModule>::cast(compiled_module));
954 : }
955 :
956 180 : RUNTIME_FUNCTION(Runtime_ValidateWasmInstancesChain) {
957 90 : HandleScope shs(isolate);
958 : DCHECK_EQ(2, args.length());
959 90 : CONVERT_ARG_HANDLE_CHECKED_2(WasmModuleObject, module_obj, 0);
960 180 : CONVERT_ARG_HANDLE_CHECKED(Smi, instance_count, 1);
961 : wasm::testing::ValidateInstancesChain(isolate, module_obj,
962 90 : instance_count->value());
963 90 : return isolate->heap()->ToBoolean(true);
964 : }
965 :
966 60 : RUNTIME_FUNCTION(Runtime_ValidateWasmModuleState) {
967 30 : HandleScope shs(isolate);
968 : DCHECK_EQ(1, args.length());
969 30 : CONVERT_ARG_HANDLE_CHECKED_2(WasmModuleObject, module_obj, 0);
970 30 : wasm::testing::ValidateModuleState(isolate, module_obj);
971 30 : return isolate->heap()->ToBoolean(true);
972 : }
973 :
974 30 : RUNTIME_FUNCTION(Runtime_ValidateWasmOrphanedInstance) {
975 15 : HandleScope shs(isolate);
976 : DCHECK_EQ(1, args.length());
977 15 : CONVERT_ARG_HANDLE_CHECKED_2(WasmInstanceObject, instance, 0);
978 15 : wasm::testing::ValidateOrphanedInstance(isolate, instance);
979 15 : return isolate->heap()->ToBoolean(true);
980 : }
981 :
982 2850 : RUNTIME_FUNCTION(Runtime_HeapObjectVerify) {
983 1425 : HandleScope shs(isolate);
984 : DCHECK_EQ(1, args.length());
985 1425 : CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
986 : #ifdef VERIFY_HEAP
987 : object->ObjectVerify();
988 : #else
989 1425 : CHECK(object->IsObject());
990 1425 : if (object->IsHeapObject()) {
991 2760 : CHECK(HeapObject::cast(*object)->map()->IsMap());
992 : } else {
993 45 : CHECK(object->IsSmi());
994 : }
995 : #endif
996 1425 : return isolate->heap()->ToBoolean(true);
997 : }
998 :
999 900 : RUNTIME_FUNCTION(Runtime_WasmNumInterpretedCalls) {
1000 : DCHECK_EQ(1, args.length());
1001 450 : HandleScope scope(isolate);
1002 900 : CONVERT_ARG_HANDLE_CHECKED(JSObject, instance_obj, 0);
1003 450 : CHECK(WasmInstanceObject::IsWasmInstanceObject(*instance_obj));
1004 : Handle<WasmInstanceObject> instance =
1005 450 : Handle<WasmInstanceObject>::cast(instance_obj);
1006 450 : if (!instance->has_debug_info()) return 0;
1007 450 : uint64_t num = instance->debug_info()->NumInterpretedCalls();
1008 900 : return *isolate->factory()->NewNumberFromSize(static_cast<size_t>(num));
1009 : }
1010 :
1011 60 : RUNTIME_FUNCTION(Runtime_RedirectToWasmInterpreter) {
1012 : DCHECK_EQ(2, args.length());
1013 30 : HandleScope scope(isolate);
1014 60 : CONVERT_ARG_HANDLE_CHECKED(JSObject, instance_obj, 0);
1015 60 : CONVERT_SMI_ARG_CHECKED(function_index, 1);
1016 30 : CHECK(WasmInstanceObject::IsWasmInstanceObject(*instance_obj));
1017 : Handle<WasmInstanceObject> instance =
1018 30 : Handle<WasmInstanceObject>::cast(instance_obj);
1019 : Handle<WasmDebugInfo> debug_info =
1020 30 : WasmInstanceObject::GetOrCreateDebugInfo(instance);
1021 : WasmDebugInfo::RedirectToInterpreter(debug_info,
1022 30 : Vector<int>(&function_index, 1));
1023 30 : return isolate->heap()->undefined_value();
1024 : }
1025 :
1026 1890 : RUNTIME_FUNCTION(Runtime_IncrementWaitCount) {
1027 945 : isolate->IncrementWaitCountForTesting();
1028 945 : return isolate->heap()->undefined_value();
1029 : }
1030 :
1031 1890 : RUNTIME_FUNCTION(Runtime_DecrementWaitCount) {
1032 945 : isolate->DecrementWaitCountForTesting();
1033 945 : return isolate->heap()->undefined_value();
1034 : }
1035 :
1036 : } // namespace internal
1037 : } // namespace v8
|