All Downloads are FREE. Search and download functionalities are using the official Maven repository.

prompto.compiler.MethodInfo Maven / Gradle / Ivy

The newest version!
package prompto.compiler;

import java.lang.reflect.Modifier;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;

import prompto.compiler.IVerifierEntry.VerifierType;

public class MethodInfo {
	
	int accessFlags = Modifier.PUBLIC;
	Utf8Constant name;
	Utf8Constant signature;
	List attributes = new LinkedList<>();
	CodeAttribute codeAttribute = null;
	Descriptor descriptor;
	ClassFile classFile;
	
	MethodInfo(ClassFile classFile, String name, Descriptor.Method descriptor) {
		this.classFile = classFile;
		this.descriptor = descriptor;
		this.name = new Utf8Constant(name);
		this.signature = new Utf8Constant(descriptor.toString());
	}
	
	public ClassFile getClassFile() {
		return classFile;
	}

	public Utf8Constant getName() {
		return name;
	}
	
	public Utf8Constant getSignature() {
		return signature;
	}
	
	public CodeAttribute getCodeAttribute() {
		return codeAttribute;
	}

	public LocalVariableTableAttribute getLocals() {
		ensureCodeAttribute();
		return codeAttribute.getLocals();
	}

	@Override
	public String toString() {
		return name.toString() + '/' + signature.toString();
	}
	
	public void addModifier(int modifier) {
		accessFlags |= modifier;
	}
	
	public boolean isStatic() {
		return (accessFlags & Modifier.STATIC) != 0;
	}


	public IInstruction addInstruction(Opcode op, IOperand ... operands) {
		return addInstruction(new Instruction(op, operands));
	}
	
	public  T addInstruction(T instruction) {
		ensureCodeAttribute();
		return codeAttribute.addInstruction(instruction);
	}

	public  T addOffsetListener(T listener) {
		ensureCodeAttribute();
		return codeAttribute.addOffsetListener(listener);
	}
	
	public IInstruction activateOffsetListener(IInstructionListener listener) {
		return codeAttribute.activateOffsetListener(listener);
	}

	public IInstruction inhibitOffsetListener(IInstructionListener listener) {
		return codeAttribute.inhibitOffsetListener(listener);
	}

	public StackLocal registerLocal(String name, VerifierType type, ClassConstant className) {
		ensureCodeAttribute();
		return codeAttribute.registerLocal(type.newStackLocal(name, className));
	}
	
	/* a work-around to get a unique transient variable name */
	/* the real solution is to manage variable scope */
	public String nextTransientName(String core) {
		ensureCodeAttribute();
		return codeAttribute.nextTransientName(core);
	}

	public StackLocal getRegisteredLocal(String name) {
		ensureCodeAttribute();
		return codeAttribute.getRegisteredLocal(name);
	}
	
	public void unregisterLocal(StackLocal local) {
		codeAttribute.unregisterLocal(local);
	}

	public ExceptionHandler registerExceptionHandler(java.lang.reflect.Type type) {
		ensureCodeAttribute();
		return codeAttribute.registerExceptionHandler(type);
	}

	public void placeExceptionHandler(ExceptionHandler handler) {
		codeAttribute.placeExceptionHandler(handler);
	}

	void register(ConstantsPool pool) {
		if(DumpLevel.current().ordinal()>0)
			System.err.println("Registering method: " + this.toString());
		name.register(pool);
		signature.register(pool);
		attributes.forEach((a)->
			a.register(pool));
	}

	public CodeAttribute ensureCodeAttribute() {
		if(codeAttribute==null) {
			codeAttribute = new CodeAttribute();
			attributes.add(codeAttribute);
		}
		return codeAttribute;
	}

	public StackLocals captureStackLocals() {
		// register stack locals, both planned (StackState) and current (locals)
		StackLocals locals = new StackLocals();
		locals.stackState = captureStackState(); 
		locals.numLocals = getLocals().numLocals();
		return locals;
	}
	
	public void restoreStackLocals(StackLocals stackLocals) {
		// restore stack locals
		List locals = getLocals().getEntries();
		ListIterator iterLocals = locals.listIterator(locals.size());
		while(iterLocals.hasPrevious()) {
			StackLocal local = iterLocals.previous();
			if(local.getIndex()>=stackLocals.numLocals)
				unregisterLocal(local);
			else
				break;
		}
		restoreStackLocals(stackLocals.stackState);
	}



	public StackState captureStackState() {
		ensureCodeAttribute();
		return codeAttribute.captureStackState();
	}

	public void restoreFullStackState(StackState state) {
		codeAttribute.restoreFullStackState(state);
	}
	
	public void restoreStackLocals(StackState state) {
		codeAttribute.restoreStackLocals(state);
	}

	public StackLabel placeLabel(StackState state) {
		ensureCodeAttribute();
		return codeAttribute.placeLabel(state);
	}


	void writeTo(ByteWriter writer) {
		/*
		method_info {
		    u2             access_flags;
		    u2             name_index;
		    u2             descriptor_index;
		    u2             attributes_count;
		    attribute_info attributes[attributes_count];
		}
		*/
		writer.writeU2(accessFlags);
		writer.writeU2(name.getIndexInConstantPool());
		writer.writeU2(signature.getIndexInConstantPool());
		writer.writeU2(attributes.size());
		attributes.forEach((a)->
			a.writeTo(writer));
	}




}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy