mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-08-01 13:49:16 +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: 8554ee386e
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);
|
visit_impl(*cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
void visit(Cell& cell)
|
void visit(Cell& cell) SWIFT_NAME(visitRef(_:))
|
||||||
{
|
{
|
||||||
visit_impl(cell);
|
visit_impl(cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
void visit(Cell const* cell)
|
void visit(Cell const* cell) SWIFT_NAME(visitConst(_:))
|
||||||
{
|
{
|
||||||
visit(const_cast<Cell*>(cell));
|
visit(const_cast<Cell*>(cell));
|
||||||
}
|
}
|
||||||
|
|
||||||
void visit(Cell const& cell)
|
void visit(Cell const& cell) SWIFT_NAME(visitConstRef(_:))
|
||||||
{
|
{
|
||||||
visit(const_cast<Cell&>(cell));
|
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
|
// Allow explicitly ignoring a GC-allocated member in a visit_edges implementation instead
|
||||||
// of just not using it.
|
// 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 {
|
public protocol HeapAllocatable {
|
||||||
static func allocate(on heap: GC.Heap) -> UnsafeMutablePointer<Self>
|
static func allocate(on heap: GC.Heap) -> UnsafeMutablePointer<Self>
|
||||||
|
|
||||||
init(cell: OpaquePointer)
|
init(cell: GC.Cell)
|
||||||
|
|
||||||
func finalize()
|
func finalize()
|
||||||
func visitEdges(_ visitor: OpaquePointer)
|
func visitEdges(_ visitor: GC.Cell.Visitor)
|
||||||
|
|
||||||
var cell: OpaquePointer { get }
|
var cell: GC.Cell { 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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Here be dragons
|
// Here be dragons
|
||||||
|
@ -64,7 +41,7 @@ func asHeapAllocatableType(_ typeMetadata: UnsafeMutableRawPointer) -> any HeapA
|
||||||
}
|
}
|
||||||
|
|
||||||
extension HeapAllocatable {
|
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))
|
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()
|
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)
|
this.assumingMemoryBound(to: Self.self).pointee.visitEdges(visitor)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,5 +78,5 @@ extension HeapAllocatable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public func finalize() {}
|
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)
|
cmake_path(GET _SWIFT_TESTING_DIR PARENT_PATH _SWIFT_TESTING_TARGETLESS_DIR)
|
||||||
set_target_properties(SwiftTesting::SwiftTesting PROPERTIES
|
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_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()
|
||||||
endif()
|
endif()
|
||||||
|
|
|
@ -6,12 +6,21 @@ if (ENABLE_SWIFT)
|
||||||
TestHeap.cpp
|
TestHeap.cpp
|
||||||
TestInterop.cpp
|
TestInterop.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
# FIXME: Swift doesn't seem to like object libraries for @main
|
# FIXME: Swift doesn't seem to like object libraries for @main
|
||||||
target_sources(TestGCSwift PRIVATE ../Resources/SwiftTestMain.swift)
|
target_sources(TestGCSwift PRIVATE ../Resources/SwiftTestMain.swift)
|
||||||
|
|
||||||
|
generate_clang_module_map(TestGCSwift)
|
||||||
|
|
||||||
set_target_properties(TestGCSwift PROPERTIES SUFFIX .swift-testing)
|
set_target_properties(TestGCSwift PROPERTIES SUFFIX .swift-testing)
|
||||||
target_include_directories(TestGCSwift PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
|
target_include_directories(TestGCSwift PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
target_link_libraries(TestGCSwift PRIVATE AK LibGC SwiftTesting::SwiftTesting)
|
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)
|
add_test(NAME TestGCSwift COMMAND TestGCSwift)
|
||||||
endif()
|
endif()
|
||||||
|
|
|
@ -6,14 +6,28 @@
|
||||||
|
|
||||||
import AK
|
import AK
|
||||||
import GC
|
import GC
|
||||||
import GCTesting
|
@_exported import TestGCSwiftCxx
|
||||||
import Testing
|
import Testing
|
||||||
|
|
||||||
// FIXME: We want a type declared *here* for HeapString, but it gives a compiler warning:
|
public struct HeapString: HeapAllocatable {
|
||||||
// error: type 'GCString' cannot conform to protocol 'HeapAllocatable' because it has requirements that cannot be satisfied
|
public var string: Swift.String
|
||||||
// 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
|
public init(cell: GC.Cell) {
|
||||||
// be re-exported by the GC module.
|
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)
|
@Suite(.serialized)
|
||||||
struct TestGCSwiftBindings {
|
struct TestGCSwiftBindings {
|
||||||
|
|
|
@ -7,9 +7,9 @@
|
||||||
#include "TestInterop.h"
|
#include "TestInterop.h"
|
||||||
#include "TestHeap.h"
|
#include "TestHeap.h"
|
||||||
#include <AK/TypeCasts.h>
|
#include <AK/TypeCasts.h>
|
||||||
#include <LibGC-Swift.h>
|
|
||||||
#include <LibGC/ForeignCell.h>
|
#include <LibGC/ForeignCell.h>
|
||||||
#include <LibGC/Heap.h>
|
#include <LibGC/Heap.h>
|
||||||
|
#include <TestGCSwift-Swift.h>
|
||||||
|
|
||||||
#define COLLECT heap.collect_garbage(GC::Heap::CollectionType::CollectGarbage)
|
#define COLLECT heap.collect_garbage(GC::Heap::CollectionType::CollectGarbage)
|
||||||
#define COLLECT_ALL heap.collect_garbage(GC::Heap::CollectionType::CollectEverything)
|
#define COLLECT_ALL heap.collect_garbage(GC::Heap::CollectionType::CollectEverything)
|
||||||
|
@ -20,7 +20,7 @@ void test_interop()
|
||||||
|
|
||||||
COLLECT_ALL;
|
COLLECT_ALL;
|
||||||
|
|
||||||
auto string = GC::ForeignRef<GC::HeapString>::allocate(heap, "Hello, World!");
|
auto string = GC::ForeignRef<TestGCSwift::HeapString>::allocate(heap, "Hello, World!");
|
||||||
|
|
||||||
COLLECT;
|
COLLECT;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
module GCTesting {
|
|
||||||
header "TestHeap.h"
|
|
||||||
header "TestInterop.h"
|
|
||||||
requires cplusplus
|
|
||||||
export *
|
|
||||||
}
|
|
Loading…
Add table
Add a link
Reference in a new issue