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

📄 code-analyse.c

📁 kaffe Java 解释器语言,源码,Java的子集系统,开放源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* code-analyse.c * Analyse a method's bytecodes. * * Copyright (c) 1996, 1997 *	Transvirtual Technologies, Inc.  All rights reserved. * * See the file "license.terms" for information on usage and redistribution  * of this file.  */#define	IDBG(s)#define	VDBG(s)#include "config.h"#include "debug.h"#include "config-std.h"#include "gtypes.h"#include "bytecode.h"#include "object.h"#include "constants.h"#include "access.h"#include "classMethod.h"#include "code-analyse.h"#include "lookup.h"#include "exception.h"#include "icode.h"#include "itypes.h"#include "locks.h"#include "thread.h"#include "jthread.h"#include "baseClasses.h"#include "soft.h"#include "md.h"#include "gc.h"const uint8 insnLen[256] = {	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 	2, 3, 2, 3, 3, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 	1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 	1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 	1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 3, 	3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 0, 0, 1, 1, 1, 1, 	1, 1, 3, 3, 3, 3, 3, 3, 3, 5, 1, 3, 2, 3, 1, 1, 	3, 3, 1, 1, 1, 4, 3, 3, 5, 5, 1, 1, 1, 1, 1, 1, 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, };static void mergeFrame(codeinfo*, int, int, frameElement*, Method*);static bool analyzeBasicBlock(codeinfo*, Method*, int32, errorInfo*);static void updateLocals(codeinfo*, int32, frameElement*);static bool analyzeCatchClause(jexceptionEntry*, Hjava_lang_Class*, errorInfo*);boolanalyzeMethod(Method* meth, codeinfo **pcodeinfo, errorInfo *einfo){	int32 pc;	int32 tabpc;	int32 idx;	int32 sp;	int32 lcl;	int count;	perPCInfo* bhead;	perPCInfo* btail;	perPCInfo* bcurr;	bool rerun;	bool failed;	bool wide;	codeinfo *codeInfo;	localUse* localuse;DBG(CODEANALYSE,	dprintf("%s %p: %s.%s\n", __FUNCTION__, THREAD_NATIVE(), 		meth->class->name->data, meth->name->data);    )	if( meth->c.bcode.code == 0 )	{		postExceptionMessage(einfo, JAVA_LANG(VerifyError),				     "No code attribute for %s.%s.",				     meth->class->name->data,				     meth->name->data);		return false;	}	codeInfo = gc_malloc(sizeof(codeinfo) + meth->c.bcode.codelen*sizeof(perPCInfo),			     GC_ALLOC_CODEANALYSE);	*pcodeinfo = codeInfo;	if (!codeInfo) {		postOutOfMemory(einfo);		return false;	}	/* Allocate space for local register info - we add in an extra one	 * to avoid mallocing 0 bytes.	 */	localuse = gc_malloc(sizeof(localUse) * (meth->localsz+1), GC_ALLOC_CODEANALYSE);	if (!localuse) {		KFREE(codeInfo);		postOutOfMemory(einfo);		return false;	}	codeInfo->localuse = localuse;	/* We don't need to do this twice */	meth->accflags |= ACC_VERIFIED;	for (lcl = 0; lcl < meth->localsz; lcl++) {		localuse = codeInfo->localuse;		localuse[lcl].use = 0;		localuse[lcl].first = 0x7FFFFFFF;		localuse[lcl].last = -1;		localuse[lcl].write = -1;		localuse[lcl].type = 0;	}DBG(CODEANALYSE,	dprintf("%s %p: codeInfo = %p\n", __FUNCTION__, THREAD_NATIVE(), codeInfo);	    )	/* Allocate code info. block */	codeInfo->localsz = meth->localsz;	codeInfo->stacksz = meth->stacksz;	codeInfo->codelen = meth->c.bcode.codelen;	/* First basic block becomes head of block chain */	SET_NEEDVERIFY(0);	bhead = &codeInfo->perPC[0];	btail = bhead;	/* Scan the code and mark the beginning of basic blocks */	wide = false;	for (pc = 0; pc < codeInfo->codelen;) {		SET_STARTOFINSTRUCTION(pc);		/* set native pc to -1 so that we can recognize whether		 * a corresponding native PC will be generated.		 */		SET_INSNPC(pc, -1);		switch (INSN(pc)) {		case IFEQ:	case IFNE:	case IFLT:		case IFGE:	case IFGT:	case IFLE:		case IF_ICMPEQ: case IF_ICMPNE:		case IF_ICMPLT: case IF_ICMPGE:		case IF_ICMPGT: case IF_ICMPLE:		case IF_ACMPEQ: case IF_ACMPNE:		case IFNULL:	case IFNONNULL:			tabpc = pc + WORD(pc+1);			SET_STARTOFBASICBLOCK(tabpc);			SET_JUMPFLOW(pc, tabpc);			pc = pc + INSNLEN(pc);			SET_STARTOFBASICBLOCK(pc);			SET_NORMALFLOW(pc);			break;		case GOTO:			tabpc = pc + WORD(pc+1);			SET_STARTOFBASICBLOCK(tabpc);			SET_JUMPFLOW(pc, tabpc);			pc = pc + INSNLEN(pc);			if (pc < codeInfo->codelen) {				SET_STARTOFBASICBLOCK(pc);			}			break;		case GOTO_W:			tabpc = pc + DWORD(pc+1);			SET_STARTOFBASICBLOCK(tabpc);			SET_JUMPFLOW(pc, tabpc);			pc = pc + INSNLEN(pc);			if (pc < codeInfo->codelen) {				SET_STARTOFBASICBLOCK(pc);			}			break;		case JSR:			tabpc = pc + WORD(pc+1);			SET_STARTOFBASICBLOCK(tabpc);			SET_JUMPFLOW(pc, tabpc);			pc = pc + INSNLEN(pc);			SET_STARTOFBASICBLOCK(pc);			SET_NORMALFLOW(pc);			break;		case JSR_W:			tabpc = pc + DWORD(pc+1);			SET_STARTOFBASICBLOCK(tabpc);			SET_JUMPFLOW(pc, tabpc);			pc = pc + INSNLEN(pc);			SET_STARTOFBASICBLOCK(pc);			SET_NORMALFLOW(pc);			break;		case TABLESWITCH:			tabpc = (pc + 4) & -4;			idx = DWORD(tabpc+8)-DWORD(tabpc+4)+1;			for (; idx > 0; idx--) {				SET_STARTOFBASICBLOCK(pc+DWORD(tabpc+idx*4+8));				SET_JUMPFLOW(pc, pc+DWORD(tabpc+idx*4+8));			}			SET_STARTOFBASICBLOCK(pc+DWORD(tabpc));			SET_JUMPFLOW(pc, pc+DWORD(tabpc));			pc = tabpc + (DWORD(tabpc+8)-DWORD(tabpc+4)+1+3) * 4;			if (pc < codeInfo->codelen) {				SET_STARTOFBASICBLOCK(pc);			}			break;		case LOOKUPSWITCH:			tabpc = (pc + 4) & -4;			idx = DWORD(tabpc+4);			for (; idx > 0; idx--) {				SET_STARTOFBASICBLOCK(pc+DWORD(tabpc+idx*8+4));				SET_JUMPFLOW(pc, pc+DWORD(tabpc+idx*8+4));			}			SET_STARTOFBASICBLOCK(pc+DWORD(tabpc));			SET_JUMPFLOW(pc, pc+DWORD(tabpc));			pc = tabpc + (DWORD(tabpc+4)+1) * 8;			if (pc < codeInfo->codelen) {				SET_STARTOFBASICBLOCK(pc);			}			break;		case IRETURN:	case LRETURN:	case ARETURN:		case FRETURN:	case DRETURN:	case RETURN:		case ATHROW:	case RET:			pc = pc + INSNLEN(pc);			if (pc < codeInfo->codelen) {				SET_STARTOFBASICBLOCK(pc);			}			break;		case WIDE:			wide = true;			pc = pc + INSNLEN(pc);			SET_NORMALFLOW(pc);			break;		case ILOAD:	case LLOAD:	case FLOAD:		case DLOAD:	case ALOAD:		case ISTORE:	case LSTORE:	case FSTORE:		case DSTORE:	case ASTORE:			pc = pc + INSNLEN(pc);			if (wide == true) {				wide = false;				pc += 1;			}			SET_NORMALFLOW(pc);			break;		case IINC:			pc = pc + INSNLEN(pc);			if (wide == true) {				wide = false;				pc += 2;			}			SET_NORMALFLOW(pc);			break;		default:			/* The default */			pc = pc + INSNLEN(pc);			SET_NORMALFLOW(pc);			break;		}	}	/* Setup exception info. */	sp = meth->localsz + meth->stacksz - 1;	if (meth->exception_table != 0) {		for (lcl = 0; lcl < meth->exception_table->length; lcl++) {			bool succ;			jexceptionEntry *entry;						entry = &(meth->exception_table->entry[lcl]);						/* Verify catch clause exception has valid type. */			succ = analyzeCatchClause(entry, meth->class, einfo);			if (succ == false) {				return false;			}			pc = entry->handler_pc;			ATTACH_NEW_BASICBLOCK(pc);			SET_STARTOFEXCEPTION(pc);			SET_STACKPOINTER(pc, sp);			SET_NEWFRAME(pc);			STACKINIT(0, TOBJ);		}	}	/* Mark the various starting states.  These include the main	 * entry point plus all the exception entry points, their arguments	 * and stack values.	 */	pc = 0;	SET_STACKPOINTER(pc, meth->localsz + meth->stacksz);	SET_NEWFRAME(pc);	/* Parse the method signature to setup the inital locals	 */	idx = 0;	if ((meth->accflags & ACC_STATIC) == 0) {		LOCALINIT(0, TOBJ);		idx++;	}	for (count = 0; count < METHOD_NARGS(meth); ++count) {		switch (*METHOD_ARG_TYPE(meth, count)) {		case 'L':		case '[':			LOCALINIT(idx, TOBJ);			idx += 1;			break;		case 'I':		case 'Z':		case 'S':		case 'B':		case 'C':			LOCALINIT(idx, TINT);			idx += 1;			break;		case 'J':			LOCALINIT(idx, TLONG);			LOCALINIT(idx+1, TVOID);			idx += 2;			break;		case 'F':			LOCALINIT(idx, TFLOAT);			idx += 1;			break;		case 'D':			LOCALINIT(idx, TDOUBLE);			LOCALINIT(idx+1, TVOID);			idx += 2;			break;		default:			assert("Signature character unknown" == 0);		}	}	/* Scan out list of basic blocks.  Unfortunately they're not in	 * precise order so we have to do this until they're all done.	 */	do {		rerun = false;		for (bcurr = bhead; bcurr != NULL; bcurr = bcurr->nextBB) {			pc = bcurr - codeInfo->perPC;			if (IS_NEEDVERIFY(pc)) {				failed = analyzeBasicBlock(codeInfo, meth, 							    pc, einfo);				if (failed) {					tidyAnalyzeMethod(pcodeinfo);					return (false);				}				rerun = true;			}		}	} while (rerun == true);	/* Check we've processed each block at least once */	/* Note that it is perfectly legal for code to contain unreachable	 * basic blocks;  There's no need to complain.	 */#if VDBG(1) - 1 == 0	for (bcurr = bhead; bcurr != NULL; bcurr = bcurr->nextBB) {		if ((bcurr->flags & FLAG_DONEVERIFY) == 0) {			VDBG(dprintf("%s.%s%s pc %d bcurr->flags 0x%04x\n", meth->class->name->data, meth->name->data, METHOD_SIGD(meth), bcurr - codeInfo->perPC, bcurr->flags);)		}	}#endif	return (true);}staticboolanalyzeBasicBlock(codeinfo* codeInfo, Method* meth, int32 pc, errorInfo *einfo){	int32 tabpc;	int32 idx;	int32 sp;	int32 opc;	callInfo call;	fieldInfo finfo;	Hjava_lang_Class* type;	const char* sig;	frameElement* activeFrame;	bool wide;	bool failed;	bool firsttime;	opc = pc;	assert(pc == 0 || IS_STARTOFBASICBLOCK(pc) || IS_STARTOFEXCEPTION(pc));	assert(IS_STACKPOINTERSET(pc));	/* If this block hasn't been verified before then note this */	if (!IS_DONEVERIFY(pc)) {		firsttime = true;	}	else {		firsttime = false;	}	/* Get stack pointer */	sp = STACKPOINTER(pc);	/* Allocate frame to hold type data */	activeFrame = ALLOCFRAME();	if (activeFrame == 0) {		postOutOfMemory(einfo);		return true;	}	SET_DONEVERIFY(pc);	FRAMELOAD(pc);	/* Process basic block until we get to the beginning of a new one */	wide = false;	failed = false;	do {		if (sp < meth->localsz || sp > meth->localsz + meth->stacksz) {			failed = true;			postExceptionMessage(einfo, JAVA_LANG(VerifyError),				"In class %s in method %s with signature %s at pc %d: sp %d not in range [%d, %d]",				meth->class->name->data, meth->name->data, METHOD_SIGD(meth),				pc, sp, meth->localsz, 				meth->localsz + meth->stacksz);			break;		}		/* If we're in an exception block, merge locals into		 * the handler.		 */		if (meth->exception_table != 0) {			for (idx = 0; idx < meth->exception_table->length; idx++) {				if (pc >= meth->exception_table->entry[idx].start_pc && pc < meth->exception_table->entry[idx].end_pc) {					FRAMEMERGE_LOCALS(meth->exception_table->entry[idx].handler_pc);				}			}		}IDBG(		dprintf("%d: %d\n", pc, INSN(pc));		)		switch (INSN(pc)) {		int32 lcl;		case NOP:			INCPC(1);			break;		case ACONST_NULL:			STKPUSH(1);			STACKOUT(0, TOBJ);			INCPC(1);			break;		case ICONST_M1:		case ICONST_0:		case ICONST_1:		case ICONST_2:		case ICONST_3:		case ICONST_4:		case ICONST_5:			STKPUSH(1);			STACKOUT_CONST(0, TINT, INSN(pc) - ICONST_0);			INCPC(1);			break;		case BIPUSH:			STKPUSH(1);			STACKOUT_CONST(0, TINT, BYTE(pc+1));			INCPC(2);			break;		case SIPUSH:			STKPUSH(1);			STACKOUT_CONST(0, TINT, WORD(pc+1));			INCPC(3);			break;		case LCONST_0:		case LCONST_1:			STKPUSH(2);			STACKOUT(0, TLONG);			STACKOUT(1, TVOID);			INCPC(1);			break;		case FCONST_0:		case FCONST_1:		case FCONST_2:			STKPUSH(1);			STACKOUT(0, TFLOAT);			INCPC(1);			break;		case DCONST_0:		case DCONST_1:			STKPUSH(2);			STACKOUT(0, TDOUBLE);			STACKOUT(1, TVOID);			INCPC(1);			break;		case LDC1:			STKPUSH(1);			lcl = (uint8)BYTE(pc + 1);			CONSTANTTYPE(type, lcl);			STACKOUT(0, type);			INCPC(2);			break;		case LDC2:			STKPUSH(1);			CONSTANTTYPE(type, (uint16)WORD(pc+1));			STACKOUT(0, type);			INCPC(3);			break;		case LDC2W:			STKPUSH(2);			CONSTANTTYPE(type, (uint16)WORD(pc+1));			STACKOUT(0, type);			STACKOUT(1, TVOID);			INCPC(3);			break;		case ILOAD_0:		case ILOAD_1:		case ILOAD_2:		case ILOAD_3:			lcl = INSN(pc) - ILOAD_0;			STKPUSH(1);			STACKOUT_LOCAL(0, TINT, lcl);			INCPC(1);			break;		case ILOAD:			if (wide) {				wide = false;				STKPUSH(1);				STACKOUT_LOCAL(0, TINT, WORD(pc+1));				INCPC(3);			}			else {				STKPUSH(1);				STACKOUT_LOCAL(0, TINT, BYTE(pc+1));				INCPC(2);			}			break;		case LLOAD_0:		case LLOAD_1:		case LLOAD_2:		case LLOAD_3:			lcl = INSN(pc) - LLOAD_0;			STKPUSH(2);			STACKOUT_LOCAL(0, TLONG, lcl);			STACKOUT_LOCAL(1, TVOID, lcl+1);			INCPC(1);			break;		case LLOAD:			if (wide) {				wide = false;				STKPUSH(2);				STACKOUT_LOCAL(0, TLONG, WORD(pc+1));				STACKOUT_LOCAL(1, TVOID, WORD(pc+1)+1);				INCPC(3);			}			else {				STKPUSH(2);				STACKOUT_LOCAL(0, TLONG, BYTE(pc+1));				STACKOUT_LOCAL(1, TVOID, BYTE(pc+1)+1);				INCPC(2);			}			break;		case FLOAD_0:		case FLOAD_1:		case FLOAD_2:		case FLOAD_3:			lcl = INSN(pc) - FLOAD_0;			STKPUSH(1);			STACKOUT_LOCAL(0, TFLOAT, lcl);			INCPC(1);			break;		case FLOAD:			if (wide) {				wide = false;				STKPUSH(1);				STACKOUT_LOCAL(0, TFLOAT, WORD(pc+1));				INCPC(3);			}			else {				STKPUSH(1);				STACKOUT_LOCAL(0, TFLOAT, BYTE(pc+1));				INCPC(2);			}			break;		case DLOAD_0:		case DLOAD_1:		case DLOAD_2:		case DLOAD_3:			lcl = INSN(pc) - DLOAD_0;			STKPUSH(2);			STACKOUT_LOCAL(0, TDOUBLE, lcl);			STACKOUT_LOCAL(1, TVOID, lcl+1);			INCPC(1);			break;		case DLOAD:			if (wide) {				lcl = WORD(pc+1);				wide = false;				STKPUSH(2);				STACKOUT_LOCAL(0, TDOUBLE, lcl);				STACKOUT_LOCAL(1, TVOID, lcl+1);				INCPC(3);			}			else {				lcl = BYTE(pc+1);				STKPUSH(2);				STACKOUT_LOCAL(0, TDOUBLE, lcl);				STACKOUT_LOCAL(1, TVOID, lcl+1);				INCPC(2);			}			break;		case ALOAD_0:		case ALOAD_1:		case ALOAD_2:		case ALOAD_3:			lcl = INSN(pc) - ALOAD_0;			STKPUSH(1);			STACKOUT_LOCAL(0, TOBJ, lcl);			INCPC(1);			break;		case ALOAD:			if (wide) {				wide = false;				STKPUSH(1);				STACKOUT_LOCAL(0, TOBJ, WORD(pc+1));				INCPC(3);			}			else {				STKPUSH(1);				STACKOUT_LOCAL(0, TOBJ, BYTE(pc+1));				INCPC(2);			}			break;		case IALOAD:		case BALOAD:		case CALOAD:		case SALOAD:			STACKIN(1, TOBJ);			STACKIN(0, TINT);			STKPOP(1);			STACKOUT(0, TINT);			INCPC(1);			break;		case LALOAD:			STACKIN(1, TOBJ);			STACKIN(0, TINT);			STACKOUT(0, TLONG);			STACKOUT(1, TVOID);			INCPC(1);			break;		case FALOAD:			STACKIN(1, TOBJ);			STACKIN(0, TINT);			STKPOP(1);			STACKOUT(0, TFLOAT);			INCPC(1);			break;		case DALOAD:			STACKIN(1, TOBJ);			STACKIN(0, TINT);			STACKOUT(0, TDOUBLE);			STACKOUT(1, TVOID);			INCPC(1);			break;		case AALOAD:			STACKIN(1, TOBJ);			STACKIN(0, TINT);			STKPOP(1);			STACKOUT(0, TOBJ);			INCPC(1);			break;		case ISTORE_0:		case ISTORE_1:		case ISTORE_2:		case ISTORE_3:			lcl = INSN(pc) - ISTORE_0;			LOCALOUT_STACK(lcl, TINT, 0);			STKPOP(1);			INCPC(1);			break;		case ISTORE:			if (wide) {				LOCALOUT_STACK(WORD(pc+1), TINT, 0);				INCPC(1);				wide = false;			}			else {				LOCALOUT_STACK(BYTE(pc+1), TINT, 0);			}

⌨️ 快捷键说明

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