33#if V8_ENABLE_WEBASSEMBLY && V8_ENABLE_DRUMBRAKE
50 template <
class S = Object>
54#define RuntimeArguments RuntimeArgumentsWithoutHandles
60template <
typename FrameType>
63 explicit FrameFinder(Isolate* isolate,
64 std::initializer_list<StackFrame::Type>
65 skipped_frame_types = {StackFrame::EXIT})
67 StackFrameIterator::FirstStackOnly{}) {
71 for (
auto type : skipped_frame_types) {
97 Memory<Address>(fp + WasmFrameConstants::kWasmInstanceDataOffset));
101Tagged<Context> GetNativeContextFromWasmInstanceOnStackTop(Isolate* isolate) {
102 return GetWasmInstanceDataOnStackTop(isolate)->native_context();
109 explicit ClearThreadInWasmScope(Isolate* isolate)
114 trap_handler::ClearThreadInWasm();
117#if V8_ENABLE_DRUMBRAKE
118 if (
v8_flags.wasm_enable_exec_time_histograms &&
v8_flags.slow_histograms &&
120 isolate->wasm_execution_timer()->Stop();
124 ~ClearThreadInWasmScope() {
125 trap_handler::AssertThreadNotInWasm();
127 trap_handler::SetThreadInWasm();
129#if V8_ENABLE_DRUMBRAKE
130 if (
v8_flags.wasm_enable_exec_time_histograms &&
132 isolate_->wasm_execution_timer()->Start();
147 std::initializer_list<DirectHandle<Object>>
args = {}) {
148#if V8_ENABLE_DRUMBRAKE
156 DirectHandle<JSObject> error_obj =
159 isolate->factory()->wasm_uncatchable_symbol(),
160 isolate->factory()->true_value(),
NONE);
161 return isolate->Throw(*error_obj);
166 DirectHandle<JSObject> error_obj =
167 isolate->factory()->NewWasmSuspendError(message);
168 return isolate->Throw(*error_obj);
176 if (IsWasmFuncRef(value)) {
180 if (
internal->try_get_external(&external))
return external;
186 if (IsWasmNull(value))
return ReadOnlyRoots(isolate).null_value();
199 int raw_type =
args.smi_value_at(1);
203 const char* error_message;
205 if (!JSToWasmObject(isolate, value, type, &error_message).ToHandle(&
result)) {
206 return isolate->Throw(*isolate->factory()->NewTypeError(
207 MessageTemplate::kWasmTrapJSTypeError));
224 int raw_type =
args.smi_value_at(1);
228 const char* error_message;
230 bool success = JSToWasmObject(isolate, value, expected, &error_message)
234 : isolate->Throw(*isolate->factory()->NewTypeError(
235 MessageTemplate::kWasmTrapJSTypeError));
240 ClearThreadInWasmScope flag_scope(isolate);
247 uint32_t memory_index =
args.positive_smi_value_at(1);
248 uint32_t delta_pages =
args.positive_smi_value_at(2);
251 trusted_instance_data->memory_object(memory_index), isolate};
255 DCHECK(!isolate->has_exception());
260 ClearThreadInWasmScope flag_scope(isolate);
261 CHECK(isolate->IsOnCentralStack());
263 FrameFinder<WasmFrame> frame_finder(isolate, {StackFrame::EXIT});
264 WasmFrame* frame = frame_finder.frame();
270 int pos = summaries.
frames.back().AsWasm().SourcePosition();
273 auto wire_bytes = frame->wasm_code()->native_module()->wire_bytes();
276 if (op == wasm::kGCPrefix || op == wasm::kExprRefAsNonNull ||
277 op == wasm::kExprCallRef || op == wasm::kExprReturnCallRef ||
279 op == wasm::kExprCallFunction || op == wasm::kExprReturnCall) {
280 message = MessageTemplate::kWasmTrapNullDereference;
286 &wire_bytes.begin()[
pos])
291 return ThrowWasmError(isolate, message);
295 ClearThreadInWasmScope flag_scope(isolate);
296 DCHECK(isolate->IsOnCentralStack());
299 int message_id =
args.smi_value_at(0);
304 ClearThreadInWasmScope clear_wasm_flag(isolate);
307 return isolate->StackOverflow();
314#if V8_ENABLE_DRUMBRAKE
316 if (
v8_flags.wasm_enable_exec_time_histograms &&
v8_flags.slow_histograms &&
319 isolate->wasm_execution_timer()->Stop();
328 isolate, NewTypeError(MessageTemplate::kWasmTrapJSTypeError));
337 return ThrowWasmSuspendError(isolate, message_id);
341 ClearThreadInWasmScope clear_wasm_flag(isolate);
349 ClearThreadInWasmScope clear_wasm_flag(isolate);
355 isolate->factory()->NewStringFromAsciiChecked(
ToString(op));
359 NewTypeError(message_id, op_name, value));
363 ClearThreadInWasmScope clear_wasm_flag(isolate);
369 isolate->factory()->NewStringFromAsciiChecked(
ToString(op));
375 ClearThreadInWasmScope clear_wasm_flag(isolate);
388 ClearThreadInWasmScope clear_wasm_flag(isolate);
391 Tagged<Context> context = GetNativeContextFromWasmInstanceOnStackTop(isolate);
392 isolate->set_context(context);
396 if (*tag == js_tag->tag()) {
397 return isolate->Throw(values->get(0));
401 return isolate->Throw(*exception);
406 ClearThreadInWasmScope clear_wasm_flag(isolate);
409 return isolate->ReThrow(
args[0]);
413 ClearThreadInWasmScope wasm_flag(isolate);
417 uint32_t gap =
args.positive_smi_value_at(0);
421 if (check.WasmHasOverflowed(gap))
return isolate->StackOverflow();
423 return isolate->stack_guard()->HandleInterrupts(
428 ClearThreadInWasmScope wasm_flag(isolate);
432 int func_index =
args.smi_value_at(1);
434 TRACE_EVENT1(
"v8.wasm",
"wasm.CompileLazy",
"func_index", func_index);
438 DCHECK(isolate->context().is_null());
439 isolate->set_context(trusted_instance_data->native_context());
445 isolate, trusted_instance_data->native_module(), func_index);
446 DCHECK(isolate->has_exception());
457 DirectHandle<WasmTrustedInstanceData> trusted_instance_data,
458 int declared_func_index) {
459 DCHECK(isolate->context().is_null());
460 isolate->set_context(trusted_instance_data->native_context());
461 const wasm::WasmModule* module =
462 trusted_instance_data->native_module()->module();
464 int func_index = declared_func_index + module->num_imported_functions;
465 int num_slots = NumFeedbackSlots(module, func_index);
466 DirectHandle<FixedArray> vector =
467 isolate->factory()->NewFixedArrayWithZeroes(num_slots);
468 DCHECK_EQ(trusted_instance_data->feedback_vectors()->get(declared_func_index),
470 trusted_instance_data->feedback_vectors()->set(declared_func_index, *vector);
477 ClearThreadInWasmScope wasm_flag(isolate);
478 DCHECK(isolate->IsOnCentralStack());
484 int declared_func_index =
args.smi_value_at(1);
490 *native_module_stack_slot = native_module;
491 return AllocateFeedbackVector(isolate, trusted_instance_data,
492 declared_func_index);
496 ClearThreadInWasmScope wasm_flag(isolate);
509 if (frame->is_wasm() && WasmFrame::cast(frame)->wasm_code()->is_liftoff()) {
513 if (vector_or_smi.
IsSmi()) {
514 int declared_func_index =
Cast<Smi>(vector_or_smi).value();
516 trusted_instance_data->feedback_vectors()->get(declared_func_index);
520 vector = AllocateFeedbackVector(isolate, trusted_instance_data,
521 declared_func_index);
523 memcpy(
reinterpret_cast<void*
>(vector_address), &vector,
526 if (++
i == deopt_frame_count) {
535void ReplaceJSToWasmWrapper(
542 CHECK(trusted_instance_data->try_get_func_ref(function_index, &func_ref));
544 CHECK(func_ref->internal(isolate)->try_get_external(&external_function));
545 if (external_function->shared()->HasWasmJSFunctionData())
return;
546 CHECK(external_function->shared()->HasWasmExportedFunctionData());
547 external_function->UpdateCode(wrapper_code);
549 external_function->shared()->wasm_exported_function_data();
550 function_data->set_wrapper_code(wrapper_code);
563 const int function_index = function_data->function_index();
566 module->canonical_sig_id(function.sig_index);
571 isolate->heap()->js_to_wasm_wrappers()->get(sig_id.
index);
581 DCHECK(isolate->context().is_null());
588 isolate,
sig, sig_id);
592 isolate->heap()->js_to_wasm_wrappers()->get(sig_id.
index));
595 wrapper_code = *new_wrapper_code;
603 ReplaceJSToWasmWrapper(isolate,
trusted_data, function_index, wrapper_code);
609 int index =
static_cast<int>(exp.index);
610 if (index == function_index)
continue;
615 ReplaceJSToWasmWrapper(isolate,
trusted_data, index, wrapper_code);
623 return isolate->heap()->ToBoolean(
633 DCHECK(isolate->context().is_null());
634 isolate->set_context(import_data->native_context());
640 if (IsWasmInternalFunction(*origin)) {
643 size_t expected_arity =
sig->parameter_count();
645 if (IsJSFunction(import_data->callable())) {
649 shared->internal_formal_parameter_count_without_receiver();
650 if (expected_arity ==
sig->parameter_count()) {
661 int arity =
static_cast<int>(expected_arity);
664 cache->MaybeGet(
kind, canonical_sig_index, arity, suspend);
667 wrapper = cache->CompileWasmImportCallWrapper(
675 if (
internal->try_get_external(&existing_external)) {
676 Tagged<Object> func_data = existing_external->shared()->GetTrustedData();
678 if (IsWasmJSFunctionData(func_data)) {
681 ->set_compiled_wrapper(wrapper);
690 DCHECK(IsWasmExportedFunctionData(func_data));
709 table->offheap_data()->WrapperCodePointerForDebugging(
711 table->InstallCompiledWrapper(
internal->function_index(), wrapper);
715 CHECK(IsWasmDispatchTable(*origin));
718 int table_slot = import_data->table_slot();
731 callable = resolved.callable();
734 int expected_arity =
static_cast<int>(
sig->parameter_count());
735 if (
kind == wasm::ImportCallKind ::kJSFunctionArityMismatch) {
738 ->internal_formal_parameter_count_without_receiver();
743 cache->MaybeGet(
kind, sig_index, expected_arity, suspend);
745 wasm_code = cache->CompileWasmImportCallWrapper(
746 isolate,
kind,
sig, sig_index,
false, expected_arity, suspend);
751 dispatch_table->InstallCompiledWrapper(table_slot, wasm_code);
757 ClearThreadInWasmScope clear_wasm_flag(isolate);
766 FrameFinder<WasmFrame> frame_finder(isolate);
767 int func_index = frame_finder.frame()->function_index();
779 trusted_data->tiering_budget_array()[array_index].store(
780 v8_flags.wasm_tiering_budget, std::memory_order_relaxed);
794 if (check.InterruptRequested()) {
805 ClearThreadInWasmScope clear_wasm_flag(isolate);
810 int memory_index =
args.smi_value_at(1);
811 double offset_double =
args.number_value_at(2);
812 uintptr_t
offset =
static_cast<uintptr_t
>(offset_double);
817 trusted_instance_data->memory_object(memory_index)->array_buffer(),
823 if (!array_buffer->is_shared() || !isolate->allow_atomics_wait()) {
824 return ThrowWasmError(
825 isolate, MessageTemplate::kAtomicsOperationNotAllowed,
826 {isolate->factory()->NewStringFromAsciiChecked(
"Atomics.wait")});
829 expected_value, timeout_ns->AsInt64());
833 ClearThreadInWasmScope clear_wasm_flag(isolate);
838 int memory_index =
args.smi_value_at(1);
839 double offset_double =
args.number_value_at(2);
840 uintptr_t
offset =
static_cast<uintptr_t
>(offset_double);
845 trusted_instance_data->memory_object(memory_index)->array_buffer(),
851 if (!array_buffer->is_shared() || !isolate->allow_atomics_wait()) {
852 return ThrowWasmError(
853 isolate, MessageTemplate::kAtomicsOperationNotAllowed,
854 {isolate->factory()->NewStringFromAsciiChecked(
"Atomics.wait")});
857 expected_value->AsInt64(),
858 timeout_ns->AsInt64());
864 DirectHandle<WasmTrustedInstanceData> trusted_instance_data) {
867 if (isolate->context().is_null()) {
868 isolate->set_context(trusted_instance_data->native_context());
870 return ThrowWasmError(isolate, MessageTemplate::kWasmTrapTableOutOfBounds);
875 ClearThreadInWasmScope flag_scope(isolate);
880 uint32_t function_index =
args.positive_smi_value_at(1);
883 isolate, trusted_instance_data, function_index);
887 ClearThreadInWasmScope flag_scope(isolate);
897 ClearThreadInWasmScope flag_scope(isolate);
902 uint32_t table_index =
args.positive_smi_value_at(1);
903 uint32_t entry_index =
args.positive_smi_value_at(2);
904 DCHECK_LT(table_index, trusted_instance_data->tables()->length());
911 if (!table->is_in_bounds(entry_index)) {
912 return ThrowWasmError(isolate, MessageTemplate::kWasmTrapTableOutOfBounds);
919 ClearThreadInWasmScope flag_scope(isolate);
924 uint32_t table_index =
args.positive_smi_value_at(1);
925 uint32_t entry_index =
args.positive_smi_value_at(2);
927 DCHECK_LT(table_index, trusted_instance_data->tables()->length());
934 if (!table->is_in_bounds(entry_index)) {
935 return ThrowWasmError(isolate, MessageTemplate::kWasmTrapTableOutOfBounds);
942 ClearThreadInWasmScope flag_scope(isolate);
947 uint32_t table_index =
args.positive_smi_value_at(1);
948 uint32_t elem_segment_index =
args.positive_smi_value_at(2);
951 "Make sure clamping to Smi range doesn't make an invalid call valid");
952 uint32_t dst =
args.positive_smi_value_at(3);
953 uint32_t src =
args.positive_smi_value_at(4);
954 uint32_t
count =
args.positive_smi_value_at(5);
956 DCHECK(!isolate->context().is_null());
959 std::optional<MessageTemplate> opt_error =
961 isolate, trusted_instance_data, trusted_instance_data, table_index,
962 elem_segment_index, dst, src,
count);
963 if (opt_error.has_value()) {
964 return ThrowWasmError(isolate, opt_error.value());
970 ClearThreadInWasmScope flag_scope(isolate);
975 uint32_t table_dst_index =
args.positive_smi_value_at(1);
976 uint32_t table_src_index =
args.positive_smi_value_at(2);
979 "Make sure clamping to Smi range doesn't make an invalid call valid");
980 uint32_t dst =
args.positive_smi_value_at(3);
981 uint32_t src =
args.positive_smi_value_at(4);
982 uint32_t
count =
args.positive_smi_value_at(5);
984 DCHECK(!isolate->context().is_null());
987 isolate, trusted_instance_data, table_dst_index, table_src_index, dst,
989 if (oob)
return ThrowTableOutOfBounds(isolate, trusted_instance_data);
994 ClearThreadInWasmScope flag_scope(isolate);
995 DCHECK(isolate->IsOnCentralStack());
1000 uint32_t table_index =
args.positive_smi_value_at(1);
1002 uint32_t delta =
args.positive_smi_value_at(3);
1013 ClearThreadInWasmScope flag_scope(isolate);
1018 uint32_t table_index =
args.positive_smi_value_at(1);
1019 uint32_t
start =
args.positive_smi_value_at(2);
1021 uint32_t
count =
args.positive_smi_value_at(4);
1027 uint32_t table_size = table->current_length();
1029 if (
start > table_size) {
1030 return ThrowTableOutOfBounds(isolate, trusted_instance_data);
1035 uint32_t fill_count = std::min(
count, table_size -
start);
1036 if (fill_count <
count) {
1037 return ThrowTableOutOfBounds(isolate, trusted_instance_data);
1046bool ExecuteWasmDebugBreaks(
1048 DirectHandle<WasmTrustedInstanceData> trusted_instance_data,
1050 DirectHandle<Script> script{trusted_instance_data->module_object()->script(),
1052 auto* debug_info = trusted_instance_data->native_module()->GetDebugInfo();
1055 DebugScope debug_scope(isolate->debug());
1059 bool paused_on_instrumentation =
false;
1061 !!trusted_instance_data->break_on_entry());
1062 if (script->break_on_entry()) {
1063 MaybeDirectHandle<FixedArray> maybe_on_entry_breakpoints =
1067 script->set_break_on_entry(
false);
1070 script->wasm_weak_instance_list();
1071 for (
int i = 0;
i < weak_instance_list->length(); ++
i) {
1072 if (weak_instance_list->Get(
i).
IsCleared())
continue;
1074 ->trusted_data(isolate)
1075 ->set_break_on_entry(
false);
1077 DCHECK(!trusted_instance_data->break_on_entry());
1078 if (!maybe_on_entry_breakpoints.is_null()) {
1079 isolate->debug()->OnInstrumentationBreak();
1080 paused_on_instrumentation =
true;
1084 if (debug_info->IsStepping(frame) && !debug_info->IsFrameBlackboxed(frame)) {
1085 debug_info->ClearStepping(isolate);
1086 StepAction step_action = isolate->debug()->last_step_action();
1087 isolate->debug()->ClearStepping();
1088 isolate->debug()->OnDebugBreak(isolate->factory()->empty_fixed_array(),
1094 DirectHandle<FixedArray> breakpoints;
1097 .ToHandle(&breakpoints)) {
1098 debug_info->ClearStepping(isolate);
1099 StepAction step_action = isolate->debug()->last_step_action();
1100 isolate->debug()->ClearStepping();
1101 if (isolate->debug()->break_points_active()) {
1103 isolate->debug()->OnDebugBreak(breakpoints, step_action);
1108 return paused_on_instrumentation;
1113 ClearThreadInWasmScope flag_scope(isolate);
1116 FrameFinder<WasmFrame> frame_finder(
1117 isolate, {StackFrame::EXIT, StackFrame::WASM_DEBUG_BREAK});
1118 WasmFrame* frame = frame_finder.frame();
1120 frame->trusted_instance_data(), isolate};
1123 if (!ExecuteWasmDebugBreaks(isolate,
trusted_data, frame)) {
1127 auto* debug_info =
trusted_data->native_module()->GetDebugInfo();
1128 debug_info->ClearStepping(frame);
1135 if (check.InterruptRequested()) {
1137 isolate->stack_guard()->HandleInterrupts();
1140 if (IsException(interrupt_object, isolate))
return interrupt_object;
1141 DCHECK(IsUndefined(interrupt_object, isolate));
1151 ClearThreadInWasmScope flag_scope(isolate);
1156 uint32_t dst_index =
args.positive_smi_value_at(1);
1158 uint32_t src_index =
args.positive_smi_value_at(3);
1159 uint32_t length =
args.positive_smi_value_at(4);
1161 bool overlapping_ranges =
1162 dst_array.
ptr() == src_array.
ptr() &&
1163 (dst_index < src_index ? dst_index + length > src_index
1164 : src_index + length > dst_index);
1166 src_array->map()->wasm_type_info()->element_type();
1168 ObjectSlot dst_slot = dst_array->ElementSlot(dst_index);
1169 ObjectSlot src_slot = src_array->ElementSlot(src_index);
1170 if (overlapping_ranges) {
1171 isolate->heap()->MoveRange(dst_array, dst_slot, src_slot, length,
1174 isolate->heap()->CopyRange(dst_array, dst_slot, src_slot, length,
1178 void* dst =
reinterpret_cast<void*
>(dst_array->ElementAddress(dst_index));
1179 void* src =
reinterpret_cast<void*
>(src_array->ElementAddress(src_index));
1181 if (overlapping_ranges) {
1191 ClearThreadInWasmScope flag_scope(isolate);
1203 ClearThreadInWasmScope flag_scope(isolate);
1208 uint32_t segment_index =
args.positive_smi_value_at(1);
1209 uint32_t
offset =
args.positive_smi_value_at(2);
1210 uint32_t length =
args.positive_smi_value_at(3);
1218 return ThrowWasmError(isolate, MessageTemplate::kWasmTrapArrayTooLarge);
1223 uint32_t length_in_bytes = length * element_size;
1227 trusted_instance_data->data_segment_sizes()->get(segment_index))) {
1228 return ThrowWasmError(isolate,
1229 MessageTemplate::kWasmTrapDataSegmentOutOfBounds);
1233 trusted_instance_data->data_segment_starts()->get(segment_index) +
1235 return *isolate->factory()->NewWasmArrayFromMemory(length, rtt,
1236 element_type, source);
1239 trusted_instance_data->element_segments()->get(segment_index), isolate);
1241 &trusted_instance_data->module()->elem_segments[segment_index];
1245 int segment_length = IsFixedArray(*elem_segment_raw)
1249 return ThrowWasmError(
1250 isolate, MessageTemplate::kWasmTrapElementSegmentOutOfBounds);
1254 isolate->factory()->NewWasmArrayFromElementSegment(
1255 trusted_instance_data, trusted_instance_data, segment_index,
offset,
1256 length, rtt, element_type);
1258 return ThrowWasmError(
1267 ClearThreadInWasmScope flag_scope(isolate);
1272 uint32_t segment_index =
args.positive_smi_value_at(1);
1274 uint32_t array_index =
args.positive_smi_value_at(3);
1276 uint32_t length =
args.positive_smi_value_at(5);
1279 array->map()->wasm_type_info()->element_type();
1283 return ThrowWasmError(isolate,
1284 MessageTemplate::kWasmTrapArrayOutOfBounds);
1293 trusted_instance_data->data_segment_sizes()->get(segment_index))) {
1294 return ThrowWasmError(isolate,
1295 MessageTemplate::kWasmTrapDataSegmentOutOfBounds);
1299 trusted_instance_data->data_segment_starts()->get(segment_index) +
1301 Address dest = array->ElementAddress(array_index);
1302#if V8_TARGET_BIG_ENDIAN
1303 MemCopyAndSwitchEndianness(
reinterpret_cast<void*
>(dest),
1304 reinterpret_cast<void*
>(source), length,
1307 MemCopy(
reinterpret_cast<void*
>(dest),
reinterpret_cast<void*
>(source),
1310 return *isolate->factory()->undefined_value();
1313 trusted_instance_data->element_segments()->get(segment_index), isolate);
1315 &trusted_instance_data->module()->elem_segments[segment_index];
1319 int segment_length = IsFixedArray(*elem_segment_raw)
1323 return ThrowWasmError(
1324 isolate, MessageTemplate::kWasmTrapElementSegmentOutOfBounds);
1327 return ThrowWasmError(isolate,
1328 MessageTemplate::kWasmTrapArrayOutOfBounds);
1336 std::optional<MessageTemplate> opt_error =
1338 trusted_instance_data, segment_index);
1339 if (opt_error.has_value()) {
1340 return ThrowWasmError(isolate, opt_error.value());
1345 trusted_instance_data->element_segments()->get(segment_index)),
1348 isolate->heap()->CopyRange(*array, array->ElementSlot(array_index),
1352 return *isolate->factory()->undefined_value();
1361 isolate->factory()->NewWasmSuspenderObject();
1365 std::unique_ptr<wasm::StackMemory> target_stack =
1366 isolate->stack_pool().GetOrAllocate();
1367 target_stack->jmpbuf()->parent = active_stack;
1368 target_stack->jmpbuf()->stack_limit = target_stack->jslimit();
1369 target_stack->jmpbuf()->sp = target_stack->base();
1372 isolate->isolate_data()->set_active_stack(target_stack.get());
1376 isolate->roots_table().slot(RootIndex::kActiveSuspender);
1377 suspender->set_parent(
1379 suspender->set_stack(isolate, target_stack.get());
1380 active_suspender_slot.
store(*suspender);
1382 target_stack->set_index(isolate->wasm_stacks().size());
1383 isolate->wasm_stacks().emplace_back(std::move(target_stack));
1384 for (
size_t i = 0;
i < isolate->wasm_stacks().
size(); ++
i) {
1395#define RETURN_RESULT_OR_TRAP(call) \
1397 DirectHandle<Object> result; \
1398 if (!(call).ToHandle(&result)) { \
1399 DCHECK(isolate->has_exception()); \
1401 DirectHandle<JSObject> exception(Cast<JSObject>(isolate->exception()), \
1403 DirectHandle<Name> uncatchable = \
1404 isolate->factory()->wasm_uncatchable_symbol(); \
1405 LookupIterator it(isolate, exception, uncatchable, LookupIterator::OWN); \
1406 if (!JSReceiver::HasProperty(&it).FromJust()) { \
1407 JSObject::AddProperty(isolate, exception, uncatchable, \
1408 isolate->factory()->true_value(), NONE); \
1410 return ReadOnlyRoots(isolate).exception(); \
1412 DCHECK(!isolate->has_exception() || \
1413 IsTerminationException(isolate->exception())); \
1420 ClearThreadInWasmScope flag_scope(isolate);
1424 int bits =
args.smi_value_at(1);
1425 DCHECK(bits == 8 || bits == 16);
1428 return ThrowWasmError(isolate, MessageTemplate::kWasmTrapNullDereference);
1431 if (!IsWasmArray(
args[0]))
return ThrowWasmError(isolate, illegal_cast);
1437 MakeStrong(isolate->heap()->wasm_canonical_rtts()->get(expected.
index));
1440 if (obj->map() != expected_map) {
1441 return ThrowWasmError(isolate, illegal_cast);
1449 ClearThreadInWasmScope flag_scope(isolate);
1454 uint32_t memory =
args.positive_smi_value_at(1);
1455 uint32_t utf8_variant_value =
args.positive_smi_value_at(2);
1456 double offset_double =
args.number_value_at(3);
1457 uintptr_t
offset =
static_cast<uintptr_t
>(offset_double);
1460 DCHECK(utf8_variant_value <=
1465 uint64_t mem_size = trusted_instance_data->memory_size(memory);
1467 return ThrowWasmError(isolate, MessageTemplate::kWasmTrapMemOutOfBounds);
1471 trusted_instance_data->memory_base(memory) +
offset, size};
1473 isolate->factory()->NewStringFromUtf8(bytes, utf8_variant);
1474 if (utf8_variant == unibrow::Utf8Variant::kUtf8NoTrap) {
1477 if (result_string.
is_null() && !isolate->has_exception()) {
1478 return *isolate->factory()->wasm_null();
1487 ClearThreadInWasmScope flag_scope(isolate);
1490 uint32_t utf8_variant_value =
args.positive_smi_value_at(0);
1495 DCHECK(utf8_variant_value <=
1500 isolate->factory()->NewStringFromUtf8(array,
start,
end, utf8_variant);
1501 if (utf8_variant == unibrow::Utf8Variant::kUtf8NoTrap) {
1502 DCHECK(!isolate->has_exception());
1503 if (result_string.
is_null()) {
1504 return *isolate->factory()->wasm_null();
1512 ClearThreadInWasmScope flag_scope(isolate);
1517 uint32_t memory =
args.positive_smi_value_at(1);
1518 double offset_double =
args.number_value_at(2);
1519 uintptr_t
offset =
static_cast<uintptr_t
>(offset_double);
1522 uint64_t mem_size = trusted_instance_data->memory_size(memory);
1525 return ThrowWasmError(isolate, MessageTemplate::kWasmTrapMemOutOfBounds);
1528 return ThrowWasmError(isolate, MessageTemplate::kWasmTrapUnalignedAccess);
1531 const uint8_t* bytes = trusted_instance_data->memory_base(memory) +
offset;
1534 {codeunits, size_in_codeunits}));
1538 ClearThreadInWasmScope flag_scope(isolate);
1546 isolate->factory()->NewStringFromUtf16(array,
start,
end));
1550 ClearThreadInWasmScope flag_scope(isolate);
1554 int start =
args.positive_smi_value_at(1);
1555 int length =
args.positive_smi_value_at(2);
1558 return *isolate->factory()->NewCopiedSubstring(
string,
start, length);
1563 ClearThreadInWasmScope flag_scope(isolate);
1570 uint32_t index =
args.positive_smi_value_at(1);
1572 DCHECK_LT(index, trusted_instance_data->module()->stringref_literals.size());
1575 trusted_instance_data->module()->stringref_literals[
index];
1577 trusted_instance_data->native_module()->wire_bytes();
1581 return *isolate->factory()
1582 ->NewStringFromUtf8(string_bytes, unibrow::Utf8Variant::kWtf8)
1587 ClearThreadInWasmScope flag_scope(isolate);
1592 uint32_t segment_index =
args.positive_smi_value_at(1);
1593 uint32_t
offset =
args.positive_smi_value_at(2);
1594 uint32_t length =
args.positive_smi_value_at(3);
1600 trusted_instance_data->data_segment_sizes()->get(segment_index))) {
1601 return ThrowWasmError(isolate,
1602 MessageTemplate::kWasmTrapDataSegmentOutOfBounds);
1606 trusted_instance_data->data_segment_starts()->get(segment_index) +
offset;
1608 {
reinterpret_cast<const uint8_t*
>(
source), length}, variant);
1609 if (variant == unibrow::Utf8Variant::kUtf8NoTrap) {
1610 DCHECK(!isolate->has_exception());
1613 if (
result.is_null())
return *isolate->factory()->wasm_null();
1614 return *
result.ToHandleChecked();
1621template <
typename T>
1628 for (
size_t i = 0;
i < wtf16.
size();
i++) {
1629 int current = wtf16[
i];
1635int MeasureWtf8(Isolate* isolate, DirectHandle<String>
string) {
1638 String::FlatContent content =
string->GetFlatContent(no_gc);
1639 DCHECK(content.IsFlat());
1640 return content.IsOneByte() ? MeasureWtf8(content.ToOneByteVector())
1641 : MeasureWtf8(content.ToUC16Vector());
1643size_t MaxEncodedSize(base::Vector<const uint8_t> wtf16) {
1644 DCHECK(wtf16.size() < std::numeric_limits<size_t>::max() /
1648size_t MaxEncodedSize(base::Vector<const base::uc16> wtf16) {
1649 DCHECK(wtf16.size() < std::numeric_limits<size_t>::max() /
1653bool HasUnpairedSurrogate(base::Vector<const uint8_t> wtf16) {
return false; }
1654bool HasUnpairedSurrogate(base::Vector<const base::uc16> wtf16) {
1657template <
typename T>
1658int EncodeWtf8(base::Vector<char> bytes,
size_t offset,
1665 *message = out_of_bounds;
1669 bool replace_invalid =
false;
1671 case unibrow::Utf8Variant::kWtf8:
1673 case unibrow::Utf8Variant::kUtf8:
1674 if (HasUnpairedSurrogate(wtf16)) {
1675 *message = MessageTemplate::kWasmTrapStringIsolatedSurrogate;
1680 replace_invalid =
true;
1686 bool write_null =
false;
1689 bytes.size() -
offset, write_null, replace_invalid);
1692 return static_cast<int>(
result.bytes_written);
1694template <
typename GetWritableBytes>
1696 DirectHandle<String>
string,
1697 GetWritableBytes get_writable_bytes,
size_t offset,
1704 String::FlatContent content =
string->GetFlatContent(no_gc);
1705 base::Vector<char> dst = get_writable_bytes(no_gc);
1706 written = content.IsOneByte()
1707 ? EncodeWtf8(dst,
offset, content.ToOneByteVector(), variant,
1708 &message, out_of_bounds_message)
1709 : EncodeWtf8(dst,
offset, content.ToUC16Vector(), variant,
1710 &message, out_of_bounds_message);
1713 DCHECK_NE(message, MessageTemplate::kNone);
1714 return ThrowWasmError(isolate, message);
1716 return *isolate->factory()->NewNumberFromInt(written);
1724 int utf8_length = MeasureWtf8(isolate,
string);
1726 out.resize(utf8_length);
1734 EncodeWtf8({out.data(), out.size()}, 0, content.
ToOneByteVector(), variant,
1735 error_cant_happen, oob_cant_happen);
1737 EncodeWtf8({out.data(), out.size()}, 0, content.
ToUC16Vector(), variant,
1738 error_cant_happen, oob_cant_happen);
1743 ClearThreadInWasmScope flag_scope(isolate);
1759 code_units.
size())) {
1762 length = MeasureWtf8(code_units);
1766 return *isolate->factory()->NewNumberFromInt(length);
1770 ClearThreadInWasmScope flag_scope(isolate);
1775 int length = MeasureWtf8(isolate,
string);
1776 return *isolate->factory()->NewNumberFromInt(length);
1780 ClearThreadInWasmScope flag_scope(isolate);
1785 uint32_t memory =
args.positive_smi_value_at(1);
1786 uint32_t utf8_variant_value =
args.positive_smi_value_at(2);
1788 double offset_double =
args.number_value_at(4);
1789 uintptr_t
offset =
static_cast<uintptr_t
>(offset_double);
1791 DCHECK(utf8_variant_value <=
1794 char* memory_start =
1795 reinterpret_cast<char*
>(trusted_instance_data->memory_base(memory));
1797 auto get_writable_bytes =
1799 return {memory_start, trusted_instance_data->memory_size(memory)};
1801 return EncodeWtf8(isolate, utf8_variant,
string, get_writable_bytes,
offset,
1802 MessageTemplate::kWasmTrapMemOutOfBounds);
1806 ClearThreadInWasmScope flag_scope(isolate);
1809 uint32_t utf8_variant_value =
args.positive_smi_value_at(0);
1814 DCHECK(utf8_variant_value <=
1817 auto get_writable_bytes =
1819 return {
reinterpret_cast<char*
>(array->ElementAddress(0)), array->length()};
1821 return EncodeWtf8(isolate, utf8_variant,
string, get_writable_bytes,
start,
1822 MessageTemplate::kWasmTrapArrayOutOfBounds);
1826 ClearThreadInWasmScope flag_scope(isolate);
1830 uint32_t length = MeasureWtf8(isolate,
string);
1838 .GetHeapObjectAssumeWeak()),
1842 auto get_writable_bytes =
1844 return {
reinterpret_cast<char*
>(array->ElementAddress(0)), length};
1848 get_writable_bytes, 0, MessageTemplate::kNone);
1855 ClearThreadInWasmScope flag_scope(isolate);
1860 uint32_t memory =
args.positive_smi_value_at(1);
1862 double offset_double =
args.number_value_at(3);
1863 uintptr_t
offset =
static_cast<uintptr_t
>(offset_double);
1864 uint32_t
start =
args.positive_smi_value_at(4);
1865 uint32_t length =
args.positive_smi_value_at(5);
1869 size_t mem_size = trusted_instance_data->memory_size(memory);
1871 (std::numeric_limits<size_t>::max() /
sizeof(
base::uc16)));
1874 return ThrowWasmError(isolate, MessageTemplate::kWasmTrapMemOutOfBounds);
1877 return ThrowWasmError(isolate, MessageTemplate::kWasmTrapUnalignedAccess);
1880#if defined(V8_TARGET_LITTLE_ENDIAN)
1881 uint16_t* dst =
reinterpret_cast<uint16_t*
>(
1882 trusted_instance_data->memory_base(memory) +
offset);
1884#elif defined(V8_TARGET_BIG_ENDIAN)
1891#error Unknown endianness
1898 ClearThreadInWasmScope flag_scope(isolate);
1902 int wtf8_length = MeasureWtf8(isolate,
string);
1905 auto utf8_variant = unibrow::Utf8Variant::kWtf8;
1906 auto get_writable_bytes =
1908 return {
reinterpret_cast<char*
>(array->begin()),
1909 static_cast<size_t>(wtf8_length)};
1911 EncodeWtf8(isolate, utf8_variant,
string, get_writable_bytes, 0,
1912 MessageTemplate::kWasmTrapArrayOutOfBounds);
1917 ClearThreadInWasmScope flag_scope(isolate);
1922 uint32_t utf8_variant_value =
args.positive_smi_value_at(1);
1924 double addr_double =
args.number_value_at(3);
1925 uintptr_t addr =
static_cast<uintptr_t
>(addr_double);
1928 uint32_t memory =
args.positive_smi_value_at(6);
1930 DCHECK(utf8_variant_value <=
1939 trusted_instance_data->memory_size(memory))) {
1940 return ThrowWasmError(isolate, MessageTemplate::kWasmTrapMemOutOfBounds);
1943 uint8_t* memory_start = trusted_instance_data->memory_base(memory);
1944 const uint8_t* src =
reinterpret_cast<const uint8_t*
>(array->begin() +
start);
1945 uint8_t* dst = memory_start + addr;
1947 std::vector<size_t> surrogates;
1948 if (utf8_variant != unibrow::Utf8Variant::kWtf8) {
1949 unibrow::Wtf8::ScanForSurrogates({src, length}, &surrogates);
1950 if (utf8_variant == unibrow::Utf8Variant::kUtf8 && !surrogates.empty()) {
1951 return ThrowWasmError(isolate,
1952 MessageTemplate::kWasmTrapStringIsolatedSurrogate);
1958 for (
size_t surrogate : surrogates) {
1970 ClearThreadInWasmScope flag_scope(isolate);
1982 return *isolate->factory()
1983 ->NewStringFromUtf8(array,
start,
end,
1984 unibrow::Utf8Variant::kWtf8)
1988#ifdef V8_ENABLE_DRUMBRAKE
1991 v8_flags.wasm_enable_exec_time_histograms);
1995 wasm::WasmExecutionTimer* timer = isolate->wasm_execution_timer();
1998 return ReadOnlyRoots(isolate).undefined_value();
2003 v8_flags.wasm_enable_exec_time_histograms);
2005 HandleScope scope(isolate);
2007 wasm::WasmExecutionTimer* timer = isolate->wasm_execution_timer();
2010 return ReadOnlyRoots(isolate).undefined_value();
2015 ClearThreadInWasmScope flag_scope(isolate);
2021 return *isolate->factory()->LookupSingleCharacterStringFromCode(code_point);
2023 if (code_point > 0x10FFFF) {
2026 return ThrowWasmError(isolate, MessageTemplate::kInvalidCodePoint,
2027 {isolate->factory()->NewNumberFromUint(code_point)});
2036 ->NewRawTwoByteString(
arraysize(char_buffer))
2044 ClearThreadInWasmScope flag_scope(isolate);
2047 uint32_t hash =
string->EnsureHash();
#define SLOW_DCHECK(condition)
static uint16_t LeadSurrogate(uint32_t char_code)
static const int kNoPreviousCharacter
static const uchar kMaxNonSurrogateCharCode
static uint16_t TrailSurrogate(uint32_t char_code)
static bool HasUnpairedSurrogate(const uint16_t *code_units, size_t length)
static const uchar kBadChar
static unsigned Length(uchar chr, int previous)
static const unsigned kMaxEncodedSize
static const unsigned kMax8BitCodeUnitSize
static const unsigned kMax16BitCodeUnitSize
static unsigned Encode(char *out, uchar c, int previous, bool replace_invalid=false)
Vector< T > SubVector(size_t from, size_t to) const
constexpr size_t size() const
constexpr T * begin() const
static constexpr int kContextOrFrameTypeOffset
static constexpr int kCallerFPOffset
static size_t DeleteForWasm(Isolate *isolate)
void store(Tagged< Object > value) const
static V8_EXPORT_PRIVATE Tagged< Object > WaitWasm64(Isolate *isolate, DirectHandle< JSArrayBuffer > array_buffer, size_t addr, int64_t value, int64_t rel_timeout_ns)
static V8_EXPORT_PRIVATE Tagged< Object > WaitWasm32(Isolate *isolate, DirectHandle< JSArrayBuffer > array_buffer, size_t addr, int32_t value, int64_t rel_timeout_ns)
static Address c_entry_fp(ThreadLocalTop *thread)
static V8_EXPORT_PRIVATE void AddProperty(Isolate *isolate, DirectHandle< JSObject > object, DirectHandle< Name > name, DirectHandle< Object > value, PropertyAttributes attributes)
V8_INLINE DirectHandle< T > ToHandleChecked() const
V8_INLINE bool is_null() const
static double NumberValue(Tagged< Number > obj)
RuntimeArgumentsWithoutHandles(int length, Address *arguments)
V8_INLINE DirectHandle< S > at(int index) const
static constexpr Tagged< Smi > FromInt(int value)
static constexpr Tagged< Smi > zero()
static constexpr int kMaxValue
static constexpr Type MarkerToType(intptr_t marker)
base::Vector< const uint8_t > ToOneByteVector() const
base::Vector< const base::uc16 > ToUC16Vector() const
static void WriteToFlat(Tagged< String > source, SinkCharT *sink, uint32_t start, uint32_t length)
static const uint32_t kMaxLength
static V8_INLINE HandleType< String > Flatten(Isolate *isolate, HandleType< T > string, AllocationType allocation=AllocationType::kYoung)
V8_INLINE constexpr StorageType ptr() const
constexpr bool IsCleared() const
bool GetHeapObject(Tagged< HeapObject > *result) const
constexpr bool IsWeakOrCleared() const
Tagged< HeapObject > GetHeapObjectAssumeWeak() const
constexpr V8_INLINE bool IsSmi() const
static constexpr int MaxLength(uint32_t element_size_bytes)
static DirectHandle< WasmExceptionPackage > New(Isolate *isolate, DirectHandle< WasmExceptionTag > exception_tag, int encoded_size)
static bool IsWasmExternalFunction(Tagged< Object > object)
static V8_EXPORT_PRIVATE DirectHandle< JSFunction > GetOrCreateExternal(DirectHandle< WasmInternalFunction > internal)
static constexpr int kFeedbackVectorOffset
static V8_EXPORT_PRIVATE int32_t Grow(Isolate *, DirectHandle< WasmMemoryObject >, uint32_t pages)
static MaybeDirectHandle< FixedArray > CheckBreakPoints(Isolate *, DirectHandle< Script >, int position, StackFrameId stack_frame_id)
static constexpr int kOnEntryBreakpointPosition
static DirectHandle< WasmStruct > AllocateDescriptorUninitialized(Isolate *isolate, DirectHandle< WasmTrustedInstanceData > trusted_data, wasm::ModuleTypeIndex index, DirectHandle< Map > map)
static V8_EXPORT_PRIVATE DirectHandle< Object > Get(Isolate *isolate, DirectHandle< WasmTableObject > table, uint32_t index)
static V8_EXPORT_PRIVATE void Fill(Isolate *isolate, DirectHandle< WasmTableObject > table, uint32_t start, DirectHandle< Object > entry, uint32_t count)
static V8_EXPORT_PRIVATE void Set(Isolate *isolate, DirectHandle< WasmTableObject > table, uint32_t index, DirectHandle< Object > entry)
static V8_EXPORT_PRIVATE int Grow(Isolate *isolate, DirectHandle< WasmTableObject > table, uint32_t count, DirectHandle< Object > init_value)
static DirectHandle< WasmFuncRef > GetOrCreateFuncRef(Isolate *isolate, DirectHandle< WasmTrustedInstanceData > trusted_instance_data, int function_index)
static std::optional< MessageTemplate > InitTableEntries(Isolate *isolate, DirectHandle< WasmTrustedInstanceData > trusted_instance_data, DirectHandle< WasmTrustedInstanceData > shared_trusted_instance_data, uint32_t table_index, uint32_t segment_index, uint32_t dst, uint32_t src, uint32_t count) V8_WARN_UNUSED_RESULT
static bool CopyTableEntries(Isolate *isolate, DirectHandle< WasmTrustedInstanceData > trusted_instance_data, uint32_t table_dst_index, uint32_t table_src_index, uint32_t dst, uint32_t src, uint32_t count) V8_WARN_UNUSED_RESULT
static constexpr CanonicalValueType FromRawBitField(uint32_t bits)
std::pair< WasmOpcode, uint32_t > read_prefixed_opcode(const uint8_t *pc, Name< ValidationTag > name="prefixed opcode")
static DirectHandle< Code > CompileJSToWasmWrapper(Isolate *isolate, const CanonicalSig *sig, CanonicalTypeIndex sig_index)
ImportCallKind kind() const
CanonicalTypeIndex FindIndex_Slow(const CanonicalSig *sig) const
static constexpr CanonicalTypeIndex kPredefinedArrayI16Index
V8_EXPORT_PRIVATE const CanonicalSig * LookupFunctionSignature(CanonicalTypeIndex index) const
static constexpr CanonicalTypeIndex kPredefinedArrayI8Index
constexpr int value_kind_size() const
static const int kLastUsedBit
constexpr bool is_reference() const
constexpr bool is_numeric() const
static void SetRuntimeLastWasmError(Isolate *isolate, MessageTemplate message)
static constexpr bool IsPrefixOpcode(WasmOpcode)
#define RUNTIME_FUNCTION(Name)
#define THROW_NEW_ERROR_RETURN_FAILURE(isolate, call)
#define RETURN_RESULT_OR_FAILURE(isolate, call)
base::Vector< const DirectHandle< Object > > args
SourcePositionTable * source_positions
ZoneVector< RpoNumber > & result
FunctionLiteral * literal
InstructionOperand source
constexpr bool IsInBounds(T index, T length, T max)
constexpr bool IsInRange(T value, U lower_limit, U higher_limit)
constexpr Vector< T > VectorOf(T *start, size_t size)
bool IsTrapHandlerEnabled()
TH_DISABLE_ASAN bool IsThreadInWasm()
void TierUpNowForTesting(Isolate *isolate, Tagged< WasmTrustedInstanceData > trusted_instance_data, int func_index)
WasmImportWrapperCache * GetWasmImportWrapperCache()
std::optional< MessageTemplate > InitializeElementSegment(Zone *zone, Isolate *isolate, DirectHandle< WasmTrustedInstanceData > trusted_instance_data, DirectHandle< WasmTrustedInstanceData > shared_trusted_instance_data, uint32_t segment_index)
void TriggerTierUp(Isolate *isolate, Tagged< WasmTrustedInstanceData > trusted_instance_data, int func_index)
constexpr IndependentValueType kWasmI8
int JumpTableOffset(const WasmModule *module, int func_index)
TypeCanonicalizer * GetTypeCanonicalizer()
void ThrowLazyCompilationError(Isolate *isolate, const NativeModule *native_module, int func_index)
int declared_function_index(const WasmModule *module, int func_index)
@ kJSFunctionArityMismatch
constexpr size_t kV8MaxWasmTableSize
constexpr size_t kV8MaxWasmStringLiterals
bool CompileLazy(Isolate *isolate, Tagged< WasmTrustedInstanceData > trusted_instance_data, int func_index)
MessageTemplate MessageTemplateFromInt(int message_id)
constexpr const char * ToString(DeoptimizeKind kind)
PerThreadAssertScopeDebugOnly< false, SAFEPOINTS_ASSERT, HEAP_ALLOCATION_ASSERT > DisallowGarbageCollection
Tagged< T > MakeStrong(Tagged< T > value)
bool IsNumber(Tagged< Object > obj)
Tagged(T object) -> Tagged< T >
kWasmInternalFunctionIndirectPointerTag instance_data
V8_INLINE constexpr bool IsSmi(TaggedImpl< kRefType, StorageType > obj)
kStaticElementsTemplateOffset kInstancePropertiesTemplateOffset Tagged< FixedArray >
V8_INLINE DirectHandle< T > direct_handle(Tagged< T > object, Isolate *isolate)
kWasmInternalFunctionIndirectPointerTag kProtectedInstanceDataOffset sig
V8_EXPORT_PRIVATE void MemMove(void *dest, const void *src, size_t size)
uint32_t NumberToUint32(Tagged< Object > number)
typename detail::FlattenUnionHelper< Union<>, Ts... >::type UnionOf
int32_t NumberToInt32(Tagged< Object > number)
Tagged< MaybeWeak< T > > MakeWeak(Tagged< T > value)
void CopyChars(DstType *dst, const SrcType *src, size_t count) V8_NONNULL(1
V8_EXPORT_PRIVATE FlagValues v8_flags
void ToUtf8Lossy(Isolate *isolate, DirectHandle< String > string, std::string &out)
static constexpr Address kNullAddress
void MemCopy(void *dest, const void *src, size_t size)
constexpr uint32_t kMaxUInt32
template const char * string
Tagged< To > Cast(Tagged< From > value, const v8::SourceLocation &loc=INIT_SOURCE_LOCATION_IN_DEBUG)
const size_t segment_offset
StackFrameIterator frame_iterator_
#define RETURN_RESULT_OR_TRAP(call)
const bool is_thread_in_wasm_
#define DCHECK_LE(v1, v2)
#define DCHECK_NOT_NULL(val)
#define DCHECK_NE(v1, v2)
#define DCHECK(condition)
#define DCHECK_LT(v1, v2)
#define DCHECK_EQ(v1, v2)
#define DCHECK_GT(v1, v2)
std::vector< FrameSummary > frames
ModuleTypeIndex sig_index
std::vector< WasmExport > export_table
CanonicalTypeIndex canonical_sig_id(ModuleTypeIndex index) const
#define TRACE_EVENT1(category_group, name, arg1_name, arg1_val)
#define V8_UNLIKELY(condition)