Skip to content

Commit fb0eb86

Browse files
committed
Move fully-featured FunctionRef from extension/pytree to ExecuTorch core
I just re-synced it with LLVM, and it seems harmless. We previously simplified FunctionRef because of an ARM baremetal toolchain issue around placement of a lambda (#555), but the current implementation has no lambda. Motivation: I want to be able to use it in the next PR in thread_parallel_interface.h (the "threadpool active" mode) and threadpool in order to save a ton of size that std::function is currently wasting by virtue of supporting ownership and copying. ghstack-source-id: 75160722db5ca9b33f7604e6811ab1a1b80d6f1d ghstack-comment-id: 2828755099 Pull-Request-resolved: #10441
1 parent 7aadc19 commit fb0eb86

File tree

9 files changed

+134
-119
lines changed

9 files changed

+134
-119
lines changed

extension/pytree/function_ref.h

+7-103
Original file line numberDiff line numberDiff line change
@@ -6,114 +6,18 @@
66
* LICENSE file in the root directory of this source tree.
77
*/
88

9-
//===- llvm/ADT/STLFunctionalExtras.h - Extras for <functional> -*- C++ -*-===//
10-
//
11-
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
12-
// See https://llvm.org/LICENSE.txt for license information.
13-
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
14-
//
15-
//===----------------------------------------------------------------------===//
16-
//
17-
// This file contains some extension to <functional>.
18-
//
19-
// No library is required when using these functions.
20-
//
21-
//===----------------------------------------------------------------------===//
22-
// Extra additions to <functional>
23-
//===----------------------------------------------------------------------===//
24-
25-
/// An efficient, type-erasing, non-owning reference to a callable. This is
26-
/// intended for use as the type of a function parameter that is not used
27-
/// after the function in question returns.
28-
///
29-
/// This class does not own the callable, so it is not in general safe to store
30-
/// a FunctionRef.
31-
32-
// torch::executor: modified from llvm::function_ref
33-
// - renamed to FunctionRef
34-
// - removed LLVM_GSL_POINTER and LLVM_LIFETIME_BOUND macro uses
35-
// - use namespaced internal::remove_cvref_t
36-
37-
389
#pragma once
3910

40-
#include <cstdint>
41-
#include <type_traits>
42-
#include <utility>
43-
44-
namespace executorch {
45-
namespace extension {
46-
namespace pytree {
47-
48-
//===----------------------------------------------------------------------===//
49-
// Features from C++20
50-
//===----------------------------------------------------------------------===//
51-
52-
namespace internal {
53-
54-
template <typename T>
55-
struct remove_cvref {
56-
using type =
57-
typename std::remove_cv<typename std::remove_reference<T>::type>::type;
58-
};
59-
60-
template <typename T>
61-
using remove_cvref_t = typename remove_cvref<T>::type;
62-
63-
} // namespace internal
64-
65-
template <typename Fn>
66-
class FunctionRef;
67-
68-
template <typename Ret, typename... Params>
69-
class FunctionRef<Ret(Params...)> {
70-
Ret (*callback)(intptr_t callable, Params ...params) = nullptr;
71-
intptr_t callable;
72-
73-
template<typename Callable>
74-
static Ret callback_fn(intptr_t callable, Params ...params) {
75-
return (*reinterpret_cast<Callable*>(callable))(
76-
std::forward<Params>(params)...);
77-
}
78-
79-
public:
80-
FunctionRef() = default;
81-
FunctionRef(std::nullptr_t) {}
82-
83-
template <typename Callable>
84-
FunctionRef(
85-
Callable &&callable,
86-
// This is not the copy-constructor.
87-
std::enable_if_t<!std::is_same<internal::remove_cvref_t<Callable>,
88-
FunctionRef>::value> * = nullptr,
89-
// Functor must be callable and return a suitable type.
90-
std::enable_if_t<std::is_void<Ret>::value ||
91-
std::is_convertible<decltype(std::declval<Callable>()(
92-
std::declval<Params>()...)),
93-
Ret>::value> * = nullptr)
94-
: callback(callback_fn<std::remove_reference_t<Callable>>),
95-
callable(reinterpret_cast<intptr_t>(&callable)) {}
96-
97-
Ret operator()(Params ...params) const {
98-
return callback(callable, std::forward<Params>(params)...);
99-
}
11+
#include <executorch/runtime/core/function_ref.h>
10012

101-
explicit operator bool() const { return callback; }
13+
/// This header is DEPRECATED; use executorch/runtime/core/function_ref.h directly instead.
10214

103-
bool operator==(const FunctionRef<Ret(Params...)> &Other) const {
104-
return callable == Other.callable;
105-
}
106-
};
107-
} // namespace pytree
108-
} // namespace extension
109-
} // namespace executorch
15+
namespace executorch::extension::pytree {
16+
using executorch::runtime::FunctionRef;
17+
} // namespace executorch::extension::pytree
11018

111-
namespace torch {
112-
namespace executor {
113-
namespace pytree {
19+
namespace torch::executor::pytree {
11420
// TODO(T197294990): Remove these deprecated aliases once all users have moved
11521
// to the new `::executorch` namespaces.
11622
using ::executorch::extension::pytree::FunctionRef;
117-
} // namespace pytree
118-
} // namespace executor
119-
} // namespace torch
23+
} // namespace torch::executor::pytree

extension/pytree/test/CMakeLists.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,6 @@ set(EXECUTORCH_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/../../..)
1919

2020
include(${EXECUTORCH_ROOT}/tools/cmake/Test.cmake)
2121

22-
set(_test_srcs function_ref_test.cpp test_pytree.cpp)
22+
set(_test_srcs test_pytree.cpp)
2323

2424
et_cxx_test(extension_pytree_test SOURCES ${_test_srcs} EXTRA_LIBS)

extension/pytree/test/TARGETS

-6
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,6 @@ cpp_unittest(
1010
deps = ["//executorch/extension/pytree:pytree"],
1111
)
1212

13-
cpp_unittest(
14-
name = "function_ref_test",
15-
srcs = ["function_ref_test.cpp"],
16-
deps = ["//executorch/extension/pytree:pytree"],
17-
)
18-
1913
python_unittest(
2014
name = "pybindings_test",
2115
srcs = [

runtime/core/function_ref.h

+105
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the BSD-style license found in the
6+
* LICENSE file in the root directory of this source tree.
7+
*/
8+
9+
//===- llvm/ADT/STLFunctionalExtras.h - Extras for <functional> -*- C++ -*-===//
10+
//
11+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
12+
// See https://llvm.org/LICENSE.txt for license information.
13+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
14+
//
15+
//===----------------------------------------------------------------------===//
16+
//
17+
// This file contains some extension to <functional>.
18+
//
19+
// No library is required when using these functions.
20+
//
21+
//===----------------------------------------------------------------------===//
22+
// Extra additions to <functional>
23+
//===----------------------------------------------------------------------===//
24+
25+
/// An efficient, type-erasing, non-owning reference to a callable. This is
26+
/// intended for use as the type of a function parameter that is not used
27+
/// after the function in question returns.
28+
///
29+
/// This class does not own the callable, so it is not in general safe to store
30+
/// a FunctionRef.
31+
32+
// torch::executor: modified from llvm::function_ref
33+
// - renamed to FunctionRef
34+
// - removed LLVM_GSL_POINTER and LLVM_LIFETIME_BOUND macro uses
35+
// - use namespaced internal::remove_cvref_t
36+
37+
38+
#pragma once
39+
40+
#include <cstdint>
41+
#include <type_traits>
42+
#include <utility>
43+
44+
namespace executorch::runtime {
45+
46+
//===----------------------------------------------------------------------===//
47+
// Features from C++20
48+
//===----------------------------------------------------------------------===//
49+
50+
namespace internal {
51+
52+
template <typename T>
53+
struct remove_cvref {
54+
using type =
55+
typename std::remove_cv<typename std::remove_reference<T>::type>::type;
56+
};
57+
58+
template <typename T>
59+
using remove_cvref_t = typename remove_cvref<T>::type;
60+
61+
} // namespace internal
62+
63+
template <typename Fn>
64+
class FunctionRef;
65+
66+
template <typename Ret, typename... Params>
67+
class FunctionRef<Ret(Params...)> {
68+
Ret (*callback)(intptr_t callable, Params ...params) = nullptr;
69+
intptr_t callable;
70+
71+
template<typename Callable>
72+
static Ret callback_fn(intptr_t callable, Params ...params) {
73+
return (*reinterpret_cast<Callable*>(callable))(
74+
std::forward<Params>(params)...);
75+
}
76+
77+
public:
78+
FunctionRef() = default;
79+
FunctionRef(std::nullptr_t) {}
80+
81+
template <typename Callable>
82+
FunctionRef(
83+
Callable &&callable,
84+
// This is not the copy-constructor.
85+
std::enable_if_t<!std::is_same<internal::remove_cvref_t<Callable>,
86+
FunctionRef>::value> * = nullptr,
87+
// Functor must be callable and return a suitable type.
88+
std::enable_if_t<std::is_void<Ret>::value ||
89+
std::is_convertible<decltype(std::declval<Callable>()(
90+
std::declval<Params>()...)),
91+
Ret>::value> * = nullptr)
92+
: callback(callback_fn<std::remove_reference_t<Callable>>),
93+
callable(reinterpret_cast<intptr_t>(&callable)) {}
94+
95+
Ret operator()(Params ...params) const {
96+
return callback(callable, std::forward<Params>(params)...);
97+
}
98+
99+
explicit operator bool() const { return callback; }
100+
101+
bool operator==(const FunctionRef<Ret(Params...)> &Other) const {
102+
return callable == Other.callable;
103+
}
104+
};
105+
} // namespace executorch::runtime

runtime/core/targets.bzl

+1
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ def define_common_targets():
4141
"defines.h",
4242
"error.h",
4343
"freeable_buffer.h",
44+
"function_ref.h",
4445
"result.h",
4546
"span.h",
4647
],

runtime/core/test/CMakeLists.txt

+5-4
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,15 @@ set(EXECUTORCH_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/../../..)
2020
include(${EXECUTORCH_ROOT}/tools/cmake/Test.cmake)
2121

2222
set(_test_srcs
23-
span_test.cpp
23+
array_ref_test.cpp
2424
error_handling_test.cpp
25+
evalue_test.cpp
2526
event_tracer_test.cpp
2627
freeable_buffer_test.cpp
27-
array_ref_test.cpp
28-
memory_allocator_test.cpp
28+
function_ref_test.cpp
2929
hierarchical_allocator_test.cpp
30-
evalue_test.cpp
30+
memory_allocator_test.cpp
31+
span_test.cpp
3132
)
3233

3334
et_cxx_test(runtime_core_test SOURCES ${_test_srcs} EXTRA_LIBS)

runtime/core/test/targets.bzl

+10
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,16 @@ def define_common_targets():
3333
],
3434
)
3535

36+
runtime.cxx_test(
37+
name = "function_ref_test",
38+
srcs = [
39+
"function_ref_test.cpp",
40+
],
41+
deps = [
42+
"//executorch/runtime/core:core",
43+
],
44+
)
45+
3646
runtime.cxx_test(
3747
name = "event_tracer_test",
3848
srcs = [

test/utils/OSSTestConfig.json

+5-5
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@
4545
{
4646
"directory": "extension/pytree/test",
4747
"sources": [
48-
"function_ref_test.cpp",
4948
"test_pytree.cpp"
5049
]
5150
},
@@ -96,14 +95,15 @@
9695
{
9796
"directory": "runtime/core/test",
9897
"sources": [
99-
"span_test.cpp",
98+
"array_ref_test.cpp",
10099
"error_handling_test.cpp",
100+
"evalue_test.cpp",
101101
"event_tracer_test.cpp",
102102
"freeable_buffer_test.cpp",
103-
"array_ref_test.cpp",
104-
"memory_allocator_test.cpp",
103+
"function_ref_test.cpp",
105104
"hierarchical_allocator_test.cpp",
106-
"evalue_test.cpp"
105+
"memory_allocator_test.cpp",
106+
"span_test.cpp"
107107
]
108108
},
109109
{

0 commit comments

Comments
 (0)