-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Adding a Test to check if Swift refcounting is really working. #35368
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Adding a Test to check if Swift refcounting is really working. #35368
Conversation
EWS run on previous version of this PR (hash d0eac26) |
d0eac26
to
e0d3936
Compare
EWS run on previous version of this PR (hash e0d3936)
|
e0d3936
to
39d68c4
Compare
EWS run on previous version of this PR (hash 39d68c4) |
} | ||
|
||
public static func getRefCountOptimizedOut(obj: WebGPUTest.CppRefCounted) -> UInt32 { | ||
return obj.refCountProxy() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the return
here can be omitted with recent Swift versions
@@ -0,0 +1,36 @@ | |||
/* | |||
* Copyright (C) 2021 Apple Inc. All rights reserved. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the year should be updated
*/ | ||
|
||
public class TestPlumbing { | ||
public static func getRefCount(obj: WebGPUTest.CppRefCounted) -> UInt32 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've seen this in some of your other PRs, but never asked: Is it intentional that you're using the fully qualified <module>.<type>
type names in function declarations? Normally I only see fully-qualified types used to disambiguate.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have never really found a way around it which is not:
typelias CppRefCounted = WebGPUTest.CppRefCounted
.
I'll do that for now and ask around as to how C++ namespaces(WebGPUTest
) are actually getting imported.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this is how the interop layer imports them, that's fine with me. I think the typealias would be unnecessary. It's just a little weird since typically in Swift, once you import the module (import WebGPUTest
), all these types would be able to be named without being fully-qualified.
#if ENABLE(WEBGPU_SWIFT) | ||
TEST(WebGPUSwiftTest, CppReferenceCounting) | ||
{ | ||
auto obj = WebGPUTest::CppRefCounted::create(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
auto obj = WebGPUTest::CppRefCounted::create(); | |
Ref obj = WebGPUTest::CppRefCounted::create(); |
(per smart ptr guidelines)
|
||
FRAMEWORK_SEARCH_PATHS = $(FRAMEWORK_SEARCH_PATHS_$(WK_COCOA_TOUCH)); | ||
FRAMEWORK_SEARCH_PATHS_ = $(inherited) $(SYSTEM_LIBRARY_DIR)/PrivateFrameworks $(SYSTEM_LIBRARY_DIR)/Frameworks/WebKit.framework/Versions/A/Frameworks; | ||
FRAMEWORK_SEARCH_PATHS_cocoatouch = $(inherited); | ||
|
||
PROJECT_HEADER_SEARCH_PATHS = $(SRCROOT)/../../Source/WebKit/Platform $(SRCROOT)/../../Source/WebKit/Platform/IPC $(SRCROOT)/../../Source/WebKit/Platform/IPC/darwin $(SRCROOT)/../../Source/WebKit/Platform/IPC/cocoa $(SRCROOT)/../../Source/WebKit/Shared $(SRCROOT)/../../Source/WebKit/Shared/Cocoa $(SRCROOT)/../../Source/WebKit/Shared/cf $(SRCROOT)/../../Source/WebKit/Shared/API/C $(BUILT_PRODUCTS_DIR)/DerivedSources/WebKit $(inherited); | ||
|
||
HEADER_SEARCH_PATHS = $(inherited) $(OBJROOT)/WebGPU.build/WebGPU.build/DerivedSources $(OBJROOT)/WebGPU.build/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/WebGPU.build/DerivedSource |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you remind me if we have precedent for reaching into other projects' intermediate build dir like this? It's pretty gross, and I worry that you are making assumptions about build directory structure that won't always be true (e.g. for a person who uses the Xcode-default derived data dir).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is a precedent in PAL<=>WebCore. and yes, It is gross.
Although, I think for this PR this is not even needed anymore. Sorry for that. It's just a remnant of how I was thinking of doing this earlier which I should have removed.
39d68c4
to
d4b414f
Compare
EWS run on previous version of this PR (hash d4b414f) |
Source/WebGPU/WebGPU/WebGPUSwift.mm
Outdated
unsigned WebGPUTest::CppRefCounted::getSwiftRefCount() | ||
{ | ||
return WebGPU::TestPlumbing::getRefCount(this); | ||
} | ||
|
||
unsigned WebGPUTest::CppRefCounted::getSwiftRefCountOptimizedOut() | ||
{ | ||
return WebGPU::TestPlumbing::getRefCountOptimizedOut(this); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this set of wrappers required? I don't think it is. Empty abstraction makes code hard to read and edit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I want to expose the swift functions out of WebGPU.framework as a C++ API so that I can call it in TestWebKitAPI. Do you know of another way to do it ? If I directly want to call TestPlumbing then I will have to enable Interop in the test binary also.. which I really did not want to do.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we want to avoid enabling interop in our unit tests? Don't we want to unit test interop?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we want to unit test interop. And that's why this PR.
I just did not want to turn on interop in TestWebKitAPI yet unless we really have a pressing need for it. Usually, enabling interop involves yet another series of #ifndef __swift__
which just adds debt to cleanup later.
If you strongly feel that we should just enable interop in TestWebKitAPI now, then I can work on that.
Source/WebGPU/WebGPU/WebGPU.h
Outdated
|
||
inline void retainCpp(WebGPUTest::CppRefCounted* obj) | ||
{ | ||
WTF::retainRefCounted(obj); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should rename WTF::retainRefCounted
to ref(). Having two names for one thing is confusing. Also, you can remove the RELEASE_ASSERT, static_assert, and static_cast. Just have it call object->ref()
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are three of these:
- RefCounted
- ThreadSafeRefCounted
- ThreadSafeRefCountedAndCanMakeThreadSafeWeakPtr
All three have Global wrappers(which Swift mandates). So I cannot rename all of them as ref
?
Also, curious if you are asking me to remove the asserts for perfomance ? I have just added them to make sure I am calling the right ref
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm saying something way more basic: If obj is a refcounted WebKit object, it has a member function named 'ref'.
I want to remove the cast because it's not type-safe, and not needed. I want to remove the asserts because they're just there to guard the cast.
Source/WebGPU/WebGPU/WebGPU.h
Outdated
|
||
} | ||
|
||
inline void retainCpp(WebGPUTest::CppRefCounted* obj) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would call this function 'ref', since it's a free function whose job is to call the 'ref' member function.
But also: If you make a free function in WTF, template<typename T> void ref(T* object) { object->ref(); }
you may not need a separate function here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried that when I was adding it to the RefCounted classes but templates don't work with swift.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, right! So we do need separate function overloads per class, but we can still make them free functions named ref: void ref(WebGPUTest::CppRefCounted* object) { object->ref(); }
Source/WebGPU/WebGPU/WebGPU.h
Outdated
|
||
inline void releaseCpp(WebGPUTest::CppRefCounted* obj) | ||
{ | ||
WTF::releaseRefCounted(obj); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto.
Source/WebGPU/WebGPU/WebGPU.h
Outdated
unsigned refCountProxy() { return refCount(); } | ||
WGPU_EXPORT unsigned getSwiftRefCount(); | ||
WGPU_EXPORT unsigned getSwiftRefCountOptimizedOut(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need any of this abstraction? Can't the caller just call refCount()
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
to expose the API in Swift in C++ and use it in TestWebKitAPI without enabling interop there.
Source/WebGPU/WebGPU/WebGPU.h
Outdated
#include <wtf/RetainReleaseSwift.h> | ||
#if ENABLE(WEBGPU_SWIFT) | ||
namespace WebGPUTest { | ||
class CppRefCounted: public RefCounted<CppRefCounted> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this class move to TestWebKitAPI?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only if I enable interop there which I would rather not do and avoid the complexity.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we want to write unit tests for Swift, we're going to need to make Swift unit testing possible.
Would it help to make Swift unit testing a separate build target? TestWebKitAPI supports that, and already has TestIPC, TestWGSL, TestWTF, etc.
Source/WebGPU/WebGPU/WebGPU.h
Outdated
// Swift is not importing const methods and RefCount::refCount() is const | ||
unsigned refCountProxy() { return refCount(); } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can make an #if __swift__
non-const overload for refCount() in the RefCounted class, with a FIXME and a Radar for not importing const methods.
public class TestPlumbing { | ||
public static func getRefCount(obj: CppRefCounted) -> UInt32 { | ||
// Just an API call to ensure swift does not optimize this out. | ||
let refCount = obj.refCountProxy() | ||
let _ = "The ref count is \(refCount)" | ||
return refCount | ||
} | ||
|
||
public static func getRefCountOptimizedOut(obj: CppRefCounted) -> UInt32 { | ||
obj.refCountProxy() | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems kinda brittle. I don't think we need it?
The goal is to determine that the object is allocated with the right refcount, right? If so, we want to export a Swift function that will allocate and return the object, and then we can test the refcount of the result directly in our caller TestWebKitAPI code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmm.. okie.. I can remove that. I just wanted to highlight the optimization via a test but it's not important.
d4b414f
to
fff4bc9
Compare
EWS run on previous version of this PR (hash fff4bc9) |
fff4bc9
to
ef20a4e
Compare
EWS run on previous version of this PR (hash ef20a4e) |
ef20a4e
to
3fbe91f
Compare
EWS run on previous version of this PR (hash 3fbe91f) |
https://bugs.webkit.org/show_bug.cgi?id=281608 rdar://problem/138056283 Reviewed by NOBODY (OOPS!). Check that reference count is getting incremented in swift. * Source/WTF/wtf/RefCounted.h: (WTF::RefCountedBase::ref): (WTF::RefCountedBase::ref const): Deleted. * Source/WebGPU/WebGPU/Buffer.mm: (WebGPU::Buffer::copy): * Source/WebGPU/WebGPU/WebGPUExt.h: * Tools/Scripts/run-api-tests: (parse_args): * Tools/Scripts/webkitpy/port/darwin.py: (DarwinPort): * Tools/TestWebKitAPI/Configurations/TestWebGPU.xcconfig: Added. * Tools/TestWebKitAPI/Configurations/TestWebKitAPIBase.xcconfig: * Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj: * Tools/TestWebKitAPI/Tests/WebGPU/RefCountTests.mm: Added. (TEST(TestWebGPU, ReferenceCounting)): * Tools/TestWebKitAPI/Tests/WebGPU/TestWebGPU.h: Added. (refCpp): (derefCpp): * Tools/TestWebKitAPI/Tests/WebGPU/TestWebGPU.mm: Added. (Cpp::CppRefCounted::getSwiftRefCount): * Tools/TestWebKitAPI/Tests/WebGPU/TestWebGPU.modulemap: Added. * Tools/TestWebKitAPI/Tests/WebGPU/Tests.swift: Added. (getRefCount(_:)):
3fbe91f
to
1b70bf0
Compare
EWS run on current version of this PR (hash 1b70bf0) |
39d68c46d92e77d3a7a19c86d3fd8bc15c666c4f
1b70bf0