⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 verify.c

📁 linux下建立JAVA虚拟机的源码KAFFE
💻 C
📖 第 1 页 / 共 2 页
字号:
	*buf = '\0';		return afterSig;}/* * countSizeOfArgsInSignature() *    Longs & Double count for 2, all else counts for one. */staticuint32countSizeOfArgsInSignature(const char* sig){	uint32 count = 0;		for (sig++; *sig != ')'; sig = parseFieldTypeDescriptor(sig)) {		if (*sig == 'J' || *sig == 'D')			count += 2;		else			count++;	}		return count;}/* * Helper function for error reporting in checkMethodCall. * Provided basically to give better debugging output. */static inlineboolverifyErrorInCheckMethodCall(Verifier* v,			     char* argbuf,			     uint32 pc,			     const uint32 idx,			     const constants* pool,			     const char* methSig,			     const char* msg){	gc_free(argbuf);	DBG(VERIFY3,	    dprintf("                error with method invocation, pc = %d, method = %s%s\n",		    pc,		    METHODREF_NAMED(idx, pool),		    methSig);	    );	return verifyError(v, msg);}/* * Helper function for error reporting in checkMethodCall. */static inlinebooltypeErrorInCheckMethodCall(Verifier* v,			   char* argbuf,			   uint32 pc,			   const uint32 idx,			   const constants* pool,			   const char* methSig){	return verifyErrorInCheckMethodCall(v, argbuf, pc, idx, pool, methSig,					    "parameters fail type checking in method invocation");}/*  * checkMethodCall() *    verify an invoke instruction.  this includes making sure that the types *    on the operand stack are type compatible with those expected by the method *    being called. * *    note: we don't check to make sure that the class being referenced by the *          method call actually has the method, or that we have permission to *          access it, as those checks are deferred until pass 4. * * returns whether the method's arguments type check correctly. * it also pushes the return type onto binfo's operand stack. */boolcheckMethodCall(Verifier* v,		BlockInfo* binfo, uint32 pc){	const unsigned char* code        = METHOD_BYTECODE_CODE(v->method);	const uint32 opcode              = code[pc];		const constants* pool            = CLASS_CONSTANTS(v->class);	const uint32 idx                 = getWord(code, pc + 1);		const uint32 classIdx            = METHODREF_CLASS(idx, pool);	Type  mrc;	Type* methodRefClass             = &mrc;	Type* t                          = &mrc; /* for shorthand :> */	Type* receiver                   = NULL;		const char* methSig              = METHODREF_SIGD(idx, pool);	const char* sig                  = methSig;	uint32 nargs                     = countSizeOfArgsInSignature(sig);		uint32 paramIndex                = 0;	char* argbuf                     = checkPtr(gc_malloc(strlen(sig) * sizeof(char), KGC_ALLOC_VERIFIER));			DBG(VERIFY3, dprintf("%scalling method %s%s\n", indent, METHODREF_NAMED(idx, pool), sig); );			if (nargs > binfo->stacksz) {		return verifyErrorInCheckMethodCall(v, argbuf, pc, idx, pool, methSig, "not enough stuff on opstack for method invocation");	}			/* make sure that the receiver is type compatible with the class being invoked */	if (opcode != INVOKESTATIC) {		if (nargs == binfo->stacksz) {			return verifyErrorInCheckMethodCall(v, argbuf, pc, idx, pool, methSig, "not enough stuff on opstack for method invocation");		}						receiver = &binfo->opstack[binfo->stacksz - (nargs + 1)];		if (!(receiver->tinfo & TINFO_UNINIT) && !isReference(receiver)) {			return verifyErrorInCheckMethodCall(v, argbuf, pc, idx, pool, methSig, "invoking a method on something that is not a reference");		}				if (pool->tags[classIdx] == CONSTANT_Class) {			methodRefClass->tinfo = TINFO_NAME;			methodRefClass->data.name = UNRESOLVED_CLASS_NAMED(classIdx, pool);		} else {			methodRefClass->tinfo = TINFO_CLASS;			methodRefClass->data.class = CLASS_CLASS(classIdx, pool);		}						if (!strcmp(METHODREF_NAMED(idx,pool), constructor_name->data)) {			if (receiver->tinfo & TINFO_UNINIT) {				UninitializedType* uninit = receiver->data.uninit;								if (receiver->tinfo == TINFO_UNINIT_SUPER) {					Type t_uninit_super;					t_uninit_super.tinfo = TINFO_CLASS;					t_uninit_super.data.class = uninit->type.data.class->superclass;										if (!sameType(methodRefClass, &uninit->type) &&					    uninit->type.data.class != getTOBJ()->data.class &&					    !sameType(methodRefClass, &t_uninit_super)) {						return verifyErrorInCheckMethodCall(v, argbuf, pc, idx, pool, methSig, "incompatible receiving type for superclass constructor call");					}				} else if (!sameType(methodRefClass, &uninit->type)) {					DBG(VERIFY3,					    dprintf("%smethodRefClass: ", indent); printType(methodRefClass);					    dprintf("\n%sreceiver: ", indent); printType(&uninit->type); dprintf("\n"); );					return verifyErrorInCheckMethodCall(v, argbuf, pc, idx, pool, methSig, "incompatible receiving type for constructor call");				}								/* fix front of list, if necessary */				if (uninit == v->uninits) {					v->uninits = v->uninits->next;					if (v->uninits) {						(v->uninits)->prev = NULL;					}					uninit->next = NULL;				}								popUninit(v->method, uninit, binfo);			}			else if (!sameType(methodRefClass, receiver)) {				return verifyErrorInCheckMethodCall(v, argbuf, pc, idx, pool, methSig, "incompatible receiving type for constructor call");			}		}		else if (!typecheck(v, methodRefClass, receiver)) {			if (receiver->tinfo & TINFO_UNINIT) {				return verifyErrorInCheckMethodCall(v, argbuf, pc, idx, pool, methSig, "invoking a method on an uninitialized object reference");			}						DBG(VERIFY3,			    dprintf("%srequired receiver type: ", indent);			    printType(methodRefClass);			    dprintf("\n%sactual   receiver type: ", indent);			    printType(receiver);			    dprintf("\n");			    );			return verifyErrorInCheckMethodCall(v, argbuf, pc, idx, pool, methSig, "expected method receiver does not typecheck with object on operand stack");		}	}			/* here we use paramIndex to represent which parameter we're currently considering.	 * remember, when we call a method, the first parameter is deepest in the stack,	 * so when we traverse the parameter list in the method signature we have to look	 * from the bottom up.	 */	paramIndex = binfo->stacksz - nargs;	for (sig = getNextArg(sig + 1, argbuf); *argbuf != ')'; sig = getNextArg(sig, argbuf)) {				if (paramIndex >= binfo->stacksz) {			gc_free(argbuf);			return verifyErrorInCheckMethodCall(v, argbuf, pc, idx, pool, methSig, "error: not enough parameters on stack for method invocation");		}						switch (*argbuf) {		case '[':		case 'L':			t->tinfo = TINFO_SIG;			t->data.sig = argbuf;						if (!typecheck(v, t, &binfo->opstack[paramIndex])) {				return typeErrorInCheckMethodCall(v, argbuf, pc, idx, pool, methSig);			}						binfo->opstack[paramIndex] = *getTUNSTABLE();			paramIndex++;			break;					case 'Z': case 'S': case 'B': case 'C':		case 'I':			if (binfo->opstack[paramIndex].data.class != getTINT()->data.class) {				return typeErrorInCheckMethodCall(v, argbuf, pc, idx, pool, methSig);			}						binfo->opstack[paramIndex] = *getTUNSTABLE();			paramIndex++;			break;					case 'F':			if (binfo->opstack[paramIndex].data.class != getTFLOAT()->data.class) {				return typeErrorInCheckMethodCall(v, argbuf, pc, idx, pool, methSig);			}						binfo->opstack[paramIndex] = *getTUNSTABLE();			paramIndex++;			break;					case 'J':			if (binfo->opstack[paramIndex].data.class != getTLONG()->data.class ||			    !isWide(&binfo->opstack[paramIndex + 1])) {				return typeErrorInCheckMethodCall(v, argbuf, pc, idx, pool, methSig);			}						binfo->opstack[paramIndex]    = *getTUNSTABLE();			binfo->opstack[paramIndex+ 1] = *getTUNSTABLE();			paramIndex += 2;			break;					case 'D':			if (binfo->opstack[paramIndex].data.class != getTDOUBLE()->data.class ||			    !isWide(&binfo->opstack[paramIndex + 1])) {				return typeErrorInCheckMethodCall(v, argbuf, pc, idx, pool, methSig);			}						binfo->opstack[paramIndex]     = *getTUNSTABLE();			binfo->opstack[paramIndex + 1] = *getTUNSTABLE();			paramIndex += 2;			break;					default:			return typeErrorInCheckMethodCall(v, argbuf, pc, idx, pool, methSig);		}	}	binfo->stacksz -= nargs;			if (opcode != INVOKESTATIC) {	        /* pop object reference off the stack */		binfo->stacksz--;		binfo->opstack[binfo->stacksz] = *getTUNSTABLE();	}			/**************************************************************	 * Process Return Type	 **************************************************************/	sig++;	sig = getNextArg(sig, argbuf);		if (*argbuf == 'J' || *argbuf == 'D') {		if (v->method->stacksz < binfo->stacksz + 2) {			return verifyErrorInCheckMethodCall(v, argbuf, pc, idx, pool, methSig, "not enough room on operand stack for method call's return value");		}	}	else if (*argbuf != 'V') {		if (v->method->stacksz < binfo->stacksz + 1) {			return verifyErrorInCheckMethodCall(v, argbuf, pc, idx, pool, methSig, "not enough room on operand stack for method call's return value");		}	}		switch (*argbuf) {	case 'Z': case 'S': case 'B': case 'C':	case 'I':		binfo->opstack[binfo->stacksz++] = *getTINT();		break;			case 'F':		binfo->opstack[binfo->stacksz++] = *getTFLOAT();		break;			case 'J':		binfo->opstack[binfo->stacksz]     = *getTLONG();		binfo->opstack[binfo->stacksz + 1] = *getTWIDE();		binfo->stacksz += 2;		break;			case 'D':		binfo->opstack[binfo->stacksz]     = *getTDOUBLE();		binfo->opstack[binfo->stacksz + 1] = *getTWIDE();		binfo->stacksz += 2;		break;			case 'V':		break;			case '[':	case 'L':		v->sigs = pushSig(v->sigs, argbuf);				binfo->opstack[binfo->stacksz].data.class = (Hjava_lang_Class*)argbuf;		binfo->opstack[binfo->stacksz].tinfo = TINFO_SIG;		binfo->stacksz++;				/* no freeing of the argbuf here... */		return(true);			default:	        /* shouldn't get here because of parsing during pass 2... */		DBG(VERIFY3, dprintf("                unrecognized return type signature: %s\n", argbuf); );		gc_free(argbuf);		postExceptionMessage(v->einfo, JAVA_LANG(InternalError),				     "unrecognized return type signature");		return(false);	}		gc_free(argbuf);	return(true);}static inlineboolverifyErrorInLoadInitialArgs(Verifier* v, const char* msg, char* argbuf) {	gc_free(argbuf);	return verifyError(v, msg);}static inlineboollocalOverflowErrorInLoadInitialArgs(Verifier* v, char* argbuf) {	return verifyErrorInLoadInitialArgs(v, "method arguments cannot fit into local variables", argbuf);}/* * pushes the initial method arguments into local variable array */staticboolloadInitialArgs(Verifier* v){	uint32 paramCount = 0;		/* the +1 skips the initial '(' */	const char* sig = METHOD_SIGD(v->method) + 1;	char* argbuf    = checkPtr(gc_malloc((strlen(sig)+1) * sizeof(char), KGC_ALLOC_VERIFIER));	char* newsig    = NULL;		/* load the initial argument into the first basic block.	 */	BlockInfo* block = v->blocks[0];	Type* locals = block->locals;			DBG(VERIFY3, dprintf("        sig: %s\n", sig); );		/* must have at least 1 local variable for the object reference	*/	if (!METHOD_IS_STATIC(v->method)) {		if (v->method->localsz <= 0) {			return verifyErrorInLoadInitialArgs(v, "number of locals in non-static method must be > 0", argbuf);		}				/* the first local variable in every method is the class to which it belongs */		locals[0].tinfo = TINFO_CLASS;		locals[0].data.class = v->method->class;		paramCount++;		if (!strcmp(METHOD_NAMED(v->method), constructor_name->data)) {		        /* the local reference in a constructor is uninitialized */			v->uninits = pushUninit(v->uninits, &locals[0]);			locals[0].tinfo = TINFO_UNINIT_SUPER;			locals[0].data.uninit = v->uninits;		}	}		for (sig = getNextArg(sig, argbuf); *argbuf != ')'; sig = getNextArg(sig, argbuf)) {		if (paramCount > v->method->localsz) {			return localOverflowErrorInLoadInitialArgs(v, argbuf);		}				switch (*argbuf) {		case 'Z': case 'S': case 'B': case 'C':		case 'I': locals[paramCount++] = *getTINT(); break;		case 'F': locals[paramCount++] = *getTFLOAT(); break;					case 'J':			if (paramCount + 1 > v->method->localsz) {				return localOverflowErrorInLoadInitialArgs(v, argbuf);			}			locals[paramCount] = *getTLONG();			locals[paramCount+1] = *getTWIDE();			paramCount += 2;			break;					case 'D':			if (paramCount + 1 > v->method->localsz) {				return localOverflowErrorInLoadInitialArgs(v, argbuf);			}			locals[paramCount] = *getTDOUBLE();			locals[paramCount+1] = *getTWIDE();			paramCount += 2;			break;					case '[':		case 'L':			newsig = checkPtr(gc_malloc((strlen(argbuf) + 1) * sizeof(char), KGC_ALLOC_VERIFIER));			v->sigs = pushSig(v->sigs, newsig);			sprintf(newsig, "%s", argbuf);			locals[paramCount].tinfo = TINFO_SIG;			locals[paramCount].data.sig = newsig;			paramCount++;			break;					default:			DBG(VERIFY3,			    dprintf("ERROR, loadInitialArgs(): argument to method has bad signature.\n");			    dprintf("        it starts with an unrecognized character: %c\n", *argbuf);			    dprintf("        the rest of argbuf: %s\n", argbuf);			    );						return verifyErrorInLoadInitialArgs(v, "unrecognized first character in parameter type descriptor", argbuf);		}	}			/* success! */	gc_free(argbuf);	return(true);#undef LOCAL_OVERFLOW_ERROR#undef VERIFY_ERROR}/* * returns a pointer to the first character of the method's return value * in the method's type descriptor. */const char*getMethodReturnSig(const Method* method){	const char* sig = METHOD_SIGD(method);		/* skip the type parameters */	for (sig++; *sig != ')'; sig = parseFieldTypeDescriptor(sig));	sig++;		return sig;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -