/***********************************************************************
 * Bdbj 1.1 (by Jon Cook August 2001)
 *
 * invoke.def 
 * 
 * Deals with stepping back into the end of a method.
 *
 * Last modified: April 2002.
 * 
 ***********************************************************************/

/* START JJC */

#define REVTYPE ( (over_mode == R_OVERFIRST || over_mode == R_OVER ) ? T_BACK_OVER : T_BACK_INTO )

define_insn(INVOKEVIRTUAL)
{
	/*
	 * ..., obj, ..args.., -> ...
	 */
	slots obj;
	obj = rcbuffs( debug );

	idx = (uint16)((getpc(0) << 8) | getpc(1));

	get_method_info(idx);

	assert( method_method() );

	/* If method doesn't exists, call 'NoSuchMethodError' */
	if (method_method() == 0) {
	  assert( 0 );
	  /*
		softcall_nosuchmethod(method_class(), method_name(), method_sig());
		low = method_returntype();
		METHOD_RETURN_VALUE();
	  */
	}
	else {
		int is_virtual = method_method()->idx >= 0;
		idx = method_nargs();

		if( is_virtual ) {
			/* Find dispatch table in object */
			load_offset_ref(mtable, &obj, method_dtable_offset);

			/* Check method table for cached entry */
			load_offset_ref(tmp, mtable,
				DTABLE_METHODOFFSET + method_idx() * DTABLE_METHODSIZE);
		} 

		/* Push arguments & object */
		idx++;

		/*pop(idx);*/

		/* Call it */
		low = method_returntype();
		if (is_virtual) {
                        softcall_initialise_class(method_class()); 
                        beg = virtualMachine((methods*)(tmp)[0].v.taddr, &obj, retval, tid, REVTYPE, thr ); /* JJC */
		} else {
                        softcall_initialise_class(method_class()); 
                        beg = virtualMachine(method_method(), &obj, retval, tid, REVTYPE, thr ); /* JJC */
		}

		if( beg == F_END )  
			wcbuffs( obj, 1, debug, thr );
	}
}

define_insn(INVOKESPECIAL)
{
	/*
	 * ..., obj, ..args.., -> ...
	 */
	slots obj;
	obj = rcbuffs( debug );

	idx = (uint16)((getpc(0) << 8) | getpc(1));

	get_special_method_info(idx);

	/* If method doesn't exists, call 'NoSuchMethodError' */
	if (method_method() == 0) {
	  assert( 0 );
	  /*
		softcall_nosuchmethod(method_class(), method_name(), method_sig());
		low = method_returntype();
		METHOD_RETURN_VALUE();
	  */
	}
	else {
		idx = method_nargs();

		/* Push arguments & object */
		idx++;

		/*pop(idx); */

		/* Call it */
		low = method_returntype();

 		softcall_initialise_class(method_class()); /* JJC */
		beg = virtualMachine(method_method(), &obj, retval, tid, REVTYPE, thr ); /* JJC */
                if( beg == F_END ) 
                        wcbuffs( obj, 1, debug, thr );
	}
}

define_insn(INVOKESTATIC)
{
	/*
	 * ..., ..args.., -> ...
	 */
	idx = (uint16)((getpc(0) << 8) | getpc(1));

	get_method_info(idx);

	/* If method doesn't exists, call 'NoSuchMethodError' */
	if (method_method() == 0) {
	  assert( 0 ); 
	  /*
		softcall_nosuchmethod(method_class(), method_name(), method_sig());
		low = method_returntype();
		METHOD_RETURN_VALUE();
	  */
	}
	else {
		idx = method_nargs();

		/* Push arguments */

		/*pop(idx); */

		/* Call it */
		low = method_returntype();
                
 		softcall_initialise_class(method_class()); /* JJC */
		beg = virtualMachine(method_method(), sp - idx, retval, tid, REVTYPE, thr ); /* JJC */
	}
}

define_insn(INVOKEINTERFACE)
{
	/*
	 * ..., obj, ..args.., -> ...
	 */
        slots obj;
        obj = rcbuffs( debug );

	idx = (uint16)((getpc(0) << 8) | getpc(1));

	get_interface_method_info(idx);

	/* If method doesn't exist, call 'NoSuchMethodError' */
	/* NB: This means that the interface class does not have the method
	 * that is asked for, not that this class does not implement the
	 * interface method.
	 */
	if (method_method() == 0) {
	  assert( 0 );
	  /*
		softcall_nosuchmethod(method_class(), method_name(), method_sig());
		low = method_returntype();
		METHOD_RETURN_VALUE();
	  */
	}
	else {
		idx = (uint8)getpc(2) - 1;

		softcall_lookupinterfacemethod(tmp, method_method(), &obj);

		/* Push arguments & object */
		idx++;

		/*pop(idx);*/

		/* Call it */
		low = method_returntype();

                softcall_initialise_class(method_class()); /* JJC */
                beg = virtualMachine((methods*)(tmp)[0].v.taddr, &obj, retval, tid, REVTYPE, thr ); /* JJC */
                if( beg == F_END ) 
                        wcbuffs( obj, 1, debug, thr );
	}
}

/* END JJC */
