/* * This file is part of the Jikes RVM project (http://jikesrvm.org). * * This file is licensed to You under the Eclipse Public License (EPL); * You may not use this file except in compliance with the License. You * may obtain a copy of the License at * * http://www.opensource.org/licenses/eclipse-1.0.php * * See the COPYRIGHT.txt file distributed with this work for information * regarding copyright ownership. */ package org.mmtk.harness.lang.compiler; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.mmtk.harness.lang.Declaration; import org.mmtk.harness.lang.Env; import org.mmtk.harness.lang.ast.NormalMethod; import org.mmtk.harness.lang.pcode.PseudoOp; import org.mmtk.harness.lang.pcode.ResolvableOp; import org.mmtk.harness.lang.runtime.PcodeInterpreter; import org.mmtk.harness.lang.runtime.StackFrame; import org.mmtk.harness.scheduler.Schedulable; /** * A method, compiled into pseudo-ops. */ public class CompiledMethod implements Schedulable { /** The name of the method */ private final String name; /** The list of instructions */ private final List<PseudoOp> contents = new ArrayList<PseudoOp>(); /** The variable declarations */ private final List<Declaration> decls; /** The number of temporaries */ private int nTemps; /** * Create an (empty) virtual method for the given parsed method. * @param method */ public CompiledMethod(NormalMethod method) { this.name = method.getName(); this.decls = method.getDecls(); } /** * Return the array of instructions corresponding to this method * @return */ public PseudoOp[] getCodeArray() { return contents.toArray(new PseudoOp[0]); } /** * Append new instructions * @param elements */ public void append(PseudoOp...elements) { contents.addAll(Arrays.asList(elements)); } /** * Get the index of the current instruction, eg as a branch target. * @return */ public int currentIndex() { return contents.size(); } /** * Return the name of this method * @return */ public String getName() { return name; } /** * Set the # temporaries required to execute * this method * @param nTemps */ public void setTemps(int nTemps) { this.nTemps = nTemps; } /** * Resolve all the method references in this method's instructions, * by replacing proxy references with the real compiled method. */ public void resolveMethodReferences() { for (PseudoOp op : contents) { if (op instanceof ResolvableOp) { ((ResolvableOp)op).resolve(); } } } /** * Format the p-code for this method */ public String toString() { StringBuilder buf = new StringBuilder(); int i=0; for (PseudoOp op : contents) { buf.append(String.format("%4d : %s%n",i++,op)); } return buf.toString(); } /** * Resolve this method. Since this is a compiled method, not a * proxy, we return ourselves. * @return */ public CompiledMethod resolve() { return this; } /** * A CompiledMethod is always resolved. * @return */ public boolean isResolved() { return true; } /** * Create a new stack frame for the execution of this method. * @return */ public StackFrame formatStackFrame() { return new StackFrame(decls,nTemps); } public void execute(Env env) { new PcodeInterpreter(env,this).exec(); } }