| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
#pragma once |
|
2
|
|
|
|
|
|
|
#include "base.h" |
|
3
|
|
|
|
|
|
|
#include "../Ref.h" |
|
4
|
|
|
|
|
|
|
#include "../Stash.h" |
|
5
|
|
|
|
|
|
|
#include "../catch.h" |
|
6
|
|
|
|
|
|
|
#include "../Backref.h" |
|
7
|
|
|
|
|
|
|
#include |
|
8
|
|
|
|
|
|
|
#include |
|
9
|
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
namespace xs { |
|
11
|
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
using panda::refcnt_inc; |
|
13
|
|
|
|
|
|
|
using panda::refcnt_dec; |
|
14
|
|
|
|
|
|
|
using panda::refcnt_get; |
|
15
|
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
namespace typemap { namespace object { |
|
17
|
|
|
|
|
|
|
using svt_clear_t = int(*)(pTHX_ SV*, MAGIC*); |
|
18
|
|
|
|
|
|
|
using svt_copy_t = int(*)(pTHX_ SV*, MAGIC*, SV*, const char*, I32); |
|
19
|
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
extern CV* fake_dtor; |
|
21
|
|
|
|
|
|
|
extern svt_copy_t backref_marker; |
|
22
|
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
void init (); |
|
24
|
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
template struct TypemapMarker { |
|
26
|
0
|
|
|
|
|
|
static int func (pTHX_ SV*, MAGIC*) { return 0; } |
|
27
|
2224
|
100
|
|
|
|
|
PANDA_GLOBAL_MEMBER_PTR(TypemapMarker, svt_clear_t, get, &func); |
|
28
|
|
|
|
|
|
|
}; |
|
29
|
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
panda::string type_details(const std::type_info&); |
|
31
|
|
|
|
|
|
|
[[ noreturn ]] void _throw_incorrect_arg(SV* arg, const std::type_info& expected, panda::string_view package); |
|
32
|
|
|
|
|
|
|
[[ noreturn ]] void _throw_no_package (const std::type_info&); |
|
33
|
|
|
|
|
|
|
}} |
|
34
|
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
template |
|
36
|
|
|
|
|
|
|
struct ObjectStorageIV { |
|
37
|
|
|
|
|
|
|
static const bool auto_disposable = false; |
|
38
|
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
static inline void* get (SV* arg) { |
|
40
|
|
|
|
|
|
|
return SvIOK(arg) ? (void*)SvIVX(arg) : nullptr; |
|
41
|
|
|
|
|
|
|
} |
|
42
|
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
static inline void set (SV* arg, void* ptr) { |
|
44
|
|
|
|
|
|
|
SvIOK_on(arg); |
|
45
|
|
|
|
|
|
|
SvIVX(arg) = (IV)ptr; |
|
46
|
|
|
|
|
|
|
} |
|
47
|
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
static Sv out (const TYPE& var, const Sv& proto) { |
|
49
|
|
|
|
|
|
|
return Typemap::create(var, proto); |
|
50
|
|
|
|
|
|
|
} |
|
51
|
|
|
|
|
|
|
}; |
|
52
|
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
template |
|
54
|
|
|
|
|
|
|
struct ObjectStorageMG_Impl { |
|
55
|
|
|
|
|
|
|
using PURE_TYPEMAP = std::remove_const_t>>; |
|
56
|
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
static const bool auto_disposable = true; |
|
58
|
|
|
|
|
|
|
|
|
59
|
976
|
|
|
|
|
|
static inline void* get (SV* arg) { |
|
60
|
976
|
|
|
|
|
|
MAGIC* mg = _get_magic(arg); |
|
61
|
976
|
50
|
|
|
|
|
return mg ? mg->mg_ptr : NULL; |
|
|
|
50
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
} |
|
63
|
|
|
|
|
|
|
|
|
64
|
136
|
|
|
|
|
|
static inline void set (SV* arg, void* ptr) { |
|
65
|
136
|
50
|
|
|
|
|
auto marker = xs::Sv::PayloadMarker::get(); |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
66
|
136
|
50
|
|
|
|
|
marker->svt_clear = typemap::object::TypemapMarker::get(); |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
67
|
136
|
|
|
|
|
|
marker->svt_free = _on_free; |
|
68
|
136
|
|
|
|
|
|
_set_br(marker, BACKREF()); |
|
69
|
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
MAGIC* mg; |
|
71
|
136
|
50
|
|
|
|
|
Newx(mg, 1, MAGIC); |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
72
|
136
|
|
|
|
|
|
mg->mg_moremagic = SvMAGIC(arg); |
|
73
|
136
|
|
|
|
|
|
SvMAGIC_set(arg, mg); |
|
74
|
136
|
|
|
|
|
|
mg->mg_virtual = marker; |
|
75
|
136
|
|
|
|
|
|
mg->mg_type = PERL_MAGIC_ext; |
|
76
|
136
|
|
|
|
|
|
mg->mg_len = 0; |
|
77
|
136
|
|
|
|
|
|
mg->mg_obj = nullptr; |
|
78
|
136
|
|
|
|
|
|
mg->mg_ptr = (char*)ptr; |
|
79
|
136
|
|
|
|
|
|
mg->mg_private = 0; |
|
80
|
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
#ifdef USE_ITHREADS |
|
82
|
|
|
|
|
|
|
marker->svt_dup = _on_svdup; |
|
83
|
|
|
|
|
|
|
mg->mg_flags = MGf_DUP; |
|
84
|
|
|
|
|
|
|
#else |
|
85
|
136
|
|
|
|
|
|
mg->mg_flags = 0; |
|
86
|
|
|
|
|
|
|
#endif |
|
87
|
136
|
|
|
|
|
|
} |
|
88
|
|
|
|
|
|
|
|
|
89
|
136
|
50
|
|
|
|
|
static Sv out (const TYPE& var, const Sv& proto) { return _out(var, proto, BACKREF()); } |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
private: |
|
92
|
976
|
|
|
|
|
|
static inline MAGIC* _get_magic (SV* sv) { |
|
93
|
976
|
|
|
|
|
|
auto marker = typemap::object::TypemapMarker::get(); |
|
94
|
|
|
|
|
|
|
MAGIC *mg; |
|
95
|
1952
|
50
|
|
|
|
|
for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) if (mg->mg_virtual && mg->mg_virtual->svt_clear == marker) return mg; |
|
|
|
50
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
96
|
0
|
|
|
|
|
|
return NULL; |
|
97
|
|
|
|
|
|
|
} |
|
98
|
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
static inline void _set_br (Sv::payload_marker_t*, std::false_type) {} |
|
100
|
136
|
|
|
|
|
|
static inline void _set_br (Sv::payload_marker_t* marker, std::true_type) { |
|
101
|
136
|
|
|
|
|
|
marker->svt_copy = typemap::object::backref_marker; |
|
102
|
136
|
|
|
|
|
|
marker->svt_local = _destroy_hook; |
|
103
|
136
|
|
|
|
|
|
} |
|
104
|
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
static inline Sv _out (const TYPE& var, const Sv& proto, std::false_type) { return Typemap::create(var, proto); } |
|
106
|
|
|
|
|
|
|
|
|
107
|
136
|
|
|
|
|
|
static inline Sv _out (const TYPE& var, const Sv& proto, std::true_type) { |
|
108
|
136
|
50
|
|
|
|
|
auto br = Backref::get(var); |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
109
|
136
|
50
|
|
|
|
|
if (!br) return Typemap::create(var, proto); |
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
110
|
113
|
50
|
|
|
|
|
if (br->svobj) { |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
111
|
0
|
|
|
|
|
|
if (!std::is_const>::value) SvREADONLY_off(br->svobj); |
|
112
|
0
|
0
|
|
|
|
|
if (!br->zombie) return Ref::create(br->svobj); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
113
|
0
|
0
|
|
|
|
|
_from_zombie(Typemap::IType::template cast(var), br->svobj, _get_magic(br->svobj), br); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
114
|
0
|
0
|
|
|
|
|
return Sv::noinc(newRV_noinc(br->svobj)); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
} |
|
116
|
249
|
50
|
|
|
|
|
auto ret = Typemap::create(var, proto); |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
117
|
113
|
|
|
|
|
|
br->svobj = SvRV(ret); |
|
118
|
113
|
|
|
|
|
|
return ret; |
|
119
|
|
|
|
|
|
|
} |
|
120
|
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
// this hook is invoked before perl frees SV and before DESTROY() method if SV is an object |
|
122
|
|
|
|
|
|
|
// if non-zero value is returned then the destruction of SV is completely aborted (and DESTROY() method is not called) |
|
123
|
544
|
|
|
|
|
|
static int _destroy_hook (pTHX_ SV* sv, MAGIC* mg) { return throw_guard(Sub(), [=]() -> int { |
|
124
|
136
|
|
|
|
|
|
TYPEMAP var = Typemap::IType::template in(mg->mg_ptr); |
|
125
|
136
|
50
|
|
|
|
|
auto br = Backref::get(var); |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
126
|
136
|
50
|
|
|
|
|
if (!br) return 0; |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
|
|
128
|
113
|
50
|
|
|
|
|
if (br->zombie) { |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
// as no one has strong reference to our zombie SV backref, its destruction is only possible in 2 cases: |
|
130
|
|
|
|
|
|
|
// - decremented from C destructor of XSBackref class |
|
131
|
|
|
|
|
|
|
// - perl is cleaning his arena in destruction phase |
|
132
|
0
|
0
|
|
|
|
|
_restore_dtor(sv); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
133
|
0
|
0
|
|
|
|
|
_from_zombie(var, sv, mg, br); |
|
134
|
0
|
0
|
|
|
|
|
if (br->in_cdtor) Typemap::IType::retain(var); // avoid double deletion if refcnt policy of 'var' drops to 0 during deletion |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
else assert(PL_in_clean_objs); |
|
136
|
0
|
|
|
|
|
|
return 0; |
|
137
|
|
|
|
|
|
|
} |
|
138
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
// if we are the only owner or in global destroy phase there is no sense of making zombie |
|
140
|
113
|
50
|
|
|
|
|
if (Typemap::IType::use_count(var) <= 1 || PL_in_clean_objs) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
141
|
113
|
50
|
|
|
|
|
_restore_dtor(sv); |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
142
|
113
|
|
|
|
|
|
br->svobj = NULL; |
|
143
|
113
|
|
|
|
|
|
return 0; |
|
144
|
|
|
|
|
|
|
} |
|
145
|
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
// perl SV goes out of scope, but C object is still accessible -> save SV to zombie |
|
147
|
0
|
0
|
|
|
|
|
_to_zombie(var, sv, mg, br); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
148
|
136
|
|
|
|
|
|
return 1; |
|
149
|
272
|
50
|
|
|
|
|
});} |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
struct ZombieMarker {}; |
|
152
|
|
|
|
|
|
|
|
|
153
|
0
|
|
|
|
|
|
static inline MAGIC* _zombie_get_stash_magic (HV* stash) { |
|
154
|
0
|
|
|
|
|
|
auto marker = xs::Sv::PayloadMarker::get(); |
|
155
|
|
|
|
|
|
|
MAGIC *mg; |
|
156
|
0
|
0
|
|
|
|
|
for (mg = SvMAGIC(stash); mg; mg = mg->mg_moremagic) if (mg->mg_virtual == marker) return mg; |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
157
|
0
|
|
|
|
|
|
return NULL; |
|
158
|
|
|
|
|
|
|
} |
|
159
|
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
#if PERL_VERSION >= 24 |
|
161
|
|
|
|
|
|
|
// prevent S_curse from calling dtor |
|
162
|
0
|
|
|
|
|
|
static inline void _ignore_dtor (SV* sv) { |
|
163
|
0
|
|
|
|
|
|
auto stash = SvSTASH(sv); |
|
164
|
0
|
0
|
|
|
|
|
auto meta = HvMROMETA(stash); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
165
|
0
|
0
|
|
|
|
|
if (meta->destroy == typemap::object::fake_dtor) return; |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
166
|
0
|
0
|
|
|
|
|
auto stmg = _zombie_get_stash_magic(stash); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
167
|
0
|
0
|
|
|
|
|
if (!stmg) stmg = Sv(stash).payload_attach(Sv::Payload(), xs::Sv::PayloadMarker::get()); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
168
|
0
|
|
|
|
|
|
stmg->mg_obj = (SV*)meta->destroy; |
|
169
|
0
|
|
|
|
|
|
stmg->mg_ptr = (char*)(uint64_t)meta->destroy_gen; |
|
170
|
0
|
|
|
|
|
|
meta->destroy = typemap::object::fake_dtor; |
|
171
|
0
|
|
|
|
|
|
meta->destroy_gen = PL_sub_generation; // make cache valid |
|
172
|
|
|
|
|
|
|
} |
|
173
|
|
|
|
|
|
|
|
|
174
|
113
|
|
|
|
|
|
static inline void _restore_dtor (SV* sv) { |
|
175
|
113
|
|
|
|
|
|
auto stash = SvSTASH(sv); |
|
176
|
113
|
50
|
|
|
|
|
auto meta = HvMROMETA(stash); |
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
177
|
113
|
50
|
|
|
|
|
if (meta->destroy != typemap::object::fake_dtor) return; |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
178
|
0
|
0
|
|
|
|
|
auto stmg = _zombie_get_stash_magic(stash); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
179
|
0
|
|
|
|
|
|
meta->destroy = (CV*)stmg->mg_obj; // restore dtor |
|
180
|
113
|
|
|
|
|
|
meta->destroy_gen = (uint64_t)stmg->mg_ptr; |
|
181
|
|
|
|
|
|
|
} |
|
182
|
|
|
|
|
|
|
#else |
|
183
|
|
|
|
|
|
|
static inline void _ignore_dtor (SV*) {} |
|
184
|
|
|
|
|
|
|
static inline void _restore_dtor (SV*) {} |
|
185
|
|
|
|
|
|
|
#endif |
|
186
|
|
|
|
|
|
|
|
|
187
|
0
|
|
|
|
|
|
static inline void _to_zombie (const TYPEMAP& var, SV* sv, MAGIC*, const Backref* br) { |
|
188
|
0
|
|
|
|
|
|
br->zombie = true; |
|
189
|
0
|
|
|
|
|
|
SvREFCNT(sv)++; |
|
190
|
0
|
|
|
|
|
|
Typemap::IType::release(var); |
|
191
|
0
|
|
|
|
|
|
_ignore_dtor(sv); |
|
192
|
0
|
|
|
|
|
|
} |
|
193
|
|
|
|
|
|
|
|
|
194
|
0
|
|
|
|
|
|
static inline void _from_zombie (const TYPEMAP& var, SV*, MAGIC*, const Backref* br) { |
|
195
|
0
|
|
|
|
|
|
br->zombie = false; |
|
196
|
0
|
|
|
|
|
|
Typemap::IType::retain(var); |
|
197
|
0
|
|
|
|
|
|
} |
|
198
|
|
|
|
|
|
|
|
|
199
|
544
|
|
|
|
|
|
static int _on_free (pTHX_ SV* sv, MAGIC* mg) {return throw_guard(Sub(), [=]() -> int { |
|
200
|
|
|
|
|
|
|
using IType = typename Typemap::IType; |
|
201
|
136
|
|
|
|
|
|
TYPEMAP downgraded = IType::template in(mg->mg_ptr); |
|
202
|
136
|
50
|
|
|
|
|
TYPE var = Typemap::template cast(downgraded); |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
203
|
136
|
50
|
|
|
|
|
if (!var) throw "TYPEMAP PANIC: bad object in sv"; |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
204
|
136
|
50
|
|
|
|
|
Typemap::dispose(var, sv); |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
205
|
136
|
|
|
|
|
|
return 0; |
|
206
|
272
|
50
|
|
|
|
|
});} |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
static int _on_svdup (pTHX_ MAGIC* mg, CLONE_PARAMS*) { return throw_guard(Sub(), [=]() -> int { |
|
209
|
|
|
|
|
|
|
using IType = typename Typemap::IType; |
|
210
|
|
|
|
|
|
|
TYPEMAP downgraded = IType::template in(mg->mg_ptr); |
|
211
|
|
|
|
|
|
|
TYPEMAP new_downgraded = Typemap::dup(downgraded); |
|
212
|
|
|
|
|
|
|
_on_svdup_br(downgraded, new_downgraded, BACKREF()); |
|
213
|
|
|
|
|
|
|
mg->mg_ptr = (char*)IType::out(new_downgraded); |
|
214
|
|
|
|
|
|
|
return 0; |
|
215
|
|
|
|
|
|
|
});} |
|
216
|
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
static void _on_svdup_br (const TYPEMAP&, const TYPEMAP&, std::false_type) {} |
|
218
|
|
|
|
|
|
|
static void _on_svdup_br (const TYPEMAP& var, const TYPEMAP& new_var, std::true_type) { |
|
219
|
|
|
|
|
|
|
auto br = Backref::get(var); |
|
220
|
|
|
|
|
|
|
auto new_br = Backref::get(new_var); |
|
221
|
|
|
|
|
|
|
if (br && br->svobj && new_br) { |
|
222
|
|
|
|
|
|
|
new_br->svobj = MUTABLE_SV(ptr_table_fetch(PL_ptr_table, br->svobj)); |
|
223
|
|
|
|
|
|
|
assert(new_br->svobj); |
|
224
|
|
|
|
|
|
|
} |
|
225
|
|
|
|
|
|
|
} |
|
226
|
|
|
|
|
|
|
}; |
|
227
|
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
template using ObjectStorageMG = ObjectStorageMG_Impl; |
|
229
|
|
|
|
|
|
|
template using ObjectStorageMGBackref = ObjectStorageMG_Impl; |
|
230
|
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
struct ObjectTypePtr { |
|
232
|
|
|
|
|
|
|
template static inline T in (void* p) { return static_cast(p); } |
|
233
|
|
|
|
|
|
|
template static inline const void* out (T* var) { return var; } |
|
234
|
|
|
|
|
|
|
template static inline void destroy (T* var, SV*) { delete var; } |
|
235
|
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
template static inline TO cast (FROM* var) { return static_cast(const_cast*>(var)); } |
|
237
|
|
|
|
|
|
|
template static inline TO upgrade (FROM* var) { return panda::dyn_cast(var); } |
|
238
|
|
|
|
|
|
|
}; |
|
239
|
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
struct ObjectTypeForeignPtr { |
|
241
|
|
|
|
|
|
|
template static inline T in (void* p) { return static_cast(p); } |
|
242
|
|
|
|
|
|
|
template static inline const void* out (T* var) { return var; } |
|
243
|
|
|
|
|
|
|
template static inline void destroy (T*, SV*) {} |
|
244
|
|
|
|
|
|
|
|
|
245
|
|
|
|
|
|
|
template static inline TO cast (FROM* var) { return static_cast(const_cast*>(var)); } |
|
246
|
|
|
|
|
|
|
template static inline TO upgrade (FROM* var) { return panda::dyn_cast(var); } |
|
247
|
|
|
|
|
|
|
}; |
|
248
|
|
|
|
|
|
|
|
|
249
|
|
|
|
|
|
|
struct ObjectTypeRefcntPtr { |
|
250
|
2496
|
|
|
|
|
|
template static inline T in (void* p) { return static_cast(p); } |
|
251
|
272
|
|
|
|
|
|
template static inline const void* out (T* var) { refcnt_inc(var); return var; } |
|
252
|
272
|
|
|
|
|
|
template static inline void destroy (T* var, SV*) { refcnt_dec(var); } |
|
253
|
0
|
|
|
|
|
|
template static inline void retain (T* var) { refcnt_inc(var); } |
|
254
|
0
|
|
|
|
|
|
template static inline void release (T* var) { refcnt_dec(var); } |
|
255
|
226
|
|
|
|
|
|
template static inline uint32_t use_count (T* var) { return refcnt_get(var); } |
|
256
|
|
|
|
|
|
|
|
|
257
|
272
|
|
|
|
|
|
template static inline TO cast (FROM* var) { return static_cast(const_cast*>(var)); } |
|
258
|
2224
|
|
|
|
|
|
template static inline TO upgrade (FROM* var) { return panda::dyn_cast(var); } |
|
259
|
|
|
|
|
|
|
}; |
|
260
|
|
|
|
|
|
|
|
|
261
|
|
|
|
|
|
|
struct ObjectTypeSharedPtr { |
|
262
|
|
|
|
|
|
|
template static inline T in (void* p) { return *(static_cast(p)); } |
|
263
|
|
|
|
|
|
|
template static inline const void* out (const std::shared_ptr& var) { return new std::shared_ptr(var); } |
|
264
|
|
|
|
|
|
|
|
|
265
|
|
|
|
|
|
|
template static inline void retain (const std::shared_ptr& var) { |
|
266
|
|
|
|
|
|
|
char tmp[sizeof(var)]; |
|
267
|
|
|
|
|
|
|
new (tmp) std::shared_ptr(var); |
|
268
|
|
|
|
|
|
|
} |
|
269
|
|
|
|
|
|
|
|
|
270
|
|
|
|
|
|
|
template static inline void release (const std::shared_ptr& var) { |
|
271
|
|
|
|
|
|
|
std::shared_ptr tmp; |
|
272
|
|
|
|
|
|
|
memcpy(&tmp, &var, sizeof(tmp)); |
|
273
|
|
|
|
|
|
|
} |
|
274
|
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
template static inline uint32_t use_count (const std::shared_ptr& var) { return var.use_count() - 1; } |
|
276
|
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
template static inline void destroy (const std::shared_ptr&, SV* arg) { |
|
278
|
|
|
|
|
|
|
using sp_t = std::shared_ptr; |
|
279
|
|
|
|
|
|
|
void* p = Typemap::IStorage::get(arg); |
|
280
|
|
|
|
|
|
|
delete static_cast(p); |
|
281
|
|
|
|
|
|
|
} |
|
282
|
|
|
|
|
|
|
|
|
283
|
|
|
|
|
|
|
template static inline TO cast (const std::shared_ptr& var) { |
|
284
|
|
|
|
|
|
|
return std::static_pointer_cast(std::const_pointer_cast>(var)); |
|
285
|
|
|
|
|
|
|
} |
|
286
|
|
|
|
|
|
|
|
|
287
|
|
|
|
|
|
|
template static inline TO upgrade (const std::shared_ptr& var) { |
|
288
|
|
|
|
|
|
|
return std::dynamic_pointer_cast(var); |
|
289
|
|
|
|
|
|
|
} |
|
290
|
|
|
|
|
|
|
}; |
|
291
|
|
|
|
|
|
|
|
|
292
|
|
|
|
|
|
|
using StaticCast = std::true_type; |
|
293
|
|
|
|
|
|
|
using DynamicCast = std::false_type; |
|
294
|
|
|
|
|
|
|
|
|
295
|
|
|
|
|
|
|
template class _IStorage, class CastType = StaticCast> |
|
296
|
|
|
|
|
|
|
struct TypemapObject : TypemapBase { |
|
297
|
|
|
|
|
|
|
using IType = _IType; |
|
298
|
|
|
|
|
|
|
using IStorage = _IStorage; |
|
299
|
|
|
|
|
|
|
using TypeNP = typename std::remove_pointer::type; |
|
300
|
|
|
|
|
|
|
|
|
301
|
976
|
|
|
|
|
|
static TYPE in (SV* arg) { |
|
302
|
976
|
50
|
|
|
|
|
if (!SvOBJECT(arg)) { |
|
|
|
50
|
|
|
|
|
|
|
303
|
976
|
50
|
|
|
|
|
if (SvROK(arg)) { |
|
|
|
50
|
|
|
|
|
|
|
304
|
976
|
|
|
|
|
|
arg = SvRV(arg); |
|
305
|
976
|
50
|
|
|
|
|
if (!SvOBJECT(arg)) throw "arg is a reference to non-object"; |
|
|
|
50
|
|
|
|
|
|
|
306
|
|
|
|
|
|
|
} |
|
307
|
0
|
0
|
|
|
|
|
else if (!SvOK(arg)) return TYPE(); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
308
|
0
|
|
|
|
|
|
else throw "arg is not a reference to object"; |
|
309
|
|
|
|
|
|
|
} |
|
310
|
|
|
|
|
|
|
|
|
311
|
976
|
50
|
|
|
|
|
auto ptr = IStorage::get(arg); |
|
|
|
50
|
|
|
|
|
|
|
312
|
976
|
50
|
|
|
|
|
if (ptr) { |
|
|
|
50
|
|
|
|
|
|
|
313
|
976
|
|
|
|
|
|
TYPEMAP downgraded = IType::template in(ptr); |
|
314
|
976
|
50
|
|
|
|
|
TYPE ret = cast(downgraded); |
|
|
|
50
|
|
|
|
|
|
|
315
|
976
|
50
|
|
|
|
|
if (ret) { |
|
|
|
50
|
|
|
|
|
|
|
316
|
972
|
50
|
|
|
|
|
if (!std::is_const::value && SvREADONLY(arg)) throw "cannot modify read-only object"; |
|
317
|
976
|
|
|
|
|
|
return ret; |
|
318
|
|
|
|
|
|
|
} |
|
319
|
|
|
|
|
|
|
} |
|
320
|
|
|
|
|
|
|
|
|
321
|
|
|
|
|
|
|
// it's definitely developer bug, there is no known way to determine real object tyep |
|
322
|
|
|
|
|
|
|
// from void*, see https://stackoverflow.com/questions/1718412/find-out-type-of-c-void-pointer |
|
323
|
0
|
|
|
|
|
|
auto package = Typemap::package(); |
|
324
|
0
|
|
|
|
|
|
auto package_view = panda::string_view{ package.data(), package.length() }; |
|
325
|
976
|
|
|
|
|
|
typemap::object::_throw_incorrect_arg(arg, typeid (TYPE), package_view); |
|
326
|
|
|
|
|
|
|
} |
|
327
|
|
|
|
|
|
|
|
|
328
|
272
|
|
|
|
|
|
static Sv out (const TYPE& var, const Sv& proto = Sv()) { return IStorage::out(var, proto); } |
|
329
|
|
|
|
|
|
|
|
|
330
|
|
|
|
|
|
|
/* proto is a hint for TypemapObject's out/create to attach 'var' to |
|
331
|
|
|
|
|
|
|
* it might be: |
|
332
|
|
|
|
|
|
|
* 1) blessed object (or reference to it): in this case it is used as final object |
|
333
|
|
|
|
|
|
|
* typical usage - when calling next method |
|
334
|
|
|
|
|
|
|
* PROTO = stash.call_next(...); |
|
335
|
|
|
|
|
|
|
* 2) class name or stash to bless to: in this case reference to undef is created and blessed into this class |
|
336
|
|
|
|
|
|
|
* typical usage - in constructor, to bless to the class 'new' was called into, not to default class |
|
337
|
|
|
|
|
|
|
* PROTO = ST(0); |
|
338
|
|
|
|
|
|
|
* 3) other values (or reference to it): in this case it is blessed to typemap's default class and used |
|
339
|
|
|
|
|
|
|
* typical usage - in constructor or in overloaded typemap's create() method to specify object's base |
|
340
|
|
|
|
|
|
|
* PROTO = Array::create(); |
|
341
|
|
|
|
|
|
|
* 4) empty: in this case reference to undef is created and blessed to typemap's default class and used |
|
342
|
|
|
|
|
|
|
*/ |
|
343
|
136
|
|
|
|
|
|
static Sv create (const TYPE& var, const Sv& proto = Sv()) { |
|
344
|
136
|
50
|
|
|
|
|
if (!var) return &PL_sv_undef; |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
345
|
272
|
|
|
|
|
|
Sv rv; |
|
346
|
|
|
|
|
|
|
SV* base; |
|
347
|
136
|
50
|
|
|
|
|
if (proto) { |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
348
|
134
|
50
|
|
|
|
|
if (SvROK(proto)) { // ref to object/base |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
349
|
0
|
0
|
|
|
|
|
rv = proto; |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
350
|
0
|
|
|
|
|
|
base = SvRV(proto); |
|
351
|
|
|
|
|
|
|
} |
|
352
|
134
|
50
|
|
|
|
|
else if (proto.type() <= SVt_PVMG) { // class name |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
353
|
115
|
50
|
|
|
|
|
if (SvOBJECT(proto)) { |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
354
|
0
|
|
|
|
|
|
base = proto; |
|
355
|
0
|
0
|
|
|
|
|
rv = Sv::noinc(newRV_noinc(base)); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
356
|
|
|
|
|
|
|
} else { |
|
357
|
115
|
50
|
|
|
|
|
base = newSV_type(SVt_PVMG); |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
358
|
115
|
50
|
|
|
|
|
rv = Sv::noinc(newRV_noinc(base)); |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
359
|
115
|
50
|
|
|
|
|
sv_bless(rv, gv_stashsv(proto, GV_ADD)); |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
360
|
|
|
|
|
|
|
} |
|
361
|
115
|
|
|
|
|
|
goto ATTACH; // skip optional blessing |
|
362
|
|
|
|
|
|
|
} |
|
363
|
19
|
0
|
|
|
|
|
else if (proto.type() == SVt_PVHV && HvNAME(proto)) { // stash |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
364
|
19
|
0
|
|
|
|
|
base = newSV_type(SVt_PVMG); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
365
|
19
|
0
|
|
|
|
|
rv = Sv::noinc(newRV_noinc(base)); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
366
|
19
|
0
|
|
|
|
|
sv_bless(rv, proto.get()); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
367
|
19
|
|
|
|
|
|
goto ATTACH; // skip optional blessing |
|
368
|
|
|
|
|
|
|
} |
|
369
|
|
|
|
|
|
|
else { // base given |
|
370
|
0
|
0
|
|
|
|
|
rv = Sv::noinc(newRV(proto)); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
371
|
0
|
|
|
|
|
|
base = proto; |
|
372
|
|
|
|
|
|
|
} |
|
373
|
|
|
|
|
|
|
} |
|
374
|
|
|
|
|
|
|
else { // nothing given, create ref to undef |
|
375
|
2
|
0
|
|
|
|
|
base = newSV_type(SVt_PVMG); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
376
|
2
|
0
|
|
|
|
|
rv = Sv::noinc(newRV_noinc(base)); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
377
|
2
|
|
|
|
|
|
goto BLESS; // definitely needs blessing |
|
378
|
|
|
|
|
|
|
} |
|
379
|
|
|
|
|
|
|
|
|
380
|
0
|
0
|
|
|
|
|
if (!SvOBJECT(base)) { // not blessed -> bless to default typemap's class |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
381
|
|
|
|
|
|
|
BLESS: |
|
382
|
2
|
0
|
|
|
|
|
static PERL_THREAD_LOCAL HV* stash = gv_stashpvn(Typemap::package().data(), Typemap::package().length(), GV_ADD); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
383
|
2
|
0
|
|
|
|
|
sv_bless(rv, stash); // TODO: custom faster bless |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
384
|
|
|
|
|
|
|
} |
|
385
|
|
|
|
|
|
|
|
|
386
|
|
|
|
|
|
|
ATTACH: |
|
387
|
136
|
50
|
|
|
|
|
IStorage::set(base, const_cast(IType::out(IType::template cast(var)))); |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
388
|
|
|
|
|
|
|
|
|
389
|
|
|
|
|
|
|
if (std::is_const::value) SvREADONLY_on(base); |
|
390
|
|
|
|
|
|
|
|
|
391
|
136
|
|
|
|
|
|
return rv; |
|
392
|
|
|
|
|
|
|
} |
|
393
|
|
|
|
|
|
|
|
|
394
|
|
|
|
|
|
|
static TYPEMAP dup (const TYPEMAP& obj) { return obj; } |
|
395
|
|
|
|
|
|
|
|
|
396
|
136
|
|
|
|
|
|
static void dispose (const TYPE& var, SV* arg) { |
|
397
|
136
|
|
|
|
|
|
IType::destroy(var, arg); |
|
398
|
136
|
|
|
|
|
|
} |
|
399
|
|
|
|
|
|
|
|
|
400
|
|
|
|
|
|
|
static void destroy (const TYPE& var, SV* arg) { |
|
401
|
|
|
|
|
|
|
if (!std::is_same::value) return; |
|
402
|
|
|
|
|
|
|
if (!IStorage::auto_disposable) dispose(var, arg); |
|
403
|
|
|
|
|
|
|
} |
|
404
|
|
|
|
|
|
|
|
|
405
|
1112
|
50
|
|
|
|
|
template static inline TO cast (FROM v) { return _cast(v, CastType()); } |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
406
|
|
|
|
|
|
|
|
|
407
|
|
|
|
|
|
|
static panda::string_view package () { typemap::object::_throw_no_package(typeid(TYPE)); return ""; } |
|
408
|
|
|
|
|
|
|
|
|
409
|
|
|
|
|
|
|
static Stash default_stash () { |
|
410
|
|
|
|
|
|
|
static PERL_THREAD_LOCAL Stash stash = gv_stashpvn(Typemap::package().data(), Typemap::package().length(), GV_ADD); |
|
411
|
|
|
|
|
|
|
return stash; |
|
412
|
|
|
|
|
|
|
} |
|
413
|
|
|
|
|
|
|
|
|
414
|
|
|
|
|
|
|
private: |
|
415
|
2224
|
|
|
|
|
|
template static inline TO _cast (FROM v, DynamicCast) { return IType::template upgrade(v); } |
|
416
|
|
|
|
|
|
|
template static inline TO _cast (FROM v, StaticCast) { return IType::template cast(v); } |
|
417
|
|
|
|
|
|
|
}; |
|
418
|
|
|
|
|
|
|
|
|
419
|
|
|
|
|
|
|
} |