electron/patches/v8/cherry-pick-901377bb2f3b.patch
Keeley Hammond 1ec867c8a1
chore: cherry-pick 11 changes from 3-M126 (#43141)
* chore: [30-x-y] cherry-pick 11 changes from 3-M126

* d54105311590 from chromium
* 43b8b682d05c from chromium
* c5dd8839bfaf from chromium
* cdbc1d9684a3 from v8
* 38e4483e47f9 from chromium
* 70d2fe6b7c47 from v8
* 901377bb2f3b from v8
* 1b9040817119 from chromium
* bb28367eed73 from v8
* 99cafbf4b4b9 from chromium
* bc545b15a0ee from v8

* chore: update patches

* 5639725: [wasm] Fix scanning of wasm-to-js params | https://chromium-review.googlesource.com/c/v8/v8/+/5639725

* 5672472: [M120-LTS] Prevent script injection on reload when racing with a navigation | https://chromium-review.googlesource.com/c/chromium/src/+/5672472
2024-08-02 10:11:51 +02:00

221 lines
10 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Thibaud Michaud <thibaudm@chromium.org>
Date: Fri, 21 Jun 2024 16:31:15 +0200
Subject: Fix scanning of wasm-to-js params
Wasm-to-js wrappers are sometimes compiled as on-heap Code objects, for
example when tiering-up from a WasmFuncRef call origin. The frames of
these functions are mapped to a subclass of TypedFrame, however
TypedFrame::Iterate() only supports iterating the generic wasm-to-js
wrapper.
Add support for iterating the tagged parameters of optimized wasm-to-js
wrappers in TypedFrame::Iterate. For this we also add two 16-bit fields
in the Code object to encode the incoming tagged parameter region, which
we would normally find in the WasmCode data.
R=jkummerow@chromium.org
Fixed: 346597059
Change-Id: I425619fca86c38f91f1ca9cbeb70e7b5a7b2d6c1
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/5639725
Reviewed-by: Jakob Kummerow <jkummerow@chromium.org>
Commit-Queue: Thibaud Michaud <thibaudm@chromium.org>
Cr-Commit-Position: refs/heads/main@{#94589}
diff --git a/src/compiler/pipeline.cc b/src/compiler/pipeline.cc
index 0181588337df73bfa97220d895733c40b92bd40b..033469e626ffb35846ae5114632f3dc000400935 100644
--- a/src/compiler/pipeline.cc
+++ b/src/compiler/pipeline.cc
@@ -2295,6 +2295,14 @@ CompilationJob::Status FinalizeWrapperCompilation(
Handle<AbstractCode>::cast(code),
info->GetDebugName().get()));
}
+ // Set the wasm-to-js specific code fields needed to scan the incoming stack
+ // parameters.
+ if (code->kind() == CodeKind::WASM_TO_JS_FUNCTION) {
+ code->set_wasm_js_tagged_parameter_count(
+ call_descriptor->GetTaggedParameterSlots() & 0xffff);
+ code->set_wasm_js_first_tagged_parameter(
+ call_descriptor->GetTaggedParameterSlots() >> 16);
+ }
return CompilationJob::SUCCEEDED;
}
return CompilationJob::FAILED;
diff --git a/src/diagnostics/objects-printer.cc b/src/diagnostics/objects-printer.cc
index 7677022ce31c1b8ead0cc2eb37fb505b750639be..12bd5b8fd27f67c73938550acc4af1857eace59a 100644
--- a/src/diagnostics/objects-printer.cc
+++ b/src/diagnostics/objects-printer.cc
@@ -2102,7 +2102,14 @@ void Code::CodePrint(std::ostream& os, const char* name, Address current_pc) {
os << "\n - instruction_size: " << instruction_size();
os << "\n - metadata_size: " << metadata_size();
- os << "\n - inlined_bytecode_size: " << inlined_bytecode_size();
+ if (kind() != CodeKind::WASM_TO_JS_FUNCTION) {
+ os << "\n - inlined_bytecode_size: " << inlined_bytecode_size();
+ } else {
+ os << "\n - wasm_js_tagged_parameter_count: "
+ << wasm_js_tagged_parameter_count();
+ os << "\n - wasm_js_first_tagged_parameter: "
+ << wasm_js_first_tagged_parameter();
+ }
os << "\n - osr_offset: " << osr_offset();
os << "\n - handler_table_offset: " << handler_table_offset();
os << "\n - unwinding_info_offset: " << unwinding_info_offset();
diff --git a/src/execution/frames.cc b/src/execution/frames.cc
index 92dff2f7e8c8f72e38eef4feb5b10ace9fe2535c..2693fb2a859dc7489ef802c3064beace88608415 100644
--- a/src/execution/frames.cc
+++ b/src/execution/frames.cc
@@ -1562,7 +1562,7 @@ void WasmFrame::Iterate(RootVisitor* v) const {
frame_header_limit);
}
-void TypedFrame::IterateParamsOfWasmToJSWrapper(RootVisitor* v) const {
+void TypedFrame::IterateParamsOfGenericWasmToJSWrapper(RootVisitor* v) const {
Tagged<Object> maybe_signature = Tagged<Object>(
Memory<Address>(fp() + WasmToJSWrapperConstants::kSignatureOffset));
if (IsSmi(maybe_signature)) {
@@ -1678,6 +1678,18 @@ void TypedFrame::IterateParamsOfWasmToJSWrapper(RootVisitor* v) const {
}
}
}
+
+void TypedFrame::IterateParamsOfOptimizedWasmToJSWrapper(RootVisitor* v) const {
+ Tagged<GcSafeCode> code = GcSafeLookupCode();
+ if (code->wasm_js_tagged_parameter_count() > 0) {
+ FullObjectSlot tagged_parameter_base(&Memory<Address>(caller_sp()));
+ tagged_parameter_base += code->wasm_js_first_tagged_parameter();
+ FullObjectSlot tagged_parameter_limit =
+ tagged_parameter_base + code->wasm_js_tagged_parameter_count();
+ v->VisitRootPointers(Root::kStackRoots, nullptr, tagged_parameter_base,
+ tagged_parameter_limit);
+ }
+}
#endif // V8_ENABLE_WEBASSEMBLY
void TypedFrame::Iterate(RootVisitor* v) const {
@@ -1709,10 +1721,13 @@ void TypedFrame::Iterate(RootVisitor* v) const {
CHECK(entry->code.has_value());
Tagged<GcSafeCode> code = entry->code.value();
#if V8_ENABLE_WEBASSEMBLY
- bool is_wasm_to_js =
+ bool is_generic_wasm_to_js =
code->is_builtin() && code->builtin_id() == Builtin::kWasmToJsWrapperCSA;
- if (is_wasm_to_js) {
- IterateParamsOfWasmToJSWrapper(v);
+ bool is_optimized_wasm_to_js = this->type() == WASM_TO_JS_FUNCTION;
+ if (is_generic_wasm_to_js) {
+ IterateParamsOfGenericWasmToJSWrapper(v);
+ } else if (is_optimized_wasm_to_js) {
+ IterateParamsOfOptimizedWasmToJSWrapper(v);
}
#endif // V8_ENABLE_WEBASSEMBLY
DCHECK(code->is_turbofanned());
@@ -1745,10 +1760,14 @@ void TypedFrame::Iterate(RootVisitor* v) const {
// wrapper switched to before pushing the outgoing stack parameters and
// calling the target. It marks the limit of the stack param area, and is
// distinct from the beginning of the spill area.
- Address central_stack_sp =
- Memory<Address>(fp() + WasmToJSWrapperConstants::kCentralStackSPOffset);
+ int central_stack_sp_offset =
+ is_generic_wasm_to_js
+ ? WasmToJSWrapperConstants::kCentralStackSPOffset
+ : WasmImportWrapperFrameConstants::kCentralStackSPOffset;
+ Address central_stack_sp = Memory<Address>(fp() + central_stack_sp_offset);
FullObjectSlot parameters_limit(
- is_wasm_to_js && central_stack_sp != kNullAddress
+ (is_generic_wasm_to_js || is_optimized_wasm_to_js) &&
+ central_stack_sp != kNullAddress
? central_stack_sp
: frame_header_base.address() - spill_slots_size);
#else
diff --git a/src/execution/frames.h b/src/execution/frames.h
index 081c74bf124ccfa57e4b40f75cbe42b00c771b2e..908239b4161235aeda04fe5526ddea8d56b09425 100644
--- a/src/execution/frames.h
+++ b/src/execution/frames.h
@@ -634,7 +634,8 @@ class TypedFrame : public CommonFrame {
Tagged<HeapObject> unchecked_code() const override { return {}; }
void Iterate(RootVisitor* v) const override;
- void IterateParamsOfWasmToJSWrapper(RootVisitor* v) const;
+ void IterateParamsOfGenericWasmToJSWrapper(RootVisitor* v) const;
+ void IterateParamsOfOptimizedWasmToJSWrapper(RootVisitor* v) const;
protected:
inline explicit TypedFrame(StackFrameIteratorBase* iterator);
diff --git a/src/objects/code-inl.h b/src/objects/code-inl.h
index baaced29afdbc87eae1c34b8df779e17e41410c4..1e1d66a87ee633cbdb49265444f53b5db790d9dd 100644
--- a/src/objects/code-inl.h
+++ b/src/objects/code-inl.h
@@ -48,6 +48,8 @@ GCSAFE_CODE_FWD_ACCESSOR(bool, has_tagged_outgoing_params)
GCSAFE_CODE_FWD_ACCESSOR(bool, marked_for_deoptimization)
GCSAFE_CODE_FWD_ACCESSOR(Tagged<Object>, raw_instruction_stream)
GCSAFE_CODE_FWD_ACCESSOR(int, stack_slots)
+GCSAFE_CODE_FWD_ACCESSOR(uint16_t, wasm_js_tagged_parameter_count)
+GCSAFE_CODE_FWD_ACCESSOR(uint16_t, wasm_js_first_tagged_parameter)
GCSAFE_CODE_FWD_ACCESSOR(Address, constant_pool)
GCSAFE_CODE_FWD_ACCESSOR(Address, safepoint_table_address)
#undef GCSAFE_CODE_FWD_ACCESSOR
@@ -428,6 +430,31 @@ void Code::set_inlined_bytecode_size(unsigned size) {
RELAXED_WRITE_UINT_FIELD(*this, kInlinedBytecodeSizeOffset, size);
}
+// For optimized on-heap wasm-js wrappers, we repurpose the (otherwise unused)
+// 32-bit InlinedBytecodeSize field to encode two 16 values needed for scanning
+// the frame: the count and starting offset of incoming tagged parameters.
+// TODO(wasm): Eventually the wrappers should be managed off-heap by the wasm
+// engine. Remove these accessors when that is the case.
+void Code::set_wasm_js_tagged_parameter_count(uint16_t count) {
+ DCHECK_EQ(kind(), CodeKind::WASM_TO_JS_FUNCTION);
+ RELAXED_WRITE_UINT16_FIELD(*this, kInlinedBytecodeSizeOffset, count);
+}
+
+uint16_t Code::wasm_js_tagged_parameter_count() const {
+ DCHECK_EQ(kind(), CodeKind::WASM_TO_JS_FUNCTION);
+ return RELAXED_READ_UINT16_FIELD(*this, kInlinedBytecodeSizeOffset);
+}
+
+void Code::set_wasm_js_first_tagged_parameter(uint16_t count) {
+ DCHECK_EQ(kind(), CodeKind::WASM_TO_JS_FUNCTION);
+ RELAXED_WRITE_UINT16_FIELD(*this, kInlinedBytecodeSizeOffset + 2, count);
+}
+
+uint16_t Code::wasm_js_first_tagged_parameter() const {
+ DCHECK_EQ(kind(), CodeKind::WASM_TO_JS_FUNCTION);
+ return RELAXED_READ_UINT16_FIELD(*this, kInlinedBytecodeSizeOffset + 2);
+}
+
BytecodeOffset Code::osr_offset() const {
return BytecodeOffset(RELAXED_READ_INT32_FIELD(*this, kOsrOffsetOffset));
}
diff --git a/src/objects/code.h b/src/objects/code.h
index 9a079a94ba0126b24532362a0ce233477f42c221..1da011899807125d6dc9ffb6d56622f5f15ad465 100644
--- a/src/objects/code.h
+++ b/src/objects/code.h
@@ -124,6 +124,15 @@ class Code : public ExposedTrustedObject {
// [deoptimization_data]: Array containing data for deopt for non-baseline
// code.
DECL_ACCESSORS(deoptimization_data, Tagged<TrustedFixedArray>)
+ // [parameter_count]: The number of formal parameters, including the
+ // receiver. Currently only available for optimized functions.
+ // TODO(saelo): make this always available. This is just a matter of figuring
+ // out how to obtain the parameter count during code generation when no
+ // BytecodeArray is available from which it can be copied.
+ DECL_PRIMITIVE_ACCESSORS(parameter_count, uint16_t)
+ inline uint16_t parameter_count_without_receiver() const;
+ DECL_PRIMITIVE_ACCESSORS(wasm_js_tagged_parameter_count, uint16_t)
+ DECL_PRIMITIVE_ACCESSORS(wasm_js_first_tagged_parameter, uint16_t)
// Whether this type of Code uses deoptimization data, in which case the
// deoptimization_data field will be populated.
@@ -503,6 +512,10 @@ class GcSafeCode : public HeapObject {
inline bool CanDeoptAt(Isolate* isolate, Address pc) const;
inline Tagged<Object> raw_instruction_stream(
PtrComprCageBase code_cage_base) const;
+ // The two following accessors repurpose the InlinedBytecodeSize field, see
+ // comment in code-inl.h.
+ inline uint16_t wasm_js_tagged_parameter_count() const;
+ inline uint16_t wasm_js_first_tagged_parameter() const;
private:
OBJECT_CONSTRUCTORS(GcSafeCode, HeapObject);