mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-04-20 11:36:10 +00:00
LibGC: Teach Swift bindings about Cell and Cell::Visitor
Add the proper annotations for the Cell and Cell::Visitor classes to be visible in Swift. This lets us remove some OpaquePointer shinangians in the Swift bindings.
This commit is contained in:
parent
4ab89d8bbb
commit
8554ee386e
Notes:
github-actions[bot]
2025-04-03 22:49:27 +00:00
Author: https://github.com/ADKaster Commit: https://github.com/LadybirdBrowser/ladybird/commit/8554ee386e9 Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/4053
7 changed files with 43 additions and 48 deletions
|
@ -72,17 +72,17 @@ public:
|
|||
visit_impl(*cell);
|
||||
}
|
||||
|
||||
void visit(Cell& cell)
|
||||
void visit(Cell& cell) SWIFT_NAME(visitRef(_:))
|
||||
{
|
||||
visit_impl(cell);
|
||||
}
|
||||
|
||||
void visit(Cell const* cell)
|
||||
void visit(Cell const* cell) SWIFT_NAME(visitConst(_:))
|
||||
{
|
||||
visit(const_cast<Cell*>(cell));
|
||||
}
|
||||
|
||||
void visit(Cell const& cell)
|
||||
void visit(Cell const& cell) SWIFT_NAME(visitConstRef(_:))
|
||||
{
|
||||
visit(const_cast<Cell&>(cell));
|
||||
}
|
||||
|
@ -157,7 +157,7 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
void visit(NanBoxedValue const& value);
|
||||
void visit(NanBoxedValue const& value) SWIFT_NAME(visitValue(_:));
|
||||
|
||||
// Allow explicitly ignoring a GC-allocated member in a visit_edges implementation instead
|
||||
// of just not using it.
|
||||
|
|
|
@ -15,38 +15,15 @@ extension GC.Heap {
|
|||
}
|
||||
}
|
||||
|
||||
// FIXME: Cell and Cell::Visitor are not imported properly, so we have to treat them as OpaquePointer
|
||||
public protocol HeapAllocatable {
|
||||
static func allocate(on heap: GC.Heap) -> UnsafeMutablePointer<Self>
|
||||
|
||||
init(cell: OpaquePointer)
|
||||
init(cell: GC.Cell)
|
||||
|
||||
func finalize()
|
||||
func visitEdges(_ visitor: OpaquePointer)
|
||||
func visitEdges(_ visitor: GC.Cell.Visitor)
|
||||
|
||||
var cell: OpaquePointer { get }
|
||||
}
|
||||
|
||||
// FIXME: Figure out why other modules can't conform to HeapAllocatable
|
||||
public struct HeapString: HeapAllocatable {
|
||||
public var string: Swift.String
|
||||
|
||||
public init(cell: OpaquePointer) {
|
||||
self.cell = cell
|
||||
self.string = ""
|
||||
}
|
||||
|
||||
// FIXME: HeapAllocatable cannot be exposed to C++ yet, so we're off to void* paradise
|
||||
public static func create(on heap: GC.Heap, string: Swift.String) -> OpaquePointer {
|
||||
// NOTE: GC must be deferred so that a collection during allocation doesn't get tripped
|
||||
// up looking for the Cell pointer on the stack or in a register when it might only exist in the heap
|
||||
precondition(heap.is_gc_deferred())
|
||||
let heapString = allocate(on: heap)
|
||||
heapString.pointee.string = string
|
||||
return heapString.pointee.cell
|
||||
}
|
||||
|
||||
public var cell: OpaquePointer
|
||||
var cell: GC.Cell { get }
|
||||
}
|
||||
|
||||
// Here be dragons
|
||||
|
@ -64,7 +41,7 @@ func asHeapAllocatableType(_ typeMetadata: UnsafeMutableRawPointer) -> any HeapA
|
|||
}
|
||||
|
||||
extension HeapAllocatable {
|
||||
fileprivate static func initializeFromFFI(at this: UnsafeMutableRawPointer, cell: OpaquePointer) {
|
||||
fileprivate static func initializeFromFFI(at this: UnsafeMutableRawPointer, cell: GC.Cell) {
|
||||
this.assumingMemoryBound(to: Self.self).initialize(to: Self.self.init(cell: cell))
|
||||
}
|
||||
|
||||
|
@ -76,7 +53,7 @@ extension HeapAllocatable {
|
|||
this.assumingMemoryBound(to: Self.self).pointee.finalize()
|
||||
}
|
||||
|
||||
fileprivate static func visitEdgesFromFFI(at this: UnsafeMutableRawPointer, visitor: OpaquePointer) {
|
||||
fileprivate static func visitEdgesFromFFI(at this: UnsafeMutableRawPointer, visitor: GC.Cell.Visitor) {
|
||||
this.assumingMemoryBound(to: Self.self).pointee.visitEdges(visitor)
|
||||
}
|
||||
|
||||
|
@ -101,5 +78,5 @@ extension HeapAllocatable {
|
|||
}
|
||||
|
||||
public func finalize() {}
|
||||
public func visitEdges(_ visitor: OpaquePointer) {}
|
||||
public func visitEdges(_ visitor: GC.Cell.Visitor) {}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ if (SWIFT_TESTING)
|
|||
cmake_path(GET _SWIFT_TESTING_DIR PARENT_PATH _SWIFT_TESTING_TARGETLESS_DIR)
|
||||
set_target_properties(SwiftTesting::SwiftTesting PROPERTIES
|
||||
INTERFACE_COMPILE_OPTIONS "$<$<COMPILE_LANGUAGE:Swift>:SHELL:-load-plugin-library ${_SWIFT_TESTING_TARGETLESS_DIR}/host/plugins/libTestingMacros.so>"
|
||||
INTERFACE_LINK_OPTIONS "-load-plugin-library;${_SWIFT_TESTING_TARGETLESS_DIR}/host/plugins/libTestingMacros.so"
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
|
|
@ -6,12 +6,21 @@ if (ENABLE_SWIFT)
|
|||
TestHeap.cpp
|
||||
TestInterop.cpp
|
||||
)
|
||||
|
||||
# FIXME: Swift doesn't seem to like object libraries for @main
|
||||
target_sources(TestGCSwift PRIVATE ../Resources/SwiftTestMain.swift)
|
||||
|
||||
generate_clang_module_map(TestGCSwift)
|
||||
|
||||
set_target_properties(TestGCSwift PROPERTIES SUFFIX .swift-testing)
|
||||
target_include_directories(TestGCSwift PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
target_link_libraries(TestGCSwift PRIVATE AK LibGC SwiftTesting::SwiftTesting)
|
||||
|
||||
get_property(testing_compile_options TARGET SwiftTesting::SwiftTesting PROPERTY INTERFACE_LINK_OPTIONS)
|
||||
|
||||
add_swift_target_properties(TestGCSwift
|
||||
LAGOM_LIBRARIES AK LibGC
|
||||
COMPILE_DEFINITIONS LIBGC_WORKAROUND_BOOL_BITFIELD
|
||||
COMPILE_OPTIONS ${testing_compile_options} -enable-experimental-feature Extern
|
||||
)
|
||||
add_test(NAME TestGCSwift COMMAND TestGCSwift)
|
||||
endif()
|
||||
|
|
|
@ -6,14 +6,28 @@
|
|||
|
||||
import AK
|
||||
import GC
|
||||
import GCTesting
|
||||
@_exported import TestGCSwiftCxx
|
||||
import Testing
|
||||
|
||||
// FIXME: We want a type declared *here* for HeapString, but it gives a compiler warning:
|
||||
// error: type 'GCString' cannot conform to protocol 'HeapAllocatable' because it has requirements that cannot be satisfied
|
||||
// Even using the same exact code from LibGC/Heap+Swift.swift
|
||||
// This is likely because one of the required types for HeapAllocatable is not fully imported from C++ and thus can't
|
||||
// be re-exported by the GC module.
|
||||
public struct HeapString: HeapAllocatable {
|
||||
public var string: Swift.String
|
||||
|
||||
public init(cell: GC.Cell) {
|
||||
self.cell = cell
|
||||
self.string = ""
|
||||
}
|
||||
|
||||
public static func create(on heap: GC.Heap, string: Swift.String) -> GC.Cell {
|
||||
// NOTE: GC must be deferred so that a collection during allocation doesn't get tripped
|
||||
// up looking for the Cell pointer on the stack or in a register when it might only exist in the heap
|
||||
precondition(heap.is_gc_deferred())
|
||||
let heapString = allocate(on: heap)
|
||||
heapString.pointee.string = string
|
||||
return heapString.pointee.cell
|
||||
}
|
||||
|
||||
public var cell: GC.Cell
|
||||
}
|
||||
|
||||
@Suite(.serialized)
|
||||
struct TestGCSwiftBindings {
|
||||
|
|
|
@ -7,9 +7,9 @@
|
|||
#include "TestInterop.h"
|
||||
#include "TestHeap.h"
|
||||
#include <AK/TypeCasts.h>
|
||||
#include <LibGC-Swift.h>
|
||||
#include <LibGC/ForeignCell.h>
|
||||
#include <LibGC/Heap.h>
|
||||
#include <TestGCSwift-Swift.h>
|
||||
|
||||
#define COLLECT heap.collect_garbage(GC::Heap::CollectionType::CollectGarbage)
|
||||
#define COLLECT_ALL heap.collect_garbage(GC::Heap::CollectionType::CollectEverything)
|
||||
|
@ -20,7 +20,7 @@ void test_interop()
|
|||
|
||||
COLLECT_ALL;
|
||||
|
||||
auto string = GC::ForeignRef<GC::HeapString>::allocate(heap, "Hello, World!");
|
||||
auto string = GC::ForeignRef<TestGCSwift::HeapString>::allocate(heap, "Hello, World!");
|
||||
|
||||
COLLECT;
|
||||
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
module GCTesting {
|
||||
header "TestHeap.h"
|
||||
header "TestInterop.h"
|
||||
requires cplusplus
|
||||
export *
|
||||
}
|
Loading…
Add table
Reference in a new issue