Skip to content

Commit 69c3183

Browse files
committed
Fix problems ans Add tests
1 parent e97af6c commit 69c3183

12 files changed

Lines changed: 205 additions & 31 deletions

src/Core/JVM/Invoker/Invokable.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ function ($item) {
217217
'OpCode: 0x%02X %-15.15s Stacks: %-4.4s PC: %-8.8s Used Memory: %-8.8s Used Memory Peak: %-8.8s',
218218
[
219219
$opcode,
220-
str_replace('_', '', $mnemonic),
220+
ltrim($mnemonic, '_'),
221221
count($stacks),
222222
$pointer,
223223
Metric::bytes(memory_get_usage())->format(),

src/Core/JavaArchive.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use PHPJava\Core\JVM\Parameters\Runtime;
66
use PHPJava\Core\Stream\Reader\InlineReader;
77
use PHPJava\Exceptions\UndefinedEntrypointException;
8+
use PHPJava\Kernel\Internal\JavaClassDeferredLoader;
89
use PHPJava\Packages\java\io\FileNotFoundException;
910
use PHPJava\Packages\java\lang\_Object;
1011
use PHPJava\Packages\java\lang\ClassNotFoundException;
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<?php
2+
namespace PHPJava\Exceptions;
3+
4+
class NotInstantiatedException extends \Exception
5+
{
6+
}

src/Kernel/Core/Accumulator.php

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -136,18 +136,21 @@ public function pushToOperandStackByReference(&$value)
136136
$this->stacks[] = &$value;
137137
}
138138

139-
public function dupStack()
139+
public function popFromOperandStack()
140140
{
141-
$stack = $this->stacks[sizeof($this->stacks) - 1] ?? null;
142-
if ($stack === null) {
143-
throw new \Exception('Stack overflow');
144-
}
145-
$this->pushStack($stack);
141+
return array_pop($this->stacks);
146142
}
147143

148-
public function popFromOperandStack()
144+
public function getCurrentStackIndex()
149145
{
150-
return array_pop($this->stacks);
146+
return count($this->stacks) - 1;
147+
}
148+
149+
public function replaceReferredObject($searchObject, $newObject)
150+
{
151+
while (($index = array_search($searchObject, $this->stacks)) !== false) {
152+
$this->stacks[$index] = $newObject;
153+
}
151154
}
152155

153156
public function popStack()
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
<?php
2+
namespace PHPJava\Kernel\Internal;
3+
4+
use PHPJava\Core\JavaClassInterface;
5+
use PHPJava\Exceptions\NotInstantiatedException;
6+
use PHPJava\Utilities\ClassResolver;
7+
8+
final class InstanceDeferredLoader
9+
{
10+
private $instance;
11+
private $classObject;
12+
private $resourceType;
13+
private $className;
14+
15+
/**
16+
* InstanceDeferredLoader constructor.
17+
* @param $classObject
18+
* @param $resourceType
19+
* @param $className
20+
*/
21+
public function __construct(
22+
$classObject,
23+
$resourceType,
24+
$className
25+
) {
26+
$this->classObject = $classObject;
27+
$this->resourceType = $resourceType;
28+
$this->className = $className;
29+
}
30+
31+
/**
32+
* @param mixed ...$arguments
33+
* @return mixed
34+
*/
35+
public function instantiate(...$arguments)
36+
{
37+
$object = $this->classObject;
38+
switch ($this->resourceType) {
39+
case ClassResolver::RESOLVED_TYPE_CLASS:
40+
$this->instance = $object(...$arguments);
41+
break;
42+
case ClassResolver::RESOLVED_TYPE_PACKAGES:
43+
$this->instance = new $object(...$arguments);
44+
break;
45+
}
46+
47+
return $this->instance;
48+
}
49+
50+
/**
51+
* @return string
52+
*/
53+
public function getClassName(): string
54+
{
55+
return $this->className;
56+
}
57+
58+
/**
59+
* @return mixed
60+
*/
61+
public function getInstance()
62+
{
63+
return $this->instance;
64+
}
65+
}

src/Kernel/Internal/JavaClassDeferredLoader.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<?php
22
namespace PHPJava\Kernel\Internal;
33

4+
use PHPJava\Core\JavaClass;
45
use PHPJava\Core\JavaClassInterface;
56

67
final class JavaClassDeferredLoader implements JavaClassInterface

src/Kernel/Mnemonics/_dup.php

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,6 @@ final class _dup implements OperationInterface
1212

1313
public function execute(): void
1414
{
15-
$stack = $this->stacks[sizeof($this->stacks) - 1] ?? null;
16-
if ($stack === null) {
17-
throw new RuntimeException('Stack overflow');
18-
}
19-
$this->pushToOperandStack($stack);
15+
$this->stacks[] = $this->stacks[$this->getCurrentStackIndex()] ?? null;
2016
}
2117
}

src/Kernel/Mnemonics/_invokespecial.php

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use PHPJava\Exceptions\NotImplementedException;
66
use PHPJava\Exceptions\UnableToCatchException;
77
use PHPJava\Kernel\Attributes\CodeAttribute;
8+
use PHPJava\Kernel\Internal\InstanceDeferredLoader;
89
use PHPJava\Kernel\Structures\_ExceptionTable;
910
use PHPJava\Utilities\AttributionResolver;
1011
use PHPJava\Utilities\BinaryTool;
@@ -30,22 +31,20 @@ public function execute(): void
3031
$parsedSignature = Formatter::parseSignature($signature);
3132

3233
// POP with right-to-left (objectref + arguments)
33-
$collection = array_fill(0, $parsedSignature['arguments_count'] + 1, null);
34-
for ($i = count($collection) - 1; $i >= 0; $i--) {
35-
$collection[$i] = $this->popFromOperandStack();
34+
$arguments = array_fill(0, $parsedSignature['arguments_count'], null);
35+
for ($i = count($arguments) - 1; $i >= 0; $i--) {
36+
$arguments[$i] = $this->popFromOperandStack();
3637
}
3738

38-
$objectref = $collection[0];
39-
39+
/**
40+
* @var InstanceDeferredLoader $objectref
41+
*/
42+
$objectref = $this->popFromOperandStack();
43+
$newObject = null;
4044
try {
41-
42-
// NOTE: first arguments is a class object. (PHPJava does not needed.)
43-
$arguments = array_values(array_slice($collection, 1));
4445
$methodName = $cpInfo[$nameAndTypeIndex->getNameIndex()]->getString();
4546

46-
if ($objectref instanceof JavaClass &&
47-
$objectref->getClassName() !== $className
48-
) {
47+
if ($objectref->getClassName() !== $className) {
4948
// If $objectref is not match $className, then change current class (I have no confidence).
5049
// See also: https://docs.oracle.com/javase/specs/jvms/se11/html/jvms-6.html#jvms-6.5.invokespecial
5150

@@ -57,16 +56,18 @@ public function execute(): void
5756

5857
switch ($resourceType) {
5958
case ClassResolver::RESOLVED_TYPE_PACKAGES:
60-
$objectref = new $classObject(...$arguments);
59+
$newObject = new $classObject(...$arguments);
6160
break;
6261
case ClassResolver::RESOLVED_TYPE_CLASS:
63-
throw new NotImplementedException('This section is not implementation.');
62+
$newObject = $classObject(...$arguments);
63+
break;
6464
}
65-
} elseif ($objectref instanceof JavaClass) {
66-
$objectref = $objectref(...$arguments);
6765
} else {
68-
$objectref = new $objectref(...$arguments);
66+
$newObject = $objectref->instantiate(...$arguments);
6967
}
68+
69+
// NOTE: PHP has a problem which a reference object cannot replace to an object.
70+
$this->replaceReferredObject($objectref, $newObject);
7071
} catch (\Exception $e) {
7172
/**
7273
* @var $codeAttribute CodeAttribute

src/Kernel/Mnemonics/_new.php

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
namespace PHPJava\Kernel\Mnemonics;
33

44
use PHPJava\Exceptions\NotImplementedException;
5+
use PHPJava\Kernel\Internal\InstanceDeferredLoader;
56
use PHPJava\Utilities\BinaryTool;
67
use PHPJava\Utilities\ClassResolver;
78

@@ -19,8 +20,14 @@ public function execute(): void
1920
[$resourceType, $classObject] = $this->getOptions('class_resolver')
2021
->resolve($className, $this->javaClass);
2122

23+
$instanceDeferredLoader = new InstanceDeferredLoader(
24+
$classObject,
25+
$resourceType,
26+
$className
27+
);
28+
2229
$this->pushToOperandStackByReference(
23-
$classObject
30+
$instanceDeferredLoader
2431
);
2532
}
2633
}

tests/ConstructTest.php

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,68 @@ class ConstructTest extends Base
77
{
88
protected $fixtures = [
99
'ConstructTest',
10+
'ConstructorWithParametersTest',
11+
'ConstructorNoParameterTest',
1012
];
1113

14+
public function testConstructorWithParameters_Pattern1()
15+
{
16+
ob_start();
17+
$result = $this->initiatedJavaClasses['ConstructorWithParametersTest']
18+
->getInvoker()
19+
->getStatic()
20+
->getMethods()
21+
->call(
22+
'main',
23+
[]
24+
);
25+
$result = ob_get_clean();
26+
$this->assertEquals("Hello World!\n", $result);
27+
}
28+
29+
30+
public function testConstructorWithParameters_Pattern2()
31+
{
32+
ob_start();
33+
$result = $this->initiatedJavaClasses['ConstructorWithParametersTest']
34+
->getInvoker()
35+
->construct("Hello World!")
36+
->getDynamic()
37+
->getMethods()
38+
->call('entrypoint');
39+
$result = ob_get_clean();
40+
$this->assertEquals("Hello World!\nEntrypoint\n", $result);
41+
}
42+
43+
public function testConstructorNoParameter_Pattern1()
44+
{
45+
ob_start();
46+
$result = $this->initiatedJavaClasses['ConstructorNoParameterTest']
47+
->getInvoker()
48+
->getStatic()
49+
->getMethods()
50+
->call(
51+
'main',
52+
[]
53+
);
54+
$result = ob_get_clean();
55+
$this->assertEquals("Hello World!\n", $result);
56+
}
57+
58+
59+
public function testConstructorNoParameter_Pattern2()
60+
{
61+
ob_start();
62+
$result = $this->initiatedJavaClasses['ConstructorNoParameterTest']
63+
->getInvoker()
64+
->construct()
65+
->getDynamic()
66+
->getMethods()
67+
->call('entrypoint');
68+
$result = ob_get_clean();
69+
$this->assertEquals("Hello World!\nEntrypoint\n", $result);
70+
}
71+
1272
public function testDynamicField()
1373
{
1474
$text = $this->initiatedJavaClasses['ConstructTest']

0 commit comments

Comments
 (0)