Line data Source code
1 : // Copyright 2018 the V8 project authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 :
5 : #ifndef V8_TORQUE_CONTEXTUAL_H_
6 : #define V8_TORQUE_CONTEXTUAL_H_
7 :
8 : #include <type_traits>
9 :
10 : #include "src/base/macros.h"
11 : #include "src/base/platform/platform.h"
12 :
13 : namespace v8 {
14 : namespace internal {
15 : namespace torque {
16 :
17 : // {ContextualVariable} provides a clean alternative to a global variable.
18 : // The contextual variable is mutable, and supports managing the value of
19 : // a variable in a well-nested fashion via the {Scope} class.
20 : // {ContextualVariable} only stores a pointer to the current value, which
21 : // is stored in a {Scope} object. The most recent value can be retrieved
22 : // via Get(). Because only {Scope} has actual storage, there must be at
23 : // least one active {Scope} (i.e. in a surrounding C++ scope), whenever Get()
24 : // is called.
25 : // Note that contextual variables must only be used from the same thread,
26 : // i.e. {Scope} and Get() have to be in the same thread.
27 : template <class Derived, class VarType>
28 : class ContextualVariable {
29 : public:
30 : using VariableType = VarType;
31 :
32 : // A {Scope} contains a new object of type {VarType} and gives
33 : // ContextualVariable::Get() access to it. Upon destruction, the contextual
34 : // variable is restored to the state before the {Scope} was created. Scopes
35 : // have to follow a stack discipline: A {Scope} has to be destructed before
36 : // any older scope is destructed.
37 : class Scope {
38 : public:
39 : template <class... Args>
40 307346 : explicit Scope(Args&&... args)
41 317088 : : current_(std::forward<Args>(args)...), previous_(Top()) {
42 314190 : Top() = ¤t_;
43 307346 : }
44 6 : ~Scope() {
45 : // Ensure stack discipline.
46 : DCHECK_EQ(¤t_, Top());
47 314190 : Top() = previous_;
48 314190 : }
49 :
50 : private:
51 : VarType current_;
52 : VarType* previous_;
53 :
54 : static_assert(std::is_base_of<ContextualVariable, Derived>::value,
55 : "Curiously Recurring Template Pattern");
56 :
57 : DISALLOW_NEW_AND_DELETE()
58 : DISALLOW_COPY_AND_ASSIGN(Scope);
59 : };
60 :
61 : // Access the most recent active {Scope}. There has to be an active {Scope}
62 : // for this contextual variable.
63 : static VarType& Get() {
64 : DCHECK_NOT_NULL(Top());
65 4615007 : return *Top();
66 : }
67 :
68 : private:
69 : V8_EXPORT_PRIVATE static VarType*& Top();
70 : };
71 :
72 : // Usage: DECLARE_CONTEXTUAL_VARIABLE(VarName, VarType)
73 : #define DECLARE_CONTEXTUAL_VARIABLE(VarName, ...) \
74 : struct VarName \
75 : : v8::internal::torque::ContextualVariable<VarName, __VA_ARGS__> {}
76 :
77 : #define DEFINE_CONTEXTUAL_VARIABLE(VarName) \
78 : template <> \
79 : V8_EXPORT_PRIVATE VarName::VariableType*& \
80 : ContextualVariable<VarName, VarName::VariableType>::Top() { \
81 : static thread_local VarName::VariableType* top = nullptr; \
82 : return top; \
83 : }
84 :
85 : // By inheriting from {ContextualClass} a class can become a contextual variable
86 : // of itself, which is very similar to a singleton.
87 : template <class T>
88 : using ContextualClass = ContextualVariable<T, T>;
89 :
90 : } // namespace torque
91 : } // namespace internal
92 : } // namespace v8
93 :
94 : #endif // V8_TORQUE_CONTEXTUAL_H_
|