55use PHPJava \Exceptions \NotImplementedException ;
66use PHPJava \Exceptions \UnableToCatchException ;
77use PHPJava \Kernel \Attributes \CodeAttribute ;
8+ use PHPJava \Kernel \Internal \InstanceDeferredLoader ;
89use PHPJava \Kernel \Structures \_ExceptionTable ;
910use PHPJava \Utilities \AttributionResolver ;
1011use PHPJava \Utilities \BinaryTool ;
12+ use PHPJava \Utilities \ClassResolver ;
1113use PHPJava \Utilities \Formatter ;
1214use PHPJava \Utilities \MethodNameResolver ;
1315use PHPJava \Utilities \TypeResolver ;
@@ -23,56 +25,49 @@ public function execute(): void
2325 $ cpInfo = $ this ->getConstantPool ();
2426 $ cp = $ cpInfo [$ this ->readUnsignedShort ()];
2527 $ nameAndTypeIndex = $ cpInfo [$ cp ->getNameAndTypeIndex ()];
28+ $ className = $ cpInfo [$ cpInfo [$ cp ->getClassIndex ()]->getClassIndex ()]->getString ();
29+ $ methodName = $ cpInfo [$ nameAndTypeIndex ->getNameIndex ()]->getString ();
2630 $ signature = $ cpInfo [$ nameAndTypeIndex ->getDescriptorIndex ()]->getString ();
2731 $ parsedSignature = Formatter::parseSignature ($ signature );
28- $ invokerClass = $ this ->popFromOperandStack ();
29-
30-
31- $ arguments = [];
32- if (($ length = $ parsedSignature ['arguments_count ' ] - 1 ) >= 0 ) {
33- $ arguments = array_fill (0 , $ length , null );
34- for ($ i = $ length ; $ i >= 0 ; $ i --) {
35- $ arguments [$ i ] = $ this ->popFromOperandStack ();
36- }
37- }
38-
39- $ methodName = $ cpInfo [$ nameAndTypeIndex ->getNameIndex ()]->getString ();
4032
41- if ($ this ->javaClassInvoker ->isInvoked ($ methodName , $ signature )) {
42- return ;
33+ // POP with right-to-left (objectref + arguments)
34+ $ arguments = array_fill (0 , $ parsedSignature ['arguments_count ' ], null );
35+ for ($ i = count ($ arguments ) - 1 ; $ i >= 0 ; $ i --) {
36+ $ arguments [$ i ] = $ this ->popFromOperandStack ();
4337 }
4438
45- $ this ->javaClassInvoker
46- ->addToSpecialInvokedList ($ methodName , $ signature );
47-
48-
39+ /**
40+ * @var InstanceDeferredLoader $objectref
41+ */
42+ $ objectref = $ this ->popFromOperandStack ();
43+ $ newObject = null ;
4944 try {
50- if ($ invokerClass instanceof JavaClass) {
51- if ($ invokerClass ->getInvoker ()->isInvoked ($ methodName , $ signature )) {
52- return ;
45+ $ methodName = $ cpInfo [$ nameAndTypeIndex ->getNameIndex ()]->getString ();
46+
47+ if ($ objectref ->getClassName () !== $ className ) {
48+ // If $objectref is not match $className, then change current class (I have no confidence).
49+ // See also: https://docs.oracle.com/javase/specs/jvms/se11/html/jvms-6.html#jvms-6.5.invokespecial
50+
51+ // FIXME: if $objectref has superclass, then refer superclass from $objectref
52+ // NOTE: This implementation is a ** first aid **.
53+ [$ resourceType , $ classObject ] = $ objectref
54+ ->getOptions ('class_resolver ' )
55+ ->resolve ($ className );
56+
57+ switch ($ resourceType ) {
58+ case ClassResolver::RESOLVED_TYPE_PACKAGES :
59+ $ newObject = new $ classObject (...$ arguments );
60+ break ;
61+ case ClassResolver::RESOLVED_TYPE_CLASS :
62+ $ newObject = $ classObject (...$ arguments );
63+ break ;
5364 }
54-
55- $ invokerClass
56- ->getInvoker ()
57- ->addToSpecialInvokedList ($ methodName , $ signature );
58-
59- $ result = $ invokerClass
60- ->getInvoker ()
61- ->getDynamic ()
62- ->getMethods ()
63- ->call (
64- $ methodName ,
65- ...$ arguments
66- );
6765 } else {
68- $ result = call_user_func_array (
69- [
70- $ invokerClass ,
71- MethodNameResolver::resolve ($ methodName ),
72- ],
73- $ arguments
74- );
66+ $ newObject = $ objectref ->instantiate (...$ arguments );
7567 }
68+
69+ // NOTE: PHP has a problem which a reference object cannot replace to an object.
70+ $ this ->replaceReferredObject ($ objectref , $ newObject );
7671 } catch (\Exception $ e ) {
7772 /**
7873 * @var $codeAttribute CodeAttribute
@@ -104,9 +99,5 @@ public function execute(): void
10499 $ e
105100 );
106101 }
107-
108- if ($ parsedSignature [0 ]['type ' ] !== 'void ' ) {
109- $ this ->pushToOperandStack ($ result );
110- }
111102 }
112103}
0 commit comments