File Coverage

blib/lib/PJVM/Runtime.pm
Criterion Covered Total %
statement 22 24 91.6
branch n/a
condition n/a
subroutine 8 8 100.0
pod n/a
total 30 32 93.7


line stmt bran cond sub pod time code
1             package PJVM::Runtime;
2              
3 4     4   63156 use strict;
  4         9  
  4         159  
4 4     4   19 use warnings;
  4         6  
  4         116  
5              
6 4     4   5200 use Module::Load qw();
  4         5258  
  4         92  
7 4     4   27 use Scalar::Util qw(blessed);
  4         7  
  4         408  
8              
9 4     4   1750 use PJVM::Runtime::Class;
  4         13  
  4         36  
10 4     4   2184 use PJVM::Runtime::Object;
  4         13  
  4         155  
11              
12 4         21 use Object::Tiny qw(
13             classpath
14             system_class_loader
15             default_execution_engine
16             class_registry
17             stack
18 4     4   24 );
  4         7  
19              
20             require Exporter;
21              
22             our @ISA = qw(Exporter);
23              
24             our @EXPORT;
25             our @EXPORT_OK = qw(rt_push_stack rt_pop_stack);
26             our %EXPORT_TAGS = (
27             stack => [qw(rt_push_stack rt_pop_stack)],
28             );
29              
30             use Module::Pluggable
31 0           search_path => [qw(PJVM::Runtime::Native)],
32 4     4   8606 sub_name => "native_classes";
  0            
33              
34             # Stack functions
35             {
36             my $stack;
37              
38             # Sets the current stack
39             sub rt_set_stack {
40             $stack = shift;
41             }
42              
43             sub rt_pop_stack() {
44             return pop @$stack;
45             }
46              
47             sub rt_push_stack($) {
48             push @$stack, @_;
49             1;
50             }
51             }
52              
53             sub new {
54             my ($pkg, $args) = @_;
55              
56             $args = {} unless ref $args eq "HASH";
57            
58             # Default class loader
59             my $class_loader = $args->{class_loader} || "PJVM::ClassLoader";
60             if ($class_loader eq "PJVM::ClassLoader") {
61             require PJVM::ClassLoader;
62             }
63             my $system_class_loader = blessed $class_loader ? $class_loader : $class_loader->new($args);
64            
65             # The object that runs the actual bytecode
66             my $engine = $args->{engine} || "PJVM::ExecutionEngine::SimpleRunloop";
67             if ($engine eq "PJVM::ExecutionEngine::SimpleRunloop") {
68             require PJVM::ExecutionEngine::SimpleRunloop;
69             }
70             my $default_engine = blessed $engine ? $engine : $engine->new($args);
71            
72             my $self = bless {
73             classpath => $args->{classpath},
74             system_class_loader => $system_class_loader,
75             default_execution_engine => $default_engine,
76             class_registry => {},
77             stack => [],
78             }, $pkg;
79            
80             # Setup native classes
81             for my $native_pkg ($self->native_classes) {
82             Module::Load::load $native_pkg;
83             my $class = $native_pkg->new();
84             $self->register_class($class);
85             }
86            
87             return $self;
88             }
89              
90             sub find_class {
91             my ($self, $classname) = @_;
92             return $self->get_class($classname) if $self->has_class($classname);
93             return $self->load_class($classname);
94             }
95              
96             sub load_class {
97             my ($self, $classname) = @_;
98            
99             return $self->get_class($classname) if $self->has_class($classname);
100            
101             my @classes = $self->system_class_loader->load_class($classname);
102             $self->register_class($_) for @classes;
103            
104             my $class = $self->get_class($classname);
105             die "NoClassDefFoundError" unless $class;
106             return $class;
107             }
108              
109             sub has_class {
110             my ($self, $class) = @_;
111             return exists $self->class_registry->{$class};
112             }
113              
114             sub get_class {
115             my ($self, $class) = @_;
116             return $self->class_registry->{$class};
117             }
118              
119             sub register_class {
120             my ($self, $class) = @_;
121            
122             if ($class->isa("PJVM::Class")) {
123             $class = PJVM::Runtime::Class->new_from_spec($self, $class);
124             }
125              
126             $self->class_registry->{$class->qname} = $class;
127            
128             1;
129             }
130              
131             sub call {
132             my ($rt, $signature, $instance, @args) = @_;
133            
134             rt_set_stack($rt->stack);
135            
136             # this
137             rt_push_stack $instance;
138            
139             my $method = $instance->class->get_method($signature);
140            
141             # Throw some shit on stack
142             rt_push_stack $_ for @args;
143            
144             # Run method
145             $method->();
146            
147             # Get result from stack if not void
148             my $result;
149             if ($signature !~ m/\)V$/) {
150             $result = rt_pop_stack;
151             }
152            
153             return $result;
154             }
155              
156             sub instantiate {
157             my ($self, $class) = @_;
158             my $object = PJVM::Runtime::Object->new($class);
159             return $object;
160             }
161              
162             1;
163             __END__