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   3277 use strict;
  15         35  
  15         474  
4 15     15   88 use warnings;
  15         31  
  15         345  
5 15     15   256 use 5.008004;
  15         55  
6 15     15   88 use Wasm::Wasmtime::FFI;
  15         54  
  15         1585  
7 15     15   4617 use Wasm::Wasmtime::Module;
  15         58  
  15         573  
8 15     15   977 use Wasm::Wasmtime::Extern;
  15         37  
  15         455  
9 15     15   90 use Wasm::Wasmtime::Func;
  15         40  
  15         391  
10 15     15   83 use Wasm::Wasmtime::Trap;
  15         56  
  15         382  
11 15     15   7008 use Wasm::Wasmtime::Instance::Exports;
  15         38  
  15         495  
12 15     15   93 use Ref::Util qw( is_ref is_blessed_ref is_plain_coderef is_plain_scalarref );
  15         35  
  15         901  
13 15     15   101 use Carp ();
  15         30  
  15         14206  
14              
15             # ABSTRACT: Wasmtime instance class
16             our $VERSION = '0.23'; # 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   12 my($ii, $mi, $store, $keep) = @_;
26 5 50 66     51 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         10 return $ii->{ptr};
33             }
34             elsif(is_plain_coderef($ii))
35             {
36 1 50       5 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         5 push @$keep, $f;
44 1         5 return $f->{ptr};
45             }
46             }
47             elsif(is_plain_scalarref($ii) || !defined $ii)
48             {
49 2 50       7 if($mi->type->kind eq 'memorytype')
50             {
51 2         8 my $m = Wasm::Wasmtime::Memory->new(
52             $store,
53             $mi->type,
54             );
55 2 100       108 $$ii = $m if defined $ii;
56 2         6 push @$keep, $m;
57 2         7 return $m->{ptr};
58             }
59             }
60 0         0 Carp::croak("Non-extern object as import");
61             }
62              
63             require FFI::Platypus::Memory;
64              
65             $ffi->attach( [ wasmtime_instance_new => 'new' ] => ['wasm_store_t','wasm_module_t','record(Wasm::Wasmtime::Vec)*','opaque*','opaque*'] => 'wasmtime_error_t' => sub {
66             my $xsub = shift;
67             my $class = shift;
68             my $module = shift;
69             my $store = is_blessed_ref($_[0]) && $_[0]->isa('Wasm::Wasmtime::Store')
70             ? shift
71             : Carp::croak('Creating a Wasm::Wasmtime::Instance instance without a Wasm::Wasmtime::Store object is no longer allowed');
72              
73             my $ptr;
74             my @keep;
75              
76             if(defined $_[0] && !is_ref($_[0]))
77             {
78             ($ptr) = @_;
79             return bless {
80             ptr => $ptr,
81             module => $module,
82             keep => \@keep,
83             }, $class;
84             }
85             else
86             {
87             my($imports) = @_;
88              
89             $imports ||= [];
90             Carp::confess("imports is not an array reference") unless ref($imports) eq 'ARRAY';
91             my @imports = @$imports;
92             my $trap;
93              
94             {
95             my @mi = @{ $module->imports };
96             if(@mi != @imports)
97             {
98             Carp::croak("Got @{[ scalar @imports ]} imports, but expected @{[ scalar @mi ]}");
99             }
100              
101             @imports = map { _cast_import($_, shift @mi, $store, \@keep) } @imports;
102             }
103              
104             my $imports_vec = Wasm::Wasmtime::Vec->new(
105             size => scalar @imports,
106             data => scalar(@imports) > 0 ? do {
107             my $count = scalar @imports;
108             my $ptr = FFI::Platypus::Memory::malloc($ffi->sizeof('opaque') * $count);
109             # void *memcpy(void *dest, const void *src, size_t n)
110             FFI::Platypus->new( lib => [undef] )->function( 'memcpy' => [ 'opaque', "opaque[$count]", 'size_t' ] => 'opaque' )->call($ptr, \@imports, $ffi->sizeof('opaque') * $count);
111             } : undef,
112             );
113              
114             my $ptr;
115             if(my $error = $xsub->($store, $module, $imports_vec, \$ptr, \$trap))
116             {
117             FFI::Platypus::Memory::free($imports_vec->data) if defined $imports_vec->data;
118             Carp::croak("error creating module: " . $error->message);
119             }
120             else
121             {
122             FFI::Platypus::Memory::free($imports_vec->data) if defined $imports_vec->data;
123             if($trap)
124             {
125             $trap = Wasm::Wasmtime::Trap->new($trap);
126             die $trap;
127             }
128             else
129             {
130             return bless {
131             ptr => $ptr,
132             module => $module,
133             keep => \@keep,
134             }, $class;
135             }
136             }
137             }
138              
139             });
140              
141              
142 31     31 1 1757 sub module { shift->{module} }
143              
144              
145             sub exports
146             {
147 29     29 1 15285 Wasm::Wasmtime::Instance::Exports->new(shift);
148             }
149              
150             $ffi->attach( [ exports => '_exports' ] => ['wasm_instance_t','wasm_extern_vec_t*'] => sub {
151             my($xsub, $self) = @_;
152             my $externs = Wasm::Wasmtime::ExternVec->new;
153             $xsub->($self, $externs);
154             $externs->to_list;
155             });
156              
157             _generate_destroy();
158              
159             1;
160              
161             __END__