v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
runtime-test-wasm.cc
Go to the documentation of this file.
1// Copyright 2021 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 <cinttypes>
6#include <type_traits>
7
8#include "include/v8-wasm.h"
9#include "src/base/memory.h"
14#include "src/heap/heap-inl.h"
16#include "src/objects/smi.h"
29
30namespace v8::internal {
31
32namespace {
33V8_WARN_UNUSED_RESULT Tagged<Object> CrashUnlessFuzzing(Isolate* isolate) {
34 CHECK(v8_flags.fuzzing);
35 return ReadOnlyRoots(isolate).undefined_value();
36}
37
38struct WasmCompileControls {
39 uint32_t MaxWasmBufferSize = std::numeric_limits<uint32_t>::max();
41};
42using WasmCompileControlsMap = std::map<v8::Isolate*, WasmCompileControls>;
43
44// We need per-isolate controls, because we sometimes run tests in multiple
45// isolates concurrently. Methods need to hold the accompanying mutex on access.
46// To avoid upsetting the static initializer count, we lazy initialize this.
47DEFINE_LAZY_LEAKY_OBJECT_GETTER(WasmCompileControlsMap,
48 GetPerIsolateWasmControls)
49base::LazyMutex g_PerIsolateWasmControlsMutex = LAZY_MUTEX_INITIALIZER;
50
51bool IsWasmCompileAllowed(v8::Isolate* isolate, v8::Local<v8::Value> value,
52 bool is_async) {
53 base::MutexGuard guard(g_PerIsolateWasmControlsMutex.Pointer());
54 DCHECK_GT(GetPerIsolateWasmControls()->count(isolate), 0);
55 const WasmCompileControls& ctrls = GetPerIsolateWasmControls()->at(isolate);
56 return (is_async && ctrls.AllowAnySizeForAsync) ||
57 (value->IsArrayBuffer() && value.As<v8::ArrayBuffer>()->ByteLength() <=
58 ctrls.MaxWasmBufferSize) ||
59 (value->IsArrayBufferView() &&
60 value.As<v8::ArrayBufferView>()->ByteLength() <=
61 ctrls.MaxWasmBufferSize);
62}
63
64// Use the compile controls for instantiation, too
65bool IsWasmInstantiateAllowed(v8::Isolate* isolate,
66 v8::Local<v8::Value> module_or_bytes,
67 bool is_async) {
68 base::MutexGuard guard(g_PerIsolateWasmControlsMutex.Pointer());
69 DCHECK_GT(GetPerIsolateWasmControls()->count(isolate), 0);
70 const WasmCompileControls& ctrls = GetPerIsolateWasmControls()->at(isolate);
71 if (is_async && ctrls.AllowAnySizeForAsync) return true;
72 if (!module_or_bytes->IsWasmModuleObject()) {
73 return IsWasmCompileAllowed(isolate, module_or_bytes, is_async);
74 }
77 return static_cast<uint32_t>(
78 module->GetCompiledModule().GetWireBytesRef().size()) <=
79 ctrls.MaxWasmBufferSize;
80}
81
82v8::Local<v8::Value> NewRangeException(v8::Isolate* isolate,
83 const char* message) {
86 reinterpret_cast<const uint8_t*>(message))
87 .ToLocalChecked());
88}
89
90void ThrowRangeException(v8::Isolate* isolate, const char* message) {
91 isolate->ThrowException(NewRangeException(isolate, message));
92}
93
94bool WasmModuleOverride(const v8::FunctionCallbackInfo<v8::Value>& info) {
96 if (IsWasmCompileAllowed(info.GetIsolate(), info[0], false)) return false;
97 ThrowRangeException(info.GetIsolate(), "Sync compile not allowed");
98 return true;
99}
100
101bool WasmInstanceOverride(const v8::FunctionCallbackInfo<v8::Value>& info) {
103 if (IsWasmInstantiateAllowed(info.GetIsolate(), info[0], false)) return false;
104 ThrowRangeException(info.GetIsolate(), "Sync instantiate not allowed");
105 return true;
106}
107
108} // namespace
109
110// Returns a callable object. The object returns the difference of its two
111// parameters when it is called.
112RUNTIME_FUNCTION(Runtime_SetWasmCompileControls) {
113 HandleScope scope(isolate);
114 if (args.length() != 2 || !IsSmi(args[0]) || !IsBoolean(args[1])) {
115 return CrashUnlessFuzzing(isolate);
116 }
117 v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
118 int block_size = args.smi_value_at(0);
119 bool allow_async = Cast<Boolean>(args[1])->ToBool(isolate);
120 base::MutexGuard guard(g_PerIsolateWasmControlsMutex.Pointer());
121 WasmCompileControls& ctrl = (*GetPerIsolateWasmControls())[v8_isolate];
122 ctrl.AllowAnySizeForAsync = allow_async;
123 ctrl.MaxWasmBufferSize = static_cast<uint32_t>(block_size);
124 v8_isolate->SetWasmModuleCallback(WasmModuleOverride);
125 return ReadOnlyRoots(isolate).undefined_value();
126}
127
128RUNTIME_FUNCTION(Runtime_SetWasmInstantiateControls) {
129 HandleScope scope(isolate);
130 v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
131 v8_isolate->SetWasmInstanceCallback(WasmInstanceOverride);
132 return ReadOnlyRoots(isolate).undefined_value();
133}
134
135namespace {
136
137void PrintIndentation(int stack_size) {
138 const int max_display = 80;
139 if (stack_size <= max_display) {
140 PrintF("%4d:%*s", stack_size, stack_size, "");
141 } else {
142 PrintF("%4d:%*s", stack_size, max_display, "...");
143 }
144}
145
146int WasmStackSize(Isolate* isolate) {
147 // TODO(wasm): Fix this for mixed JS/Wasm stacks with both --trace and
148 // --trace-wasm.
149 int n = 0;
150 for (DebuggableStackFrameIterator it(isolate); !it.done(); it.Advance()) {
151 if (it.is_wasm()) n++;
152 }
153 return n;
154}
155
156} // namespace
157
158RUNTIME_FUNCTION(Runtime_CountUnoptimizedWasmToJSWrapper) {
159 SealHandleScope shs(isolate);
160 if (args.length() != 1 || !IsWasmInstanceObject(args[0])) {
161 return CrashUnlessFuzzing(isolate);
162 }
166 instance_object->trusted_data(isolate);
167 Address wrapper_entry =
168 Builtins::EntryOf(Builtin::kWasmToJsWrapperAsm, isolate);
169
170 int result = 0;
171 Tagged<WasmDispatchTable> dispatch_table =
172 trusted_data->dispatch_table_for_imports();
173 int import_count = dispatch_table->length();
175 for (int i = 0; i < import_count; ++i) {
176 if (cpt->EntrypointEqualTo(dispatch_table->target(i), wrapper_entry)) {
177 ++result;
178 }
179 }
180 Tagged<ProtectedFixedArray> dispatch_tables = trusted_data->dispatch_tables();
181 int table_count = dispatch_tables->length();
182 for (int table_index = 0; table_index < table_count; ++table_index) {
183 if (dispatch_tables->get(table_index) == Smi::zero()) continue;
185 Cast<WasmDispatchTable>(dispatch_tables->get(table_index));
186 int table_size = table->length();
187 for (int entry_index = 0; entry_index < table_size; ++entry_index) {
188 WasmCodePointer target = table->target(entry_index);
189 if (target != wasm::kInvalidWasmCodePointer &&
190 cpt->EntrypointEqualTo(target, wrapper_entry))
191 ++result;
192 }
193 }
194 return Smi::FromInt(result);
195}
196
197RUNTIME_FUNCTION(Runtime_HasUnoptimizedWasmToJSWrapper) {
198 SealHandleScope shs{isolate};
199 if (args.length() != 1 || !IsJSFunction(args[0])) {
200 return CrashUnlessFuzzing(isolate);
201 }
203 Tagged<SharedFunctionInfo> sfi = function->shared();
204 if (!sfi->HasWasmFunctionData()) return isolate->heap()->ToBoolean(false);
205 Tagged<WasmFunctionData> func_data = sfi->wasm_function_data();
206 WasmCodePointer call_target = func_data->internal()->call_target();
207
208 Address wrapper_entry =
209 Builtins::EntryOf(Builtin::kWasmToJsWrapperAsm, isolate);
210 return isolate->heap()->ToBoolean(
211 wasm::GetProcessWideWasmCodePointerTable()->EntrypointEqualTo(
212 call_target, wrapper_entry));
213}
214
215RUNTIME_FUNCTION(Runtime_HasUnoptimizedJSToJSWrapper) {
216 HandleScope shs(isolate);
217 if (args.length() != 1) {
218 return CrashUnlessFuzzing(isolate);
219 }
220 Handle<Object> param = args.at<Object>(0);
222 return isolate->heap()->ToBoolean(false);
223 }
224 auto wasm_js_function = Cast<WasmJSFunction>(param);
226 wasm_js_function->shared()->wasm_js_function_data(), isolate);
227
228 DirectHandle<JSFunction> external_function =
230 direct_handle(function_data->internal(), isolate));
231 DirectHandle<Code> external_function_code(external_function->code(isolate),
232 isolate);
233 DirectHandle<Code> function_data_code(function_data->wrapper_code(isolate),
234 isolate);
235 Tagged<Code> wrapper = isolate->builtins()->code(Builtin::kJSToJSWrapper);
236 // TODO(saelo): we have to use full pointer comparison here until all Code
237 // objects are located in trusted space. Currently, builtin Code objects are
238 // still inside the main pointer compression cage.
239 static_assert(!kAllCodeObjectsLiveInTrustedSpace);
240 if (!wrapper.SafeEquals(*external_function_code)) {
241 return isolate->heap()->ToBoolean(false);
242 }
243 if (wrapper != *function_data_code) {
244 return isolate->heap()->ToBoolean(false);
245 }
246
247 return isolate->heap()->ToBoolean(true);
248}
249
250RUNTIME_FUNCTION(Runtime_WasmTraceEnter) {
251 HandleScope shs(isolate);
252 // This isn't exposed to fuzzers so doesn't need to handle invalid arguments.
253 DCHECK_EQ(0, args.length());
254 PrintIndentation(WasmStackSize(isolate));
255
256 // Find the caller wasm frame.
257 wasm::WasmCodeRefScope wasm_code_ref_scope;
259 DCHECK(!it.done());
260 DCHECK(it.is_wasm());
261#if V8_ENABLE_DRUMBRAKE
262 DCHECK(!it.is_wasm_interpreter_entry());
263#endif // V8_ENABLE_DRUMBRAKE
264 WasmFrame* frame = WasmFrame::cast(it.frame());
265
266 // Find the function name.
267 int func_index = frame->function_index();
268 const wasm::WasmModule* module = frame->trusted_instance_data()->module();
269 wasm::ModuleWireBytes wire_bytes =
270 wasm::ModuleWireBytes(frame->native_module()->wire_bytes());
271 wasm::WireBytesRef name_ref =
272 module->lazily_generated_names.LookupFunctionName(wire_bytes, func_index);
273 wasm::WasmName name = wire_bytes.GetNameOrNull(name_ref);
274
275 wasm::WasmCode* code = frame->wasm_code();
276 PrintF(code->is_liftoff() ? "~" : "*");
277
278 if (name.empty()) {
279 PrintF("wasm-function[%d] {\n", func_index);
280 } else {
281 PrintF("wasm-function[%d] \"%.*s\" {\n", func_index, name.length(),
282 name.begin());
283 }
284
285 return ReadOnlyRoots(isolate).undefined_value();
286}
287
288RUNTIME_FUNCTION(Runtime_WasmTraceExit) {
289 HandleScope shs(isolate);
290 // This isn't exposed to fuzzers so doesn't need to handle invalid arguments.
291 DCHECK_EQ(1, args.length());
292 Tagged<Smi> return_addr_smi = Cast<Smi>(args[0]);
293
294 PrintIndentation(WasmStackSize(isolate));
295 PrintF("}");
296
297 // Find the caller wasm frame.
298 wasm::WasmCodeRefScope wasm_code_ref_scope;
300 DCHECK(!it.done());
301 DCHECK(it.is_wasm());
302#if V8_ENABLE_DRUMBRAKE
303 DCHECK(!it.is_wasm_interpreter_entry());
304#endif // V8_ENABLE_DRUMBRAKE
305 WasmFrame* frame = WasmFrame::cast(it.frame());
306 int func_index = frame->function_index();
307 const wasm::WasmModule* module = frame->trusted_instance_data()->module();
308 const wasm::FunctionSig* sig = module->functions[func_index].sig;
309
310 size_t num_returns = sig->return_count();
311 // If we have no returns, we should have passed {Smi::zero()}.
312 DCHECK_IMPLIES(num_returns == 0, IsZero(return_addr_smi));
313 if (num_returns == 1) {
314 wasm::ValueType return_type = sig->GetReturn(0);
315 switch (return_type.kind()) {
316 case wasm::kI32: {
317 int32_t value =
318 base::ReadUnalignedValue<int32_t>(return_addr_smi.ptr());
319 PrintF(" -> %d\n", value);
320 break;
321 }
322 case wasm::kI64: {
323 int64_t value =
324 base::ReadUnalignedValue<int64_t>(return_addr_smi.ptr());
325 PrintF(" -> %" PRId64 "\n", value);
326 break;
327 }
328 case wasm::kF32: {
329 float value = base::ReadUnalignedValue<float>(return_addr_smi.ptr());
330 PrintF(" -> %f\n", value);
331 break;
332 }
333 case wasm::kF64: {
334 double value = base::ReadUnalignedValue<double>(return_addr_smi.ptr());
335 PrintF(" -> %f\n", value);
336 break;
337 }
338 default:
339 PrintF(" -> Unsupported type\n");
340 break;
341 }
342 } else {
343 // TODO(wasm) Handle multiple return values.
344 PrintF("\n");
345 }
346
347 return ReadOnlyRoots(isolate).undefined_value();
348}
349
350RUNTIME_FUNCTION(Runtime_IsAsmWasmCode) {
351 SealHandleScope shs(isolate);
352 if (args.length() != 1 || !IsJSFunction(args[0])) {
353 return CrashUnlessFuzzing(isolate);
354 }
355 auto function = Cast<JSFunction>(args[0]);
356 if (!function->shared()->HasAsmWasmData()) {
357 return ReadOnlyRoots(isolate).false_value();
358 }
359 if (function->shared()->HasBuiltinId() &&
360 function->shared()->builtin_id() == Builtin::kInstantiateAsmJs) {
361 // Hasn't been compiled yet.
362 return ReadOnlyRoots(isolate).false_value();
363 }
364 return ReadOnlyRoots(isolate).true_value();
365}
366
367namespace {
368
369bool DisallowWasmCodegenFromStringsCallback(v8::Local<v8::Context> context,
370 v8::Local<v8::String> source) {
371 return false;
372}
373
374} // namespace
375
376RUNTIME_FUNCTION(Runtime_DisallowWasmCodegen) {
377 SealHandleScope shs(isolate);
378 if (args.length() != 1 || !IsBoolean(args[0])) {
379 return CrashUnlessFuzzing(isolate);
380 }
381 bool flag = Cast<Boolean>(args[0])->ToBool(isolate);
382 v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
384 flag ? DisallowWasmCodegenFromStringsCallback : nullptr);
385 return ReadOnlyRoots(isolate).undefined_value();
386}
387
388RUNTIME_FUNCTION(Runtime_IsWasmCode) {
389 SealHandleScope shs(isolate);
390 if (args.length() != 1 || !IsJSFunction(args[0])) {
391 return CrashUnlessFuzzing(isolate);
392 }
393 auto function = Cast<JSFunction>(args[0]);
394 Tagged<Code> code = function->code(isolate);
395 bool is_js_to_wasm = code->kind() == CodeKind::JS_TO_WASM_FUNCTION ||
396 (code->builtin_id() == Builtin::kJSToWasmWrapper);
397#if V8_ENABLE_DRUMBRAKE
398 // TODO(paolosev@microsoft.com) - Implement an empty
399 // GenericJSToWasmInterpreterWrapper also when V8_ENABLE_DRUMBRAKE is not
400 // defined to get rid of these #ifdefs.
401 is_js_to_wasm =
402 is_js_to_wasm ||
403 (code->builtin_id() == Builtin::kGenericJSToWasmInterpreterWrapper);
404#endif // V8_ENABLE_DRUMBRAKE
405 return isolate->heap()->ToBoolean(is_js_to_wasm);
406}
407
408RUNTIME_FUNCTION(Runtime_IsWasmTrapHandlerEnabled) {
410 return isolate->heap()->ToBoolean(trap_handler::IsTrapHandlerEnabled());
411}
412
413RUNTIME_FUNCTION(Runtime_IsWasmPartialOOBWriteNoop) {
415 return isolate->heap()->ToBoolean(wasm::kPartialOOBWritesAreNoops);
416}
417
418RUNTIME_FUNCTION(Runtime_IsThreadInWasm) {
420 return isolate->heap()->ToBoolean(trap_handler::IsThreadInWasm());
421}
422
423RUNTIME_FUNCTION(Runtime_GetWasmRecoveredTrapCount) {
424 HandleScope scope(isolate);
425 size_t trap_count = trap_handler::GetRecoveredTrapCount();
426 return *isolate->factory()->NewNumberFromSize(trap_count);
427}
428
429RUNTIME_FUNCTION(Runtime_GetWasmExceptionTagId) {
430 HandleScope scope(isolate);
431 if (args.length() != 2 || !IsWasmExceptionPackage(args[0]) ||
432 !IsWasmInstanceObject(args[1]) ||
434 ->trusted_data(isolate)
435 ->has_tags_table()) {
436 return CrashUnlessFuzzing(isolate);
437 }
443 instance_object->trusted_data(isolate), isolate);
445 WasmExceptionPackage::GetExceptionTag(isolate, exception);
446 CHECK(IsWasmExceptionTag(*tag));
447 DirectHandle<FixedArray> tags_table(trusted_data->tags_table(), isolate);
448 for (int index = 0; index < tags_table->length(); ++index) {
449 if (tags_table->get(index) == *tag) return Smi::FromInt(index);
450 }
451 return CrashUnlessFuzzing(isolate);
452}
453
454RUNTIME_FUNCTION(Runtime_GetWasmExceptionValues) {
455 HandleScope scope(isolate);
456 if (args.length() != 1 || !IsWasmExceptionPackage(args[0])) {
457 return CrashUnlessFuzzing(isolate);
458 }
461 DirectHandle<Object> values_obj =
463 if (!IsFixedArray(*values_obj)) {
464 // Only called with correct input (unless fuzzing).
465 return CrashUnlessFuzzing(isolate);
466 }
467 auto values = Cast<FixedArray>(values_obj);
468 DirectHandle<FixedArray> externalized_values =
469 isolate->factory()->NewFixedArray(values->length());
470 for (int i = 0; i < values->length(); i++) {
471 DirectHandle<Object> value(values->get(i), isolate);
472 if (!IsSmi(*value)) {
473 // Note: This will leak string views to JS. This should be fine for a
474 // debugging function.
475 value = wasm::WasmToJSObject(isolate, value);
476 }
477 externalized_values->set(i, *value);
478 }
479 return *isolate->factory()->NewJSArrayWithElements(externalized_values);
480}
481
482RUNTIME_FUNCTION(Runtime_SerializeWasmModule) {
483 HandleScope scope(isolate);
484 if (args.length() != 1 || !IsWasmModuleObject(args[0])) {
485 return CrashUnlessFuzzing(isolate);
486 }
488
489 wasm::NativeModule* native_module = module_obj->native_module();
490 DCHECK(!native_module->compilation_state()->failed());
491
492 wasm::WasmSerializer wasm_serializer(native_module);
493 size_t byte_length = wasm_serializer.GetSerializedNativeModuleSize();
494
495 DirectHandle<JSArrayBuffer> array_buffer =
496 isolate->factory()
497 ->NewJSArrayBufferAndBackingStore(byte_length,
499 .ToHandleChecked();
500
501 bool serialized_successfully = wasm_serializer.SerializeNativeModule(
502 {static_cast<uint8_t*>(array_buffer->backing_store()), byte_length});
503 CHECK(serialized_successfully || v8_flags.fuzzing);
504 return *array_buffer;
505}
506
507// Take an array buffer and attempt to reconstruct a compiled wasm module.
508// Return undefined if unsuccessful.
509RUNTIME_FUNCTION(Runtime_DeserializeWasmModule) {
510 HandleScope scope(isolate);
511 // This isn't exposed to fuzzers so doesn't need to handle invalid arguments.
512 CHECK_EQ(2, args.length());
513 CHECK(IsJSArrayBuffer(args[0]));
514 CHECK(IsJSTypedArray(args[1]));
515
517 DirectHandle<JSTypedArray> wire_bytes = args.at<JSTypedArray>(1);
518 CHECK(!buffer->was_detached());
519 CHECK(!wire_bytes->WasDetached());
520
521 DirectHandle<JSArrayBuffer> wire_bytes_buffer = wire_bytes->GetBuffer();
522 base::Vector<const uint8_t> wire_bytes_vec{
523 reinterpret_cast<const uint8_t*>(wire_bytes_buffer->backing_store()) +
524 wire_bytes->byte_offset(),
525 wire_bytes->byte_length()};
526 base::Vector<uint8_t> buffer_vec{
527 reinterpret_cast<uint8_t*>(buffer->backing_store()),
528 buffer->byte_length()};
529
530 // Note that {wasm::DeserializeNativeModule} will allocate. We assume the
531 // JSArrayBuffer backing store doesn't get relocated.
532 wasm::CompileTimeImports compile_imports{};
533 MaybeDirectHandle<WasmModuleObject> maybe_module_object =
534 wasm::DeserializeNativeModule(isolate, buffer_vec, wire_bytes_vec,
535 compile_imports, {});
536 DirectHandle<WasmModuleObject> module_object;
537 if (!maybe_module_object.ToHandle(&module_object)) {
538 return ReadOnlyRoots(isolate).undefined_value();
539 }
540 return *module_object;
541}
542
543RUNTIME_FUNCTION(Runtime_WasmGetNumberOfInstances) {
544 SealHandleScope shs(isolate);
545 if (args.length() != 1 || !IsWasmModuleObject(args[0])) {
546 return CrashUnlessFuzzing(isolate);
547 }
549 int instance_count = 0;
550 Tagged<WeakArrayList> weak_instance_list =
551 module_obj->script()->wasm_weak_instance_list();
552 for (int i = 0; i < weak_instance_list->length(); ++i) {
553 if (weak_instance_list->Get(i).IsWeak()) instance_count++;
554 }
555 return Smi::FromInt(instance_count);
556}
557
558RUNTIME_FUNCTION(Runtime_WasmNumCodeSpaces) {
559 HandleScope scope(isolate);
560 if (args.length() != 1 || !IsJSObject(args[0])) {
561 return CrashUnlessFuzzing(isolate);
562 }
563 DirectHandle<JSObject> argument = args.at<JSObject>(0);
564 wasm::NativeModule* native_module;
565 if (IsWasmInstanceObject(*argument)) {
566 native_module = Cast<WasmInstanceObject>(*argument)
567 ->trusted_data(isolate)
568 ->native_module();
569 } else if (IsWasmModuleObject(*argument)) {
570 native_module = Cast<WasmModuleObject>(*argument)->native_module();
571 } else {
572 return CrashUnlessFuzzing(isolate);
573 }
574 size_t num_spaces = native_module->GetNumberOfCodeSpacesForTesting();
575 return *isolate->factory()->NewNumberFromSize(num_spaces);
576}
577
578namespace {
579
580template <typename T1, typename T2 = T1>
581void PrintRep(Address address, const char* str) {
582 PrintF("%4s:", str);
583 const auto t1 = base::ReadLittleEndianValue<T1>(address);
584 if constexpr (std::is_floating_point_v<T1>) {
585 PrintF("%f", t1);
586 } else if constexpr (sizeof(T1) > sizeof(uint32_t)) {
587 PrintF("%" PRIu64, t1);
588 } else {
589 PrintF("%u", t1);
590 }
591 const auto t2 = base::ReadLittleEndianValue<T2>(address);
592 if constexpr (sizeof(T1) > sizeof(uint32_t)) {
593 PrintF(" / %016" PRIx64 "\n", t2);
594 } else {
595 PrintF(" / %0*x\n", static_cast<int>(2 * sizeof(T2)), t2);
596 }
597}
598
599} // namespace
600
601RUNTIME_FUNCTION(Runtime_WasmTraceMemory) {
602 SealHandleScope scope(isolate);
603 if (args.length() != 1 || !IsSmi(args[0])) {
604 return CrashUnlessFuzzing(isolate);
605 }
607 auto info_addr = Cast<Smi>(args[0]);
608
610 reinterpret_cast<wasm::MemoryTracingInfo*>(info_addr.ptr());
611
612 // Find the caller wasm frame.
613 wasm::WasmCodeRefScope wasm_code_ref_scope;
615 DCHECK(!it.done());
616 DCHECK(it.is_wasm());
617#if V8_ENABLE_DRUMBRAKE
618 DCHECK(!it.is_wasm_interpreter_entry());
619#endif // V8_ENABLE_DRUMBRAKE
620 WasmFrame* frame = WasmFrame::cast(it.frame());
621
622 PrintF("%-11s func:%6d:0x%-4x %s %016" PRIuPTR " val: ",
623 ExecutionTierToString(frame->wasm_code()->is_liftoff()
626 frame->function_index(), frame->position(),
627 // Note: The extra leading space makes " store to" the same width as
628 // "load from".
629 info->is_store ? " store to" : "load from", info->offset);
630 // TODO(14259): Fix for multi-memory.
631 const Address address =
632 reinterpret_cast<Address>(frame->trusted_instance_data()
633 ->memory_object(0)
634 ->array_buffer()
635 ->backing_store()) +
636 info->offset;
637 switch (static_cast<MachineRepresentation>(info->mem_rep)) {
639 PrintRep<uint8_t>(address, "i8");
640 break;
642 PrintRep<uint16_t>(address, "i16");
643 break;
645 PrintRep<uint32_t>(address, "i32");
646 break;
648 PrintRep<uint64_t>(address, "i64");
649 break;
651 PrintRep<float, uint32_t>(address, "f32");
652 break;
654 PrintRep<double, uint64_t>(address, "f64");
655 break;
657 const auto a = base::ReadLittleEndianValue<uint32_t>(address);
658 const auto b = base::ReadLittleEndianValue<uint32_t>(address + 4);
659 const auto c = base::ReadLittleEndianValue<uint32_t>(address + 8);
660 const auto d = base::ReadLittleEndianValue<uint32_t>(address + 12);
661 PrintF("s128:%u %u %u %u / %08x %08x %08x %08x\n", a, b, c, d, a, b, c,
662 d);
663 break;
664 }
665 default:
666 PrintF("unknown\n");
667 break;
668 }
669
670 return ReadOnlyRoots(isolate).undefined_value();
671}
672
673namespace {
674// Validate a function now if not already validated. Returns false on validation
675// failure, true otherwise.
677bool ValidateFunctionNowIfNeeded(Isolate* isolate,
678 wasm::NativeModule* native_module,
679 int func_index) {
680 const wasm::WasmModule* module = native_module->module();
681 if (module->function_was_validated(func_index)) return true;
682 DCHECK(v8_flags.wasm_lazy_validation);
683 Zone validation_zone(isolate->allocator(), ZONE_NAME);
684 wasm::WasmDetectedFeatures unused_detected_features;
685 const wasm::WasmFunction* func = &module->functions[func_index];
686 bool is_shared = module->type(func->sig_index).is_shared;
687 base::Vector<const uint8_t> wire_bytes = native_module->wire_bytes();
688 wasm::FunctionBody body{
689 func->sig, func->code.offset(), wire_bytes.begin() + func->code.offset(),
690 wire_bytes.begin() + func->code.end_offset(), is_shared};
691 if (ValidateFunctionBody(&validation_zone, native_module->enabled_features(),
692 module, &unused_detected_features, body)
693 .failed()) {
694 return false;
695 }
696 module->set_function_validated(func_index);
697 return true;
698}
699} // namespace
700
701RUNTIME_FUNCTION(Runtime_WasmTierUpFunction) {
702 DCHECK(!v8_flags.wasm_jitless);
703
704 HandleScope scope(isolate);
705 if (args.length() != 1 ||
707 return CrashUnlessFuzzing(isolate);
708 }
710 auto func_data = exp_fun->shared()->wasm_exported_function_data();
711 Tagged<WasmTrustedInstanceData> trusted_data = func_data->instance_data();
712 int func_index = func_data->function_index();
713 wasm::NativeModule* native_module = trusted_data->native_module();
714 const wasm::WasmModule* module = native_module->module();
715 if (static_cast<uint32_t>(func_index) < module->num_imported_functions) {
716 return CrashUnlessFuzzing(isolate);
717 }
718 if (!ValidateFunctionNowIfNeeded(isolate, native_module, func_index)) {
719 return CrashUnlessFuzzing(isolate);
720 }
721 wasm::TierUpNowForTesting(isolate, trusted_data, func_index);
722 return ReadOnlyRoots(isolate).undefined_value();
723}
724
725RUNTIME_FUNCTION(Runtime_WasmTriggerTierUpForTesting) {
726 DCHECK(!v8_flags.wasm_jitless);
727
728 HandleScope scope(isolate);
729 if (args.length() != 1 ||
731 return CrashUnlessFuzzing(isolate);
732 }
734 auto func_data = exp_fun->shared()->wasm_exported_function_data();
735 Tagged<WasmTrustedInstanceData> trusted_data = func_data->instance_data();
736 int func_index = func_data->function_index();
737 wasm::NativeModule* native_module = trusted_data->native_module();
738 const wasm::WasmModule* module = native_module->module();
739 if (static_cast<uint32_t>(func_index) < module->num_imported_functions) {
740 return CrashUnlessFuzzing(isolate);
741 }
742 if (!ValidateFunctionNowIfNeeded(isolate, native_module, func_index)) {
743 return CrashUnlessFuzzing(isolate);
744 }
745 wasm::TriggerTierUp(isolate, trusted_data, func_index);
746 return ReadOnlyRoots(isolate).undefined_value();
747}
748
749RUNTIME_FUNCTION(Runtime_WasmNull) {
750 // This isn't exposed to fuzzers. (Wasm nulls may not appear in JS.)
751 HandleScope scope(isolate);
752 return ReadOnlyRoots(isolate).wasm_null();
753}
754
756 base::Vector<const uint8_t> module_bytes,
757 bool is_struct) {
758 if (module_bytes.size() > v8_flags.wasm_max_module_size) {
759 return CrashUnlessFuzzing(isolate);
760 }
761 // Create and compile the wasm module.
762 wasm::ErrorThrower thrower(isolate, "CreateWasmObject");
765 MaybeDirectHandle<WasmModuleObject> maybe_module_object = engine->SyncCompile(
767 &thrower, std::move(bytes));
768 CHECK(!thrower.error());
769 DirectHandle<WasmModuleObject> module_object;
770 if (!maybe_module_object.ToHandle(&module_object)) {
771 DCHECK(isolate->has_exception());
772 return ReadOnlyRoots(isolate).exception();
773 }
774 // Instantiate the module.
776 engine->SyncInstantiate(isolate, &thrower, module_object,
779 CHECK(!thrower.error());
781 if (!maybe_instance.ToHandle(&instance)) {
782 DCHECK(isolate->has_exception());
783 return ReadOnlyRoots(isolate).exception();
784 }
785 wasm::WasmValue value(int64_t{0x7AADF00DBAADF00D});
786 wasm::ModuleTypeIndex type_index{0};
788 instance->trusted_data(isolate)->managed_object_maps()->get(
789 type_index.index));
790 if (is_struct) {
791 const wasm::StructType* struct_type =
792 instance->module()->struct_type(type_index);
793 DCHECK_EQ(struct_type->field_count(), 1);
794 DCHECK_EQ(struct_type->field(0), wasm::kWasmI64);
795 return *isolate->factory()->NewWasmStruct(struct_type, &value,
796 direct_handle(map, isolate));
797 } else {
798 DCHECK_EQ(instance->module()->array_type(type_index)->element_type(),
800 return *isolate->factory()->NewWasmArray(wasm::kWasmI64, 1, value,
801 direct_handle(map, isolate));
802 }
803}
804
805// In jitless mode we don't support creation of real wasm objects (they require
806// a NativeModule and instantiating that is not supported in jitless), so this
807// function creates a frozen JS object that should behave the same as a wasm
808// object within JS.
810 DirectHandle<JSObject> obj = isolate->factory()->NewJSObjectWithNullProto();
811 CHECK(IsJSReceiver(*obj));
814 ReadOnlyRoots(isolate).exception());
815 return *obj;
816}
817
818// Creates a new wasm struct with one i64 (value 0x7AADF00DBAADF00D).
819RUNTIME_FUNCTION(Runtime_WasmStruct) {
820 HandleScope scope(isolate);
821 if (v8_flags.jitless && !v8_flags.wasm_jitless) {
823 }
824 /* Recreate with:
825 d8.file.execute('test/mjsunit/wasm/wasm-module-builder.js');
826 let builder = new WasmModuleBuilder();
827 let struct = builder.addStruct([makeField(kWasmI64, false)]);
828 builder.instantiate();
829 */
830 static constexpr uint8_t wasm_module_bytes[] = {
831 0x00, 0x61, 0x73, 0x6d, // wasm magic
832 0x01, 0x00, 0x00, 0x00, // wasm version
833 0x01, // section kind: Type
834 0x07, // section length 7
835 0x01, 0x50, 0x00, // types count 1: subtype extensible,
836 // supertype count 0
837 0x5f, 0x01, 0x7e, 0x00, // kind: struct, field count 1: i64 immutable
838 };
839 return CreateWasmObject(isolate, base::VectorOf(wasm_module_bytes), true);
840}
841
842// Creates a new wasm array of type i64 with one element (0x7AADF00DBAADF00D).
843RUNTIME_FUNCTION(Runtime_WasmArray) {
844 HandleScope scope(isolate);
845 if (v8_flags.jitless && !v8_flags.wasm_jitless) {
847 }
848 /* Recreate with:
849 d8.file.execute('test/mjsunit/wasm/wasm-module-builder.js');
850 let builder = new WasmModuleBuilder();
851 let array = builder.addArray(kWasmI64, false);
852 builder.instantiate();
853 */
854 static constexpr uint8_t wasm_module_bytes[] = {
855 0x00, 0x61, 0x73, 0x6d, // wasm magic
856 0x01, 0x00, 0x00, 0x00, // wasm version
857 0x01, // section kind: Type
858 0x06, // section length 6
859 0x01, 0x50, 0x00, // types count 1: subtype extensible,
860 // supertype count 0
861 0x5e, 0x7e, 0x00, // kind: array i64 immutable
862 };
863 return CreateWasmObject(isolate, base::VectorOf(wasm_module_bytes), false);
864}
865
866RUNTIME_FUNCTION(Runtime_WasmEnterDebugging) {
867 HandleScope scope(isolate);
869 return ReadOnlyRoots(isolate).undefined_value();
870}
871
872RUNTIME_FUNCTION(Runtime_WasmLeaveDebugging) {
873 HandleScope scope(isolate);
875 return ReadOnlyRoots(isolate).undefined_value();
876}
877
878RUNTIME_FUNCTION(Runtime_IsWasmDebugFunction) {
879 HandleScope scope(isolate);
880 if (args.length() != 1 ||
882 return CrashUnlessFuzzing(isolate);
883 }
885 auto data = exp_fun->shared()->wasm_exported_function_data();
886 wasm::NativeModule* native_module = data->instance_data()->native_module();
887 uint32_t func_index = data->function_index();
888 if (static_cast<uint32_t>(func_index) <
889 data->instance_data()->module()->num_imported_functions) {
890 return CrashUnlessFuzzing(isolate);
891 }
892 wasm::WasmCodeRefScope code_ref_scope;
893 wasm::WasmCode* code = native_module->GetCode(func_index);
894 return isolate->heap()->ToBoolean(code && code->is_liftoff() &&
895 code->for_debugging());
896}
897
898RUNTIME_FUNCTION(Runtime_IsLiftoffFunction) {
899 HandleScope scope(isolate);
900 if (args.length() != 1 ||
902 return CrashUnlessFuzzing(isolate);
903 }
905 auto data = exp_fun->shared()->wasm_exported_function_data();
906 wasm::NativeModule* native_module = data->instance_data()->native_module();
907 uint32_t func_index = data->function_index();
908 if (static_cast<uint32_t>(func_index) <
909 data->instance_data()->module()->num_imported_functions) {
910 return CrashUnlessFuzzing(isolate);
911 }
912 wasm::WasmCodeRefScope code_ref_scope;
913 wasm::WasmCode* code = native_module->GetCode(func_index);
914 return isolate->heap()->ToBoolean(code && code->is_liftoff());
915}
916
917RUNTIME_FUNCTION(Runtime_IsTurboFanFunction) {
918 HandleScope scope(isolate);
919 if (args.length() != 1 ||
921 return CrashUnlessFuzzing(isolate);
922 }
924 auto data = exp_fun->shared()->wasm_exported_function_data();
925 wasm::NativeModule* native_module = data->instance_data()->native_module();
926 uint32_t func_index = data->function_index();
927 if (static_cast<uint32_t>(func_index) <
928 data->instance_data()->module()->num_imported_functions) {
929 return CrashUnlessFuzzing(isolate);
930 }
931 wasm::WasmCodeRefScope code_ref_scope;
932 wasm::WasmCode* code = native_module->GetCode(func_index);
933 return isolate->heap()->ToBoolean(code && code->is_turbofan());
934}
935
936RUNTIME_FUNCTION(Runtime_IsUncompiledWasmFunction) {
937 HandleScope scope(isolate);
938 if (args.length() != 1 ||
940 return CrashUnlessFuzzing(isolate);
941 }
943 auto data = exp_fun->shared()->wasm_exported_function_data();
944 wasm::NativeModule* native_module = data->instance_data()->native_module();
945 uint32_t func_index = data->function_index();
946 if (static_cast<uint32_t>(func_index) <
947 data->instance_data()->module()->num_imported_functions) {
948 return CrashUnlessFuzzing(isolate);
949 }
950 return isolate->heap()->ToBoolean(!native_module->HasCode(func_index));
951}
952
953RUNTIME_FUNCTION(Runtime_FreezeWasmLazyCompilation) {
954 // This isn't exposed to fuzzers so doesn't need to handle invalid arguments.
955 DCHECK_EQ(args.length(), 1);
956 DCHECK(IsWasmInstanceObject(args[0]));
959
960 instance_object->module_object()->native_module()->set_lazy_compile_frozen(
961 true);
962 return ReadOnlyRoots(isolate).undefined_value();
963}
964
965// This runtime function enables WebAssembly imported strings through an
966// embedder callback and thereby bypasses the value in v8_flags.
967RUNTIME_FUNCTION(Runtime_SetWasmImportedStringsEnabled) {
968 if (args.length() != 1) {
969 return CrashUnlessFuzzing(isolate);
970 }
971 bool enable = Object::BooleanValue(*args.at(0), isolate);
972 v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
974 return true;
975 };
977 return false;
978 };
979 v8_isolate->SetWasmImportedStringsEnabledCallback(enable ? enabled
980 : disabled);
981 return ReadOnlyRoots(isolate).undefined_value();
982}
983
984RUNTIME_FUNCTION(Runtime_FlushLiftoffCode) {
985 auto [code_size, metadata_size] = wasm::GetWasmEngine()->FlushLiftoffCode();
986 return Smi::FromInt(static_cast<int>(code_size + metadata_size));
987}
988
989RUNTIME_FUNCTION(Runtime_WasmTriggerCodeGC) {
991 return ReadOnlyRoots(isolate).undefined_value();
992}
993
994RUNTIME_FUNCTION(Runtime_EstimateCurrentMemoryConsumption) {
996 return Smi::FromInt(static_cast<int>(result));
997}
998
999RUNTIME_FUNCTION(Runtime_WasmCompiledExportWrappersCount) {
1000 int count = isolate->counters()
1001 ->wasm_compiled_export_wrapper()
1002 ->GetInternalPointer()
1003 ->load();
1004 return Smi::FromInt(count);
1005}
1006
1007RUNTIME_FUNCTION(Runtime_WasmDeoptsExecutedCount) {
1009 return Smi::FromInt(count);
1010}
1011
1012RUNTIME_FUNCTION(Runtime_WasmDeoptsExecutedForFunction) {
1013 if (args.length() != 1 ||
1015 return CrashUnlessFuzzing(isolate);
1016 }
1018 auto func_data = exp_fun->shared()->wasm_exported_function_data();
1019 const wasm::WasmModule* module =
1020 func_data->instance_data()->native_module()->module();
1021 uint32_t func_index = func_data->function_index();
1022 if (static_cast<uint32_t>(func_index) <
1023 func_data->instance_data()->module()->num_imported_functions) {
1024 return CrashUnlessFuzzing(isolate);
1025 }
1026 const wasm::TypeFeedbackStorage& feedback = module->type_feedback;
1027 base::MutexGuard mutex_guard(&feedback.mutex);
1028 auto entry = feedback.deopt_count_for_function.find(func_index);
1029 if (entry == feedback.deopt_count_for_function.end()) {
1030 return Smi::FromInt(0);
1031 }
1032 return Smi::FromInt(entry->second);
1033}
1034
1035RUNTIME_FUNCTION(Runtime_WasmSwitchToTheCentralStackCount) {
1036 int count = isolate->wasm_switch_to_the_central_stack_counter();
1037 return Smi::FromInt(count);
1038}
1039
1040RUNTIME_FUNCTION(Runtime_CheckIsOnCentralStack) {
1041 // This function verifies that itself, and therefore the JS function that
1042 // called it, is running on the central stack. This is used to check that wasm
1043 // switches to the central stack to run JS imports.
1044 CHECK(isolate->IsOnCentralStack());
1045 return ReadOnlyRoots(isolate).undefined_value();
1046}
1047
1048// Takes a type index, creates a ValueType for (ref $index) and returns its
1049// raw bit field. Useful for sandbox tests.
1050RUNTIME_FUNCTION(Runtime_BuildRefTypeBitfield) {
1051 SealHandleScope scope(isolate);
1052 if (args.length() != 2 || !IsSmi(args[0]) || !IsWasmInstanceObject(args[1])) {
1053 return CrashUnlessFuzzing(isolate);
1054 }
1056 // Allow fuzzers to generate invalid types, but avoid running into the
1057 // DCHECK in base::BitField::encode().
1058 static constexpr uint32_t kMask = (1u << wasm::ValueType::kNumIndexBits) - 1;
1059 wasm::ModuleTypeIndex type_index{
1060 static_cast<uint32_t>(Cast<Smi>(args[0]).value()) & kMask};
1061 const wasm::WasmModule* module = Cast<WasmInstanceObject>(args[1])->module();
1062 // If we get an invalid type index, make up the additional data; the result
1063 // may still be useful for fuzzers for causing interesting confusion.
1064 wasm::ValueType t =
1065 module->has_type(type_index)
1066 ? wasm::ValueType::Ref(module->heap_type(type_index))
1067 : wasm::ValueType::Ref(type_index, false, wasm::RefTypeKind::kStruct);
1068 return Smi::FromInt(t.raw_bit_field());
1069}
1070
1071// The GenerateRandomWasmModule function is only implemented in non-official
1072// builds (to save binary size). Hence also skip the runtime function in
1073// official builds.
1074#ifdef V8_WASM_RANDOM_FUZZERS
1075RUNTIME_FUNCTION(Runtime_WasmGenerateRandomModule) {
1076 if (v8_flags.jitless) {
1077 return CrashUnlessFuzzing(isolate);
1078 }
1079 HandleScope scope{isolate};
1080 Zone temporary_zone{isolate->allocator(), "WasmGenerateRandomModule"};
1081 constexpr size_t kMaxInputBytes = 512;
1082 ZoneVector<uint8_t> input_bytes{&temporary_zone};
1083 auto add_input_bytes = [&input_bytes](void* bytes, size_t max_bytes) {
1084 size_t num_bytes = std::min(kMaxInputBytes - input_bytes.size(), max_bytes);
1085 input_bytes.resize(input_bytes.size() + num_bytes);
1086 memcpy(input_bytes.end() - num_bytes, bytes, num_bytes);
1087 };
1088 if (args.length() == 0) {
1089 // If we are called without any arguments, use the RNG from the isolate to
1090 // generate between 1 and kMaxInputBytes random bytes.
1091 int num_bytes =
1092 1 + isolate->random_number_generator()->NextInt(kMaxInputBytes);
1093 input_bytes.resize(num_bytes);
1094 isolate->random_number_generator()->NextBytes(input_bytes.data(),
1095 num_bytes);
1096 } else {
1097 for (int i = 0; i < args.length(); ++i) {
1098 if (IsJSTypedArray(args[i])) {
1100 add_input_bytes(typed_array->DataPtr(), typed_array->GetByteLength());
1101 } else if (IsJSArrayBuffer(args[i])) {
1103 add_input_bytes(array_buffer->backing_store(),
1104 array_buffer->GetByteLength());
1105 } else if (IsSmi(args[i])) {
1106 int smi_value = Cast<Smi>(args[i]).value();
1107 add_input_bytes(&smi_value, kIntSize);
1108 } else if (IsHeapNumber(args[i])) {
1109 double value = Cast<HeapNumber>(args[i])->value();
1110 add_input_bytes(&value, kDoubleSize);
1111 } else {
1112 // TODO(14637): Extract bytes from more types.
1113 }
1114 }
1115 }
1116
1117 // Avoid generating SIMD if the CPU does not support it, or it's disabled via
1118 // flags. Otherwise, do not limit the generated expressions and types.
1119 constexpr auto kAllOptions =
1120 wasm::fuzzing::WasmModuleGenerationOptions::All();
1121 constexpr auto kNoSimdOptions = wasm::fuzzing::WasmModuleGenerationOptions{
1122 {wasm::fuzzing::WasmModuleGenerationOption::kGenerateWasmGC}};
1123 static_assert(
1124 (kNoSimdOptions |
1125 wasm::fuzzing::WasmModuleGenerationOptions{
1126 {wasm::fuzzing::WasmModuleGenerationOption::kGenerateSIMD}}) ==
1127 kAllOptions);
1128 auto options =
1129 wasm::CheckHardwareSupportsSimd() ? kAllOptions : kNoSimdOptions;
1130
1131 base::Vector<const uint8_t> module_bytes =
1132 wasm::fuzzing::GenerateRandomWasmModule(&temporary_zone, options,
1133 base::VectorOf(input_bytes));
1134
1135 // Fuzzers can set `--wasm-max-module-size` to small values and then call
1136 // %WasmGenerateRandomModule() (see https://crbug.com/382816108).
1137 if (module_bytes.size() > v8_flags.wasm_max_module_size) {
1138 return CrashUnlessFuzzing(isolate);
1139 }
1140
1141 wasm::ErrorThrower thrower{isolate, "WasmGenerateRandomModule"};
1142 MaybeDirectHandle<WasmModuleObject> maybe_module_object =
1145 wasm::CompileTimeImports{}, &thrower,
1146 base::OwnedCopyOf(module_bytes));
1147 if (thrower.error()) {
1148 FATAL(
1149 "wasm::GenerateRandomWasmModule produced a module which did not "
1150 "compile: %s",
1151 thrower.error_msg());
1152 }
1153 return *maybe_module_object.ToHandleChecked();
1154}
1155#endif // V8_WASM_RANDOM_FUZZERS
1156
1157} // namespace v8::internal
friend Zone
Definition asm-types.cc:195
size_t ByteLength()
Definition api.cc:9250
size_t ByteLength() const
Definition api.cc:9000
static Local< Value > RangeError(Local< String > message, Local< Value > options={})
void SetAllowWasmCodeGenerationCallback(AllowWasmCodeGenerationCallback callback)
void SetWasmInstanceCallback(ExtensionCallback callback)
void SetWasmModuleCallback(ExtensionCallback callback)
void SetWasmImportedStringsEnabledCallback(WasmImportedStringsEnabledCallback callback)
static V8_INLINE Local< T > Cast(Local< S > that)
static V8_WARN_UNUSED_RESULT MaybeLocal< String > NewFromOneByte(Isolate *isolate, const uint8_t *data, NewStringType type=NewStringType::kNormal, int length=-1)
Definition api.cc:7599
constexpr size_t size() const
Definition vector.h:70
constexpr T * begin() const
Definition vector.h:96
static Address EntryOf(Builtin builtin, Isolate *isolate)
static V8_WARN_UNUSED_RESULT Maybe< bool > SetIntegrityLevel(Isolate *isolate, DirectHandle< JSReceiver > object, IntegrityLevel lvl, ShouldThrow should_throw)
V8_WARN_UNUSED_RESULT V8_INLINE bool ToHandle(DirectHandle< S > *out) const
static V8_EXPORT_PRIVATE bool BooleanValue(Tagged< Object > obj, IsolateT *isolate)
size_t return_count() const
Definition signature.h:93
static constexpr Tagged< Smi > FromInt(int value)
Definition smi.h:38
static constexpr Tagged< Smi > zero()
Definition smi.h:99
V8_INLINE constexpr StorageType ptr() const
constexpr bool SafeEquals(TaggedImpl< kOtherRefType, StorageType > other) const
Definition tagged-impl.h:93
constexpr bool IsWeak() const
static DirectHandle< Object > GetExceptionValues(Isolate *isolate, DirectHandle< WasmExceptionPackage > exception_package)
static DirectHandle< Object > GetExceptionTag(Isolate *isolate, DirectHandle< WasmExceptionPackage > exception_package)
static V8_EXPORT_PRIVATE bool IsWasmExportedFunction(Tagged< Object > object)
static V8_EXPORT_PRIVATE DirectHandle< JSFunction > GetOrCreateExternal(DirectHandle< WasmInternalFunction > internal)
static bool IsWasmJSFunction(Tagged< Object > object)
WasmCode * GetCode(uint32_t index) const
const WasmModule * module() const
bool HasCode(uint32_t index) const
ValueType field(uint32_t index) const
constexpr ValueKind kind() const
Definition value-type.h:631
bool EntrypointEqualTo(WasmCodePointer index, Address address)
static V8_EXPORT_PRIVATE WasmEnabledFeatures FromFlags()
MaybeDirectHandle< WasmModuleObject > SyncCompile(Isolate *isolate, WasmEnabledFeatures enabled, CompileTimeImports compile_imports, ErrorThrower *thrower, base::OwnedVector< const uint8_t > bytes)
void EnterDebuggingForIsolate(Isolate *isolate)
size_t EstimateCurrentMemoryConsumption() const
void LeaveDebuggingForIsolate(Isolate *isolate)
std::pair< size_t, size_t > FlushLiftoffCode()
bool SerializeNativeModule(base::Vector< uint8_t > buffer) const
uint32_t count
#define RUNTIME_FUNCTION(Name)
Definition arguments.h:162
#define MAYBE_RETURN(call, value)
Definition isolate.h:408
base::Vector< const DirectHandle< Object > > args
Definition execution.cc:74
Isolate * isolate
ZoneVector< RpoNumber > & result
#define DEFINE_LAZY_LEAKY_OBJECT_GETTER(T, FunctionName,...)
int n
Definition mul-fft.cc:296
#define LAZY_MUTEX_INITIALIZER
Definition mutex.h:105
static V ReadUnalignedValue(Address p)
Definition memory.h:28
constexpr Vector< T > VectorOf(T *start, size_t size)
Definition vector.h:360
static V ReadLittleEndianValue(Address p)
Definition memory.h:52
OwnedVector< T > OwnedCopyOf(const T *data, size_t size)
Definition vector.h:383
LockGuard< Mutex > MutexGuard
Definition mutex.h:219
LazyStaticInstance< Mutex, DefaultConstructTrait< Mutex >, ThreadSafeInitOnceTrait >::type LazyMutex
Definition mutex.h:103
TH_DISABLE_ASAN bool IsThreadInWasm()
base::Vector< uint8_t > GenerateRandomWasmModule(Zone *zone, WasmModuleGenerationOptions options, base::Vector< const uint8_t > data)
V8_EXPORT_PRIVATE WasmCodePointerTable * GetProcessWideWasmCodePointerTable()
void TierUpNowForTesting(Isolate *isolate, Tagged< WasmTrustedInstanceData > trusted_instance_data, int func_index)
void TriggerTierUp(Isolate *isolate, Tagged< WasmTrustedInstanceData > trusted_instance_data, int func_index)
constexpr WasmCodePointer kInvalidWasmCodePointer
MaybeDirectHandle< WasmModuleObject > DeserializeNativeModule(Isolate *isolate, base::Vector< const uint8_t > data, base::Vector< const uint8_t > wire_bytes_vec, const CompileTimeImports &compile_imports, base::Vector< const char > source_url)
WasmEngine * GetWasmEngine()
constexpr bool kPartialOOBWritesAreNoops
constexpr IndependentValueType kWasmI64
DirectHandle< Object > WasmToJSObject(Isolate *isolate, DirectHandle< Object > value)
constexpr int kIntSize
Definition globals.h:400
void PrintF(const char *format,...)
Definition utils.cc:39
Tagged(T object) -> Tagged< T >
V8_INLINE constexpr bool IsSmi(TaggedImpl< kRefType, StorageType > obj)
Definition objects.h:665
V8_INLINE DirectHandle< T > direct_handle(Tagged< T > object, Isolate *isolate)
kWasmInternalFunctionIndirectPointerTag kProtectedInstanceDataOffset sig
bool V8_EXPORT ValidateCallbackInfo(const FunctionCallbackInfo< void > &info)
Definition api.cc:12301
static Tagged< Object > CreateDummyWasmLookAlikeForFuzzing(Isolate *isolate)
V8_EXPORT_PRIVATE FlagValues v8_flags
return value
Definition map-inl.h:893
constexpr bool kAllCodeObjectsLiveInTrustedSpace
constexpr int kDoubleSize
Definition globals.h:407
JSArrayBuffer::IsDetachableBit is_shared
kMemory0SizeOffset Address kNewAllocationLimitAddressOffset Address kOldAllocationLimitAddressOffset uint8_t kGlobalsStartOffset kJumpTableStartOffset std::atomic< uint32_t > kTieringBudgetArrayOffset kDataSegmentStartsOffset kElementSegmentsOffset instance_object
static Tagged< Object > CreateWasmObject(Isolate *isolate, base::Vector< const uint8_t > module_bytes, bool is_struct)
static bool IsZero(const Operand &rt)
Tagged< To > Cast(Tagged< From > value, const v8::SourceLocation &loc=INIT_SOURCE_LOCATION_IN_DEBUG)
Definition casting.h:150
bool(*)(Local< Context > context) WasmImportedStringsEnabledCallback
bool AllowAnySizeForAsync
uint32_t MaxWasmBufferSize
#define FATAL(...)
Definition logging.h:47
#define CHECK(condition)
Definition logging.h:124
#define DCHECK_IMPLIES(v1, v2)
Definition logging.h:493
#define CHECK_EQ(lhs, rhs)
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_EQ(v1, v2)
Definition logging.h:485
#define DCHECK_GT(v1, v2)
Definition logging.h:487
WasmName GetNameOrNull(WireBytesRef ref) const
#define T1(name, string, precedence)
Definition token.cc:28
#define T2(name, string, precedence)
Definition token.cc:30
#define V8_WARN_UNUSED_RESULT
Definition v8config.h:671
#define ZONE_NAME
Definition zone.h:22