2 unresolved_method *um; /* struct describing the called method */
3 constant_FMIref *mref; /* reference to the called method */
4 methodinfo *mi; /* resolved method (if any) */
5 methoddesc *md; /* descriptor of the called method */
6 utf *mname; /* method name */
7 utf *mclassname; /* name of the method's class */
8 bool specialmethod; /* true if a <...> method is called */
9 int opcode; /* invocation opcode */
10 bool callinginit; /* true if <init> is called */
12 classref_or_classinfo initclass;
14 s4 argindex; /* argument variable index */
15 varinfo *av; /* argument variable */
16 varinfo *dv; /* result variable of the invocation */
18 u1 rtype; /* return type of called method */
19 resolve_result_t result;
26 /* get the FMIref and the unresolved_method struct (if any) */
27 /* from the instruction */
29 if (INSTRUCTION_IS_UNRESOLVED(state->iptr)) {
30 /* unresolved method */
31 um = state->iptr->sx.s23.s3.um;
37 mref = state->iptr->sx.s23.s3.fmiref;
40 /* get method descriptor and name */
42 md = mref->parseddesc.md;
45 /* get method info (if resolved) and classname */
47 if (IS_FMIREF_RESOLVED(mref)) {
49 mclassname = mi->class->name;
53 mclassname = mref->p.classref->name;
56 opcode = state->iptr[0].opc;
57 invokestatic = (opcode == ICMD_INVOKESTATIC);
58 invokespecial = (opcode == ICMD_INVOKESPECIAL);
59 specialmethod = (mname->text[0] == '<');
60 dv = VAROP(state->iptr->dst);
62 /* prevent compiler warnings */
66 /* check whether we are calling <init> */
68 callinginit = (invokespecial && mname == utf_init);
69 if (specialmethod && !callinginit)
70 TYPECHECK_VERIFYERROR_bool("Invalid invocation of special method");
72 /* allocate parameters if necessary */
75 if (!descriptor_params_from_paramtypes(md,
76 (opcode == ICMD_INVOKESTATIC) ? ACC_STATIC : ACC_NONE))
79 /* check parameter types */
81 i = md->paramcount; /* number of parameters including 'this'*/
84 argindex = state->iptr->sx.s23.s2.args[i];
86 td = md->paramtypes + i;
88 if (av->type != td->type)
89 TYPECHECK_VERIFYERROR_bool("Parameter type mismatch in method invocation");
91 if (av->type == TYPE_ADR) {
92 LOGINFO(&(av->typeinfo));
93 if (i==0 && callinginit)
95 /* first argument to <init> method */
96 if (!TYPEINFO_IS_NEWOBJECT(av->typeinfo))
97 TYPECHECK_VERIFYERROR_bool("Calling <init> on initialized object");
99 /* get the address of the NEW instruction */
100 LOGINFO(&(av->typeinfo));
101 ins = (instruction *) TYPEINFO_NEWOBJECT_INSTRUCTION(av->typeinfo);
103 initclass = ins[-1].sx.val.c;
105 initclass.cls = state->m->class;
106 LOGSTR("class: "); LOGNAME(initclass); LOGNL;
110 /* non-adress argument. if this is the first argument and we are */
111 /* invoking an instance method, this is an error. */
112 if (i==0 && opcode != ICMD_INVOKESTATIC) {
113 TYPECHECK_VERIFYERROR_bool("Parameter type mismatch for 'this' argument");
120 LOG("replacing uninitialized object");
121 /* replace uninitialized object type on stack */
123 /* for all live-in and live-through variables */
124 for (i=0; i<state->iptr->s1.argcount; ++i) {
125 argindex = state->iptr->sx.s23.s2.args[i];
127 if (av->type == TYPE_ADR
128 && TYPEINFO_IS_NEWOBJECT(av->typeinfo)
129 && TYPEINFO_NEWOBJECT_INSTRUCTION(av->typeinfo) == ins)
131 LOG("replacing uninitialized type");
133 /* If this stackslot is in the instack of
134 * this basic block we must save the type(s)
135 * we are going to replace.
137 /* XXX this needs a new check */
138 if (state->bptr->invars
139 && argindex >= state->bptr->invars[0]
140 && argindex < state->bptr->varstart
141 && !state->savedinvars)
143 typestate_save_invars(state);
146 if (!typeinfo_init_class(&(av->typeinfo),initclass))
151 /* replace uninitialized object type in locals */
152 if (!typevector_init_object(state->jd->var, ins, initclass,
156 /* initializing the 'this' reference? */
159 TYPECHECK_ASSERT(state->initmethod);
160 /* { we are initializing the 'this' reference } */
161 /* must be <init> of current class or direct superclass */
162 /* the current class is linked, so must be its superclass. thus we can be */
163 /* sure that resolving will be trivial. */
168 if (!resolve_classref(state->m,mref->p.classref,resolveLazy,false,true,&cls))
169 return false; /* exception */
172 /* if lazy resolving did not succeed, it's not one of the allowed classes */
173 /* otherwise we check it directly */
174 if (cls == NULL || (cls != state->m->class && cls != state->m->class->super.cls)) {
175 TYPECHECK_VERIFYERROR_bool("<init> calling <init> of the wrong class");
178 /* set our marker variable to type int */
179 LOG("setting <init> marker");
180 typevector_store(jd->var, state->numlocals-1, TYPE_INT, NULL);
183 /* { we are initializing an instance created with NEW } */
184 if ((IS_CLASSREF(initclass) ? initclass.ref->name : initclass.cls->name) != mclassname) {
185 TYPECHECK_VERIFYERROR_bool("wrong <init> called for uninitialized reference");
190 /* try to resolve the method lazily */
192 result = resolve_method_lazy(state->m, mref, invokespecial);
194 /* perform verification checks */
196 if (result == resolveSucceeded) {
198 assert(IS_FMIREF_RESOLVED(mref));
202 result = resolve_method_verifier_checks(state->m,
208 /* check types of parameters */
210 if (result == resolveSucceeded && !invokestatic)
211 result = resolve_method_instance_type_checks(
213 &(VAR(state->iptr->sx.s23.s2.args[0])->typeinfo),
216 if (result == resolveSucceeded)
217 result = resolve_method_param_type_checks(
218 jd, state->m, state->iptr,
221 /* impose loading constraints */
223 if (result == resolveSucceeded) {
224 /* XXX state->m->class may have to be wrong when inlining */
225 if (!resolve_method_loading_constraints(state->m->class, mi))
229 if (result == resolveFailed)
232 if (result == resolveSucceeded) {
233 /* if this call is monomorphic, turn it into an INVOKESPECIAL */
235 if ((state->iptr->opc == ICMD_INVOKEVIRTUAL)
236 && (mi->flags & (ACC_FINAL | ACC_PRIVATE)))
238 state->iptr->opc = ICMD_INVOKESPECIAL;
242 /* resolution must be deferred */
245 um = resolve_create_unresolved_method(state->m->class, state->m,
247 state->iptr->opc == ICMD_INVOKESTATIC,
254 /* record subtype constraints for parameters */
256 if (!invokestatic && !resolve_constrain_unresolved_method_instance(
258 &(VAR(state->iptr->sx.s23.s2.args[0])->typeinfo),
260 return false; /* XXX maybe wrap exception */
262 if (!resolve_constrain_unresolved_method_params(
263 jd, um, state->m, state->iptr))
264 return false; /* XXX maybe wrap exception */
266 /* store the unresolved_method pointer */
268 state->iptr->sx.s23.s3.um = um;
269 state->iptr->flags.bits |= INS_FLAG_UNRESOLVED;
272 /* set the return type */
274 rtype = md->returntype.type;
275 if (rtype != TYPE_VOID) {
277 if (!typeinfo_init_from_typedesc(&(md->returntype),NULL,&(dv->typeinfo)))
283 * These are local overrides for various environment variables in Emacs.
284 * Please do not remove this and leave it at the end of the file, where
285 * Emacs will automagically detect them.
286 * ---------------------------------------------------------------------
289 * indent-tabs-mode: t
293 * vim:noexpandtab:sw=4:ts=4:filetype=c: