File Coverage

blib/lib/Wasm/Wasmtime/Instance.pm
Criterion Covered Total %
statement 46 48 95.8
branch 10 14 71.4
condition 4 6 66.6
subroutine 14 14 100.0
pod 2 2 100.0
total 76 84 90.4


line stmt bran cond sub pod time code
1             package Wasm::Wasmtime::Instance;
2              
3 15     15   3271 use strict;
  15         36  
  15         511  
4 15     15   90 use warnings;
  15         33  
  15         371  
5 15     15   251 use 5.008004;
  15         52  
6 15     15   89 use Wasm::Wasmtime::FFI;
  15         56  
  15         1722  
7 15     15   4710 use Wasm::Wasmtime::Module;
  15         50  
  15         576  
8 15     15   940 use Wasm::Wasmtime::Extern;
  15         60  
  15         436  
9 15     15   94 use Wasm::Wasmtime::Func;
  15         38  
  15         406  
10 15     15   97 use Wasm::Wasmtime::Trap;
  15         32  
  15         379  
11 15     15   7689 use Wasm::Wasmtime::Instance::Exports;
  15         39  
  15         502  
12 15     15   116 use Ref::Util qw( is_ref is_blessed_ref is_plain_coderef is_plain_scalarref );
  15         38  
  15         945  
13 15     15   93 use Carp ();
  15         33  
  15         19995  
14              
15             # ABSTRACT: Wasmtime instance class
16             our $VERSION = '0.22'; # VERSION
17              
18              
19             $ffi_prefix = 'wasm_instance_';
20             $ffi->load_custom_type('::PtrObject' => 'wasm_instance_t' => __PACKAGE__);
21              
22              
23             sub _cast_import
24             {
25 5     5   23 my($ii, $mi, $store, $keep) = @_;
26 5 50 66     49 if(ref($ii) eq 'Wasm::Wasmtime::Extern')
    100 66        
    100          
    50          
27             {
28 0         0 return $ii->{ptr};
29             }
30             elsif(is_blessed_ref($ii) && $ii->isa('Wasm::Wasmtime::Extern'))
31             {
32 2         13 return $ii->{ptr};
33             }
34             elsif(is_plain_coderef($ii))
35             {
36 1 50       4 if($mi->type->kind eq 'functype')
37             {
38 1         5 my $f = Wasm::Wasmtime::Func->new(
39             $store,
40             $mi->type,
41             $ii,
42             );
43 1         4 push @$keep, $f;
44 1         5 return $f->{ptr};
45             }
46             }
47             elsif(is_plain_scalarref($ii) || !defined $ii)
48             {
49 2 50       9 if($mi->type->kind eq 'memorytype')
50             {
51 2         7 my $m = Wasm::Wasmtime::Memory->new(
52             $store,
53             $mi->type,
54             );
55 2 100       111 $$ii = $m if defined $ii;
56 2         6 push @$keep, $m;
57 2         9 return $m->{ptr};
58             }
59             }
60 0         0 Carp::croak("Non-extern object as import");
61             }
62              
63             if(_v0_23_0())
64             {
65             require FFI::Platypus::Memory;
66              
67             $ffi->attach( [ wasmtime_instance_new => 'new' ] => ['wasm_store_t','wasm_module_t','record(Wasm::Wasmtime::Vec)*','opaque*','opaque*'] => 'wasmtime_error_t' => sub {
68             my $xsub = shift;
69             my $class = shift;
70             my $module = shift;
71             my $store = is_blessed_ref($_[0]) && $_[0]->isa('Wasm::Wasmtime::Store')
72             ? shift
73             : Carp::croak('Creating a Wasm::Wasmtime::Instance instance without a Wasm::Wasmtime::Store object is no longer allowed');
74              
75             my $ptr;
76             my @keep;
77              
78             if(defined $_[0] && !is_ref($_[0]))
79             {
80             ($ptr) = @_;
81             return bless {
82             ptr => $ptr,
83             module => $module,
84             keep => \@keep,
85             }, $class;
86             }
87             else
88             {
89             my($imports) = @_;
90              
91             $imports ||= [];
92             Carp::confess("imports is not an array reference") unless ref($imports) eq 'ARRAY';
93             my @imports = @$imports;
94             my $trap;
95              
96             {
97             my @mi = @{ $module->imports };
98             if(@mi != @imports)
99             {
100             Carp::croak("Got @{[ scalar @imports ]} imports, but expected @{[ scalar @mi ]}");
101             }
102              
103             @imports = map { _cast_import($_, shift @mi, $store, \@keep) } @imports;
104             }
105              
106             my $imports_vec = Wasm::Wasmtime::Vec->new(
107             size => scalar @imports,
108             data => scalar(@imports) > 0 ? do {
109             my $count = scalar @imports;
110             my $ptr = FFI::Platypus::Memory::malloc($ffi->sizeof('opaque') * $count);
111             # void *memcpy(void *dest, const void *src, size_t n)
112             FFI::Platypus->new( lib => [undef] )->function( 'memcpy' => [ 'opaque', "opaque[$count]", 'size_t' ] => 'opaque' )->call($ptr, \@imports, $ffi->sizeof('opaque') * $count);
113             } : undef,
114             );
115              
116             my $ptr;
117             if(my $error = $xsub->($store, $module, $imports_vec, \$ptr, \$trap))
118             {
119             FFI::Platypus::Memory::free($imports_vec->data) if defined $imports_vec->data;
120             Carp::croak("error creating module: " . $error->message);
121             }
122             else
123             {
124             FFI::Platypus::Memory::free($imports_vec->data) if defined $imports_vec->data;
125             if($trap)
126             {
127             $trap = Wasm::Wasmtime::Trap->new($trap);
128             die $trap;
129             }
130             else
131             {
132             return bless {
133             ptr => $ptr,
134             module => $module,
135             keep => \@keep,
136             }, $class;
137             }
138             }
139             }
140              
141             });
142              
143             }
144             else
145             {
146              
147             $ffi->attach( [ wasmtime_instance_new => 'new' ] => ['wasm_store_t','wasm_module_t','opaque[]','size_t','opaque*','opaque*'] => 'wasmtime_error_t' => sub {
148             my $xsub = shift;
149             my $class = shift;
150             my $module = shift;
151             my $store = is_blessed_ref($_[0]) && $_[0]->isa('Wasm::Wasmtime::Store')
152             ? shift
153             : Carp::croak('Creating a Wasm::Wasmtime::Instance instance without a Wasm::Wasmtime::Store object is no longer allowed');
154              
155             my $ptr;
156             my @keep;
157              
158             if(defined $_[0] && !is_ref($_[0]))
159             {
160             ($ptr) = @_;
161             return bless {
162             ptr => $ptr,
163             module => $module,
164             keep => \@keep,
165             }, $class;
166             }
167             else
168             {
169             my($imports) = @_;
170              
171             $imports ||= [];
172             Carp::confess("imports is not an array reference") unless ref($imports) eq 'ARRAY';
173             my @imports = @$imports;
174             my $trap;
175              
176             {
177             my @mi = @{ $module->imports };
178             if(@mi != @imports)
179             {
180             Carp::croak("Got @{[ scalar @imports ]} imports, but expected @{[ scalar @mi ]}");
181             }
182              
183             @imports = map { _cast_import($_, shift @mi, $store, \@keep) } @imports;
184             }
185              
186             my $ptr;
187             if(my $error = $xsub->($store, $module, \@imports, scalar(@imports), \$ptr, \$trap))
188             {
189             Carp::croak("error creating module: " . $error->message);
190             }
191             else
192             {
193             if($trap)
194             {
195             $trap = Wasm::Wasmtime::Trap->new($trap);
196             die $trap;
197             }
198             else
199             {
200             return bless {
201             ptr => $ptr,
202             module => $module,
203             keep => \@keep,
204             }, $class;
205             }
206             }
207             }
208              
209             });
210             }
211              
212              
213 31     31 1 2446 sub module { shift->{module} }
214              
215              
216             sub exports
217             {
218 29     29 1 15413 Wasm::Wasmtime::Instance::Exports->new(shift);
219             }
220              
221             $ffi->attach( [ exports => '_exports' ] => ['wasm_instance_t','wasm_extern_vec_t*'] => sub {
222             my($xsub, $self) = @_;
223             my $externs = Wasm::Wasmtime::ExternVec->new;
224             $xsub->($self, $externs);
225             $externs->to_list;
226             });
227              
228             _generate_destroy();
229              
230             1;
231              
232             __END__