blob: b08ee06becacac8bc20baef5f23ac2c4c404206c [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @author Intel, George A. Timoshenko
*
*/
#ifndef _JAVABYTECODEPARSER_H_
#define _JAVABYTECODEPARSER_H_
#include <stdio.h>
#include <iostream>
#include "ByteCodeParser.h"
#include "BitSet.h"
#include "Queue.h"
#include "HashTable.h"
namespace Jitrino {
//
// big-endian ordering
//
int16 si16(const U_8* bcp);
uint16 su16(const U_8* bcp);
I_32 si32(const U_8* bcp);
uint64 si64(const U_8* bcp);
class JavaSwitchTargetsIter;
class JavaLookupSwitchTargetsIter;
class JavaByteCodeParserCallback : public ByteCodeParserCallback {
public:
JavaByteCodeParserCallback() : isLinearPass(true) {
currentOffset = 0;
nextOffset = 0;
linearPassDone = false;
visited = NULL;
bytecodevisited = NULL;
prepassVisited = NULL;
labelStack = NULL;
noNeedToParse = false;
}
JavaByteCodeParserCallback(MemoryManager& memManager,U_32 byteCodeLength)
: isLinearPass(false)
{
currentOffset = 0;
nextOffset = 0;
linearPassDone = false;
visited = new (memManager) BitSet(memManager,byteCodeLength);
bytecodevisited = new (memManager) BitSet(memManager,byteCodeLength);
prepassVisited = NULL;
labelStack = new (memManager) Queue<U_8>(memManager);
noNeedToParse = false;
}
bool parseByteCode(const U_8* byteCodes,U_32 byteCodeOffset);
BitSet* getVisited() { return visited; }
protected:
// the current byte codes offset
U_32 currentOffset;
const bool isLinearPass;
bool linearPassDone;
BitSet* visited;
BitSet* bytecodevisited;
BitSet* prepassVisited;
Queue<U_8>* labelStack;
// for example when some exception type can not be resolved
bool noNeedToParse;
// called before each byte code to indicate the next byte code's offset
virtual void offset(U_32 offset) = 0;
virtual void offset_done(U_32 offset) = 0;
virtual void nop() = 0;
virtual void aconst_null() = 0;
virtual void iconst(I_32) = 0;
virtual void lconst(int64) = 0;
virtual void fconst(float) = 0;
virtual void dconst(double) = 0;
virtual void bipush(I_8) = 0;
virtual void sipush(int16) = 0;
virtual void ldc(U_32) = 0;
virtual void ldc2(U_32) = 0;
virtual void iload(uint16 varIndex) = 0;
virtual void lload(uint16 varIndex) = 0;
virtual void fload(uint16 varIndex) = 0;
virtual void dload(uint16 varIndex) = 0;
virtual void aload(uint16 varIndex) = 0;
virtual void iaload() = 0;
virtual void laload() = 0;
virtual void faload() = 0;
virtual void daload() = 0;
virtual void aaload() = 0;
virtual void baload() = 0;
virtual void caload() = 0;
virtual void saload() = 0;
virtual void istore(uint16 varIndex,U_32 off) = 0;
virtual void lstore(uint16 varIndex,U_32 off) = 0;
virtual void fstore(uint16 varIndex,U_32 off) = 0;
virtual void dstore(uint16 varIndex,U_32 off) = 0;
virtual void astore(uint16 varIndex,U_32 off) = 0;
virtual void iastore() = 0;
virtual void lastore() = 0;
virtual void fastore() = 0;
virtual void dastore() = 0;
virtual void aastore() = 0;
virtual void bastore() = 0;
virtual void castore() = 0;
virtual void sastore() = 0;
virtual void pop() = 0;
virtual void pop2() = 0;
virtual void dup() = 0;
virtual void dup_x1() = 0;
virtual void dup_x2() = 0;
virtual void dup2() = 0;
virtual void dup2_x1() = 0;
virtual void dup2_x2() = 0;
virtual void swap() = 0;
virtual void iadd() = 0;
virtual void ladd() = 0;
virtual void fadd() = 0;
virtual void dadd() = 0;
virtual void isub() = 0;
virtual void lsub() = 0;
virtual void fsub() = 0;
virtual void dsub() = 0;
virtual void imul() = 0;
virtual void lmul() = 0;
virtual void fmul() = 0;
virtual void dmul() = 0;
virtual void idiv() = 0;
virtual void ldiv() = 0;
virtual void fdiv() = 0;
virtual void ddiv() = 0;
virtual void irem() = 0;
virtual void lrem() = 0;
virtual void frem() = 0;
virtual void drem() = 0;
virtual void ineg() = 0;
virtual void lneg() = 0;
virtual void fneg() = 0;
virtual void dneg() = 0;
virtual void ishl() = 0;
virtual void lshl() = 0;
virtual void ishr() = 0;
virtual void lshr() = 0;
virtual void iushr() = 0;
virtual void lushr() = 0;
virtual void iand() = 0;
virtual void land() = 0;
virtual void ior() = 0;
virtual void lor() = 0;
virtual void ixor() = 0;
virtual void lxor() = 0;
virtual void iinc(uint16 varIndex,I_32 amount) = 0;
virtual void i2l() = 0;
virtual void i2f() = 0;
virtual void i2d() = 0;
virtual void l2i() = 0;
virtual void l2f() = 0;
virtual void l2d() = 0;
virtual void f2i() = 0;
virtual void f2l() = 0;
virtual void f2d() = 0;
virtual void d2i() = 0;
virtual void d2l() = 0;
virtual void d2f() = 0;
virtual void i2b() = 0;
virtual void i2c() = 0;
virtual void i2s() = 0;
virtual void lcmp() = 0;
virtual void fcmpl() = 0;
virtual void fcmpg() = 0;
virtual void dcmpl() = 0;
virtual void dcmpg() = 0;
virtual void ifeq(U_32 targetOffset,U_32 nextOffset) = 0;
virtual void ifne(U_32 targetOffset,U_32 nextOffset) = 0;
virtual void iflt(U_32 targetOffset,U_32 nextOffset) = 0;
virtual void ifge(U_32 targetOffset,U_32 nextOffset) = 0;
virtual void ifgt(U_32 targetOffset,U_32 nextOffset) = 0;
virtual void ifle(U_32 targetOffset,U_32 nextOffset) = 0;
virtual void if_icmpeq(U_32 targetOffset,U_32 nextOffset) = 0;
virtual void if_icmpne(U_32 targetOffset,U_32 nextOffset) = 0;
virtual void if_icmplt(U_32 targetOffset,U_32 nextOffset) = 0;
virtual void if_icmpge(U_32 targetOffset,U_32 nextOffset) = 0;
virtual void if_icmpgt(U_32 targetOffset,U_32 nextOffset) = 0;
virtual void if_icmple(U_32 targetOffset,U_32 nextOffset) = 0;
virtual void if_acmpeq(U_32 targetOffset,U_32 nextOffset) = 0;
virtual void if_acmpne(U_32 targetOffset,U_32 nextOffset) = 0;
virtual void goto_(U_32 targetOffset,U_32 nextOffset) = 0;
virtual void jsr(U_32 offset, U_32 nextOffset) = 0;
virtual void ret(uint16 varIndex, const U_8* byteCodes) = 0;
virtual void tableswitch(JavaSwitchTargetsIter*) = 0;
virtual void lookupswitch(JavaLookupSwitchTargetsIter*) = 0;
virtual void ireturn(U_32 off) = 0;
virtual void lreturn(U_32 off) = 0;
virtual void freturn(U_32 off) = 0;
virtual void dreturn(U_32 off) = 0;
virtual void areturn(U_32 off) = 0;
virtual void return_(U_32 off) = 0;
virtual void getstatic(U_32 constPoolIndex) = 0;
virtual void putstatic(U_32 constPoolIndex) = 0;
virtual void getfield(U_32 constPoolIndex) = 0;
virtual void putfield(U_32 constPoolIndex) = 0;
virtual void invokevirtual(U_32 constPoolIndex) = 0;
virtual void invokespecial(U_32 constPoolIndex) = 0;
virtual void invokestatic(U_32 constPoolIndex) = 0;
virtual void invokeinterface(U_32 constPoolIndex,U_32 count) = 0;
virtual void new_(U_32 constPoolIndex) = 0;
virtual void newarray(U_8 type) = 0;
virtual void anewarray(U_32 constPoolIndex) = 0;
virtual void arraylength() = 0;
virtual void athrow() = 0;
virtual void checkcast(U_32 constPoolIndex) = 0;
virtual int instanceof(const U_8* bcp, U_32 constPoolIndex, U_32 off) = 0;
virtual void monitorenter() = 0;
virtual void monitorexit() = 0;
virtual void multianewarray(U_32 constPoolIndex,U_8 dimensions) = 0;
virtual void ifnull(U_32 targetOffset,U_32 nextOffset) = 0;
virtual void ifnonnull(U_32 targetOffset,U_32 nextOffset) = 0;
virtual bool skipParsing() {return noNeedToParse;}
};
class JavaSwitchTargetsIter {
public:
JavaSwitchTargetsIter(const U_8* bcp,U_32 off) {
// skip over padding
switchOffset = off;
U_32 offset = ((off+4)&~3)-off;
// read in the default target
defaultTarget = readU4Be(bcp+offset);
lowValue = readU4Be(bcp+offset+4);
highValue = readU4Be(bcp+offset+8);
numTargets = highValue - lowValue + 1;
nextTarget = bcp+offset+12;
length = ((U_32)(nextTarget-bcp)) + (numTargets * 4);
nextByteCode = bcp + length;
}
bool hasNext() {
return (nextTarget < nextByteCode);
}
U_32 getNextTarget() {
if (hasNext() == false)
return 0;
I_32 target = readU4Be(nextTarget);
nextTarget += 4;
return target+switchOffset;
}
U_32 getNumTargets() {return numTargets;}
U_32 getLength() {return length;}
U_32 getDefaultTarget() {return defaultTarget+switchOffset;}
U_32 getHighValue() {return highValue;}
U_32 getLowValue() {return lowValue;}
private:
const U_8* nextByteCode;
const U_8* nextTarget;
U_32 switchOffset;
U_32 numTargets;
U_32 length;
I_32 defaultTarget;
U_32 highValue;
U_32 lowValue;
};
class JavaLookupSwitchTargetsIter {
public:
JavaLookupSwitchTargetsIter(const U_8* bcp,U_32 off) {
// skip over padding
lookupOffset = off;
U_32 offset = ((off+4)&~3)-off;
// read in the default target
defaultTarget = readU4Be(bcp+offset);
numTargets = readU4Be(bcp+offset+4);
nextTarget = bcp+offset+8;
length = ((U_32)(nextTarget-bcp)) + (numTargets * 8);
nextByteCode = bcp + length;
}
bool hasNext() {
return (nextTarget < nextByteCode);
}
U_32 getNextTarget(U_32* key) {
if (hasNext() == false)
return 0;
*key = readU4Be(nextTarget);
I_32 target = readU4Be(nextTarget+4);
nextTarget += 8;
return target+lookupOffset;
}
U_32 getNumTargets() {return numTargets;}
U_32 getLength() {return length;}
U_32 getDefaultTarget() {return defaultTarget+lookupOffset;}
private:
const U_8* nextByteCode;
const U_8* nextTarget;
U_32 lookupOffset;
U_32 numTargets;
U_32 length;
I_32 defaultTarget;
};
} //namespace Jitrino
#endif // _JAVABYTECODEPARSER_H_