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