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__ |