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

📄 bcmethod.java

📁 derby database source code.good for you.
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
		{			if (stackDepth == 0)				overflowMethodCheck();		}		// Check the declared type of the method		if (SanityManager.DEBUG) {			d_BCValidate.checkMethod(opcode, dt, methodName, debugParameterTypes, rt);		}		return cpi;	}	private Type vmNameDeclaringClass(String declaringClass) {		if (declaringClass == null)			return null;		return cb.factory.type(declaringClass);	}	public void callSuper() {		pushThis();		callMethod(VMOpcode.INVOKESPECIAL, cb.getSuperClassName(), "<init>", "void", 0);	}	public void pushNewStart(String className) {		int cpi = modClass.addClassReference(className);		// Use U2, not CPE, since only wide form exists.		myCode.addInstrU2(VMOpcode.NEW, cpi);		myCode.addInstr(VMOpcode.DUP);		// Grow the stack twice as we are pushing		// two instances of newly created reference		Type nt = cb.factory.type(className);		growStack(1, nt);		growStack(1, nt);	}	public void pushNewComplete(int numArgs) {		callMethod(VMOpcode.INVOKESPECIAL, (String) null, "<init>", "void", numArgs);	}	public void upCast(String className) {		Type uct = cb.factory.type(className);		stackTypes[stackTypeOffset - 1] = uct;		//popStack();		//growStack(1, uct);	}	public void cast(String className) {		Type ct = cb.factory.type(className);		Type tbc = popStack();		short sourceType = tbc.vmType();		short targetType = ct.vmType();		if (SanityManager.DEBUG) {			if (!((sourceType == BCExpr.vm_reference &&				targetType == BCExpr.vm_reference) ||				(sourceType != BCExpr.vm_reference &&				targetType != BCExpr.vm_reference))) {				SanityManager.THROWASSERT("Both or neither must be object types " + ct.javaName() + " " + tbc.javaName());			}		}		// if it is an object type, do a checkcast on it.		if (sourceType == BCExpr.vm_reference) {			int cpi = modClass.addClassReference(ct.vmNameSimple);			myCode.addInstrU2(VMOpcode.CHECKCAST, cpi);		}		// otherwise, try to convert it.		else {			short opcode = VMOpcode.NOP;			// we use the conversionInfo array			// to determine how to convert; if			// the result type of the conversion			// is not our target type, we are not done			// yet.  Make sure there are no			// infinite loop possibilities in the			// conversionInfo array!			while (sourceType!=targetType && opcode!=VMOpcode.BAD) {				short[] currentConversion = 					CodeChunk.CAST_CONVERSION_INFO[sourceType][targetType];				sourceType = currentConversion[1];				opcode = currentConversion[0];				if (opcode != VMOpcode.NOP) {					myCode.addInstr(opcode);				}			}			if (SanityManager.DEBUG) {				SanityManager.ASSERT(opcode != VMOpcode.BAD,					"BAD VMOpcode not expected in cast");			}		}		growStack(ct);	}	public void isInstanceOf(String className) {		int cpi = modClass.addClassReference(className);		myCode.addInstrU2(VMOpcode.INSTANCEOF, cpi);		popStack();		growStack(1, Type.BOOLEAN);	}	public void pushNull(String type) {		myCode.addInstr(VMOpcode.ACONST_NULL);		growStack(1, cb.factory.type(type));	}	public void getField(LocalField field) {		BCLocalField lf = (BCLocalField) field;		Type lt = lf.type;		pushThis();		myCode.addInstrU2(VMOpcode.GETFIELD, lf.cpi);		popStack();		growStack(lt);	}	public void getField(String declaringClass, String fieldName, String fieldType) {		Type dt = popStack();		Type dtu = vmNameDeclaringClass(declaringClass);		if (dtu != null)			dt = dtu;		getField(VMOpcode.GETFIELD, dt.vmNameSimple, fieldName, fieldType);	}	/**		Push the contents of the described static field onto the stack.			*/	public void getStaticField(String declaringClass, String fieldName, String fieldType) {		getField(VMOpcode.GETSTATIC, declaringClass, fieldName, fieldType);	}	private void getField(short opcode, String declaringClass, String fieldName, String fieldType) { 		Type ft = cb.factory.type(fieldType);		int cpi = modClass.addFieldReference(vmNameDeclaringClass(declaringClass).vmNameSimple, fieldName, ft.vmName());		myCode.addInstrU2(opcode, cpi);		growStack(ft);	}		/**	 * Set the field but don't duplicate its value so	 * nothing is left on the stack after this call.	 */	public void setField(LocalField field) {		BCLocalField lf = (BCLocalField) field;		Type lt = lf.type;		putField(lf.type, lf.cpi, false);		if (stackDepth == 0)			overflowMethodCheck();	}	/**		Upon entry the top word(s) on the stack is		the value to be put into the field. Ie.		we have		<PRE>		word		</PRE>		Before the call we need 		<PRE>		word		this		word		</PRE>		word2,word1 -> word2, word1, word2		So that we are left with word after the put.	*/	public void putField(LocalField field) {		BCLocalField lf = (BCLocalField) field;		Type lt = lf.type;		putField(lf.type, lf.cpi, true);	}	/**		Pop the top stack value and store it in the instance field of this class.	*/	public void putField(String fieldName, String fieldType) {		Type ft = cb.factory.type(fieldType);		int cpi = modClass.addFieldReference(cb.classType.vmNameSimple, fieldName, ft.vmName());		putField(ft, cpi, true);	}	private void putField(Type fieldType, int cpi, boolean dup) {		// now have ...,value		if (dup)		{			myCode.addInstr(fieldType.width() == 2  ? VMOpcode.DUP2 : VMOpcode.DUP);			growStack(fieldType);		}		// now have		// dup true:  ...,value,value		// dup false: ...,value,		pushThis();		// now have		// dup true:  ...,value,value,this		// dup false: ...,value,this		swap();		// now have		// dup true:  ...,value,this,value		// dup false: ...,this,value		myCode.addInstrU2(VMOpcode.PUTFIELD, cpi);		popStack(); // the value		popStack(); // this		// now have		// dup true:  ...,value		// dup false: ...	}	/**		Pop the top stack value and store it in the field.		This call requires the instance to be pushed by the caller.	*/	public void putField(String declaringClass, String fieldName, String fieldType) {		Type vt = popStack();		Type dt = popStack();		if (SanityManager.DEBUG) {			if (dt.width() != 1)				SanityManager.THROWASSERT("reference expected for field access - is " + dt.javaName());		}		// have objectref,value		// need value,objectref,value		myCode.addInstr(vt.width() == 2  ? VMOpcode.DUP2_X1 : VMOpcode.DUP_X1);		growStack(vt);		growStack(dt);		growStack(vt);		Type dtu = vmNameDeclaringClass(declaringClass);		if (dtu != null)			dt = dtu;		Type ft = cb.factory.type(fieldType);		int cpi = modClass.addFieldReference(dt.vmNameSimple, fieldName, ft.vmName());		myCode.addInstrU2(VMOpcode.PUTFIELD, cpi);		popStack(); // value		popStack(); // reference	}	public void conditionalIfNull() {		conditionalIf(VMOpcode.IFNONNULL);	}	public void conditionalIf() {		conditionalIf(VMOpcode.IFEQ);	}	private Conditional condition;	private void conditionalIf(short opcode) {		popStack();		int clearTo = stackTypeOffset;		condition = new Conditional(condition, myCode, opcode, clearTo);	}	public void startElseCode() {		int clearTo = condition.startElse(myCode, stackTypeOffset);		if (SanityManager.DEBUG) {			if ((stackTypeOffset - 1) != clearTo)				SanityManager.THROWASSERT(stackTypeOffset + " is not one more than " + clearTo);		}		while (stackTypeOffset > clearTo) {			popStack();		}	}	public void completeConditional() {		condition = condition.end(myCode, stackTypeOffset);	}		public void pop() {		if (SanityManager.DEBUG) {			if (stackDepth == 0)				SanityManager.THROWASSERT("pop when stack is empty!");		}		Type toPop = popStack();		myCode.addInstr(toPop.width() == 2  ? VMOpcode.POP2 : VMOpcode.POP);				if (stackDepth == 0)			overflowMethodCheck();	}		public void endStatement() {		if (stackDepth != 0) {			pop();		}		//if (SanityManager.DEBUG) {		//	if (stackDepth != 0)		//		SanityManager.THROWASSERT("items left on stack " + stackDepth);	//	}	}	/**	*/	public void getArrayElement(int element) {		push(element);		popStack(); // int just pushed will be popped by array access		Type arrayType = popStack();		String arrayJava = arrayType.javaName();		String componentString = arrayJava.substring(0,arrayJava.length()-2);		Type componentType = cb.factory.type(componentString);		short typ = componentType.vmType();		// boolean has a type id of integer, here it needs to be byte.		if ((typ == BCExpr.vm_int) && (componentType.vmName().equals("Z")))			typ = BCExpr.vm_byte;		myCode.addInstr(CodeChunk.ARRAY_ACCESS[typ]);		growStack(componentType);	}	// come in with ref, value	public void setArrayElement(int element) {		// ref, value		push(element);		// ref, value, index		swap();				Type componentType = popStack(); // value		popStack(); // int just pushed will be popped by array access				popStack(); // array ref.		short typ = componentType.vmType();		// boolean has a type id of integer, here it needs to be byte.		if ((typ == BCExpr.vm_int) && (componentType.vmName().equals("Z")))			typ = BCExpr.vm_byte;		myCode.addInstr(CodeChunk.ARRAY_STORE[typ]);	}	/**		this array maps the BCExpr vm_* constants 0..6 to		the expected VM type constants for the newarray instruction.		<p>		Because boolean was mapped to integer for general instructions,		it will have to be specially matched and mapped to its value		directly (4).	 */	private static final byte newArrayElementTypeMap[] = { 8, 9, 10, 11, 6, 7, 5 };	static final byte T_BOOLEAN = 4;	/**		Create an array instance		Stack ... =>		      ...,arrayref	*/	public void pushNewArray(String className, int size) {		push(size);		popStack(); // int just pushed will be popped by array creation		Type elementType = cb.factory.type(className);		// determine the instruction to use based on the element type		if (elementType.vmType() == BCExpr.vm_reference) {			// For an array of Java class/interface elements, generate:			// ANEWARRAY #cpei ; where cpei is a constant pool index for the class			int cpi = modClass.addClassReference(elementType.javaName());			// Use U2, not CPE, since only wide form exists.			myCode.addInstrU2(VMOpcode.ANEWARRAY, cpi);		} else {			byte atype;			// get the argument for the array type			// if the element type is boolean, we can't use the map			// because the type id will say integer.			// but we can use vm_int test to weed out some tests			if (elementType.vmType() == BCExpr.vm_int &&			    VMDescriptor.C_BOOLEAN == elementType.vmName().charAt(0))				atype = T_BOOLEAN;			else				atype = newArrayElementTypeMap[elementType.vmType()];			// For an array of Java builtin type elements, generate:			// NEWARRAY #atype ; where atype is a constant for the builtin type			myCode.addInstrU1(VMOpcode.NEWARRAY, atype);		}		// an array reference is an object, hence width of 1		growStack(1, cb.factory.type(className.concat("[]")));	}	/**		Tell if statement number in this method builder hits limit.  This		method builder keeps a counter of how many statements are added to it.		Caller should call this function every time it tries to add a statement		to this method builder (counter is increased by 1), then the function		returns whether the accumulated statement number hits a limit.		The reason of doing this is that Java compiler has a limit of 64K code		size for each method.  We might hit this limit if an extremely long		insert statement is issued, for example (see beetle 4293).  Counting		statement number is an approximation without too much overhead.	*/	public boolean statementNumHitLimit(int noStatementsAdded)	{		if (statementNum > 2048)    // 2K limit			return true;		else		{			statementNum = statementNum + noStatementsAdded;			return false;		}	}		/**	 * Check to see if the current method byte code is nearing the	 * limit of 65535. If it is start overflowing to a new method.	 * <P>	 * Overflow is handled for a method named e23 as:	 * <CODE>	 public Object e23()	 {	   ... existing code	   // split point	   return e23_0();	 }	 private Object e23_0()	 {	    ... first set overflowed code	    // split point	    return e23_1(); 	 }	 private Object e23_1()	 {	    ... second set overflowed code	    // method complete	    return result; 	 }	 	 </CODE>	 <P>	 	 These overflow methods are hidden from the code using this MethodBuilder,	 it continues to think that it is building a single method with the	 original name.	 * <BR> Restrictions:	 * <UL>	 * <LI> Only handles methods with no arguments	 * <LI> Stack depth must be zero	 * </UL>	 * 	 *	 */	private void overflowMethodCheck()	{		if (handlingOverflow)			return;				// don't sub method in the middle of a conditional		if (condition != null)			return;				int currentCodeSize = myCode.getRelativePC();				// Overflow at >= 55,000 bytes which is someway		// below the limit of 65,535. Ideally overflow		// would occur at 65535 minus the few bytes needed		// to call the sub-method, but the issue is at this level		// we don't know frequently we are called given the restriction		// of only being called when the stack depth is zero.		// Thus split earlier to try ensure most cases are caught.		// Only downside is that we may split into N methods when N-1 would suffice.		if (currentCodeSize < 55000)			return;				// only handle no-arg methods at the moment.		if (parameters != null)		{			if (parameters.length != 0)				return;		}				int modifiers = myEntry.getModifier();			//System.out.println("NEED TO SPLIT " + myEntry.getName() + "  " + currentCodeSize + " stack " + stackDepth);		// the sub-method can be private to ensure that no-one		// can call it accidentally from outside the class.		modifiers &= ~(Modifier.PROTECTED | Modifier.PUBLIC);		modifiers |= Modifier.PRIVATE;				String subMethodName = myName + "_s" + Integer.toString(subMethodCount++);		BCMethod subMethod = (BCMethod) cb.newMethodBuilder(				modifiers,				myReturnType, subMethodName);		subMethod.thrownExceptions = this.thrownExceptions;						// stop any recursion		handlingOverflow = true;				// in this method make a call to the sub method we will		// be transferring control to.		short op;		if ((modifiers & Modifier.STATIC) == 0)		{			op = VMOpcode.INVOKEVIRTUAL;			this.pushThis();		} else {			op = VMOpcode.INVOKESTATIC;		}				this.callMethod(op, (String) null, subMethodName, myReturnType, 0);			// and return its value, works just as well for a void method!		this.methodReturn();		this.complete();				handlingOverflow = false;				// now the tricky bit, make this object take over the		// code etc. from the sub method. This is done so		// that any code that has a reference to this MethodBuilder		// will continue to work. They will be writing code into the		// new sub method.				this.myEntry = subMethod.myEntry;		this.myCode = subMethod.myCode;		this.currentVarNum = subMethod.currentVarNum;		this.statementNum = subMethod.statementNum;				// copy stack info		this.stackTypes = subMethod.stackTypes;		this.stackTypeOffset = subMethod.stackTypeOffset;		this.maxStack = subMethod.maxStack;		this.stackDepth = subMethod.stackDepth;	}}

⌨️ 快捷键说明

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