/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.core.util; import org.eclipse.jdt.core.util.ClassFormatException; import org.eclipse.jdt.core.util.IConstantPool; import org.eclipse.jdt.core.util.IStackMapFrame; import org.eclipse.jdt.core.util.IVerificationTypeInfo; /** * Default implementation of IStackMapFrame */ public class StackMapFrame extends ClassFileStruct implements IStackMapFrame { private static final IVerificationTypeInfo[] EMPTY_LOCALS_OR_STACK_ITEMS= new IVerificationTypeInfo[0]; private int readOffset; private int frameType; private int numberOfLocals; private int numberOfStackItems; private IVerificationTypeInfo[] locals; private IVerificationTypeInfo[] stackItems; private int offsetDelta; /** * Constructor for StackMapFrame. * * @param classFileBytes * @param constantPool * @param offset * @throws ClassFormatException */ public StackMapFrame( byte[] classFileBytes, IConstantPool constantPool, int offset) throws ClassFormatException { final int type= u1At(classFileBytes, 0, offset); this.frameType= type; switch (type) { case 247: // SAME_LOCALS_1_STACK_ITEM_EXTENDED this.offsetDelta= u2At(classFileBytes, 1, offset); this.numberOfStackItems= 1; this.stackItems= new VerificationInfo[1]; this.readOffset= 3; VerificationInfo info= new VerificationInfo(classFileBytes, constantPool, offset + this.readOffset); this.stackItems[0]= info; this.readOffset+= info.sizeInBytes(); this.locals= EMPTY_LOCALS_OR_STACK_ITEMS; this.numberOfLocals= 0; break; case 248: case 249: case 250: // CHOP this.offsetDelta= u2At(classFileBytes, 1, offset); this.numberOfStackItems= 0; this.stackItems= EMPTY_LOCALS_OR_STACK_ITEMS; this.readOffset= 3; this.locals= EMPTY_LOCALS_OR_STACK_ITEMS; this.numberOfLocals= 0; break; case 251: // SAME_FRAME_EXTENDED this.offsetDelta= u2At(classFileBytes, 1, offset); this.numberOfStackItems= 0; this.stackItems= EMPTY_LOCALS_OR_STACK_ITEMS; this.readOffset= 3; this.locals= EMPTY_LOCALS_OR_STACK_ITEMS; this.numberOfLocals= 0; break; case 252: case 253: case 254: // APPEND this.offsetDelta= u2At(classFileBytes, 1, offset); this.numberOfStackItems= 0; this.stackItems= EMPTY_LOCALS_OR_STACK_ITEMS; this.readOffset= 3; int diffLocals= type - 251; this.numberOfLocals= diffLocals; this.locals= new IVerificationTypeInfo[diffLocals]; for (int i= 0; i < diffLocals; i++) { VerificationInfo verificationInfo= new VerificationInfo(classFileBytes, constantPool, offset + this.readOffset); this.locals[i]= verificationInfo; this.readOffset+= verificationInfo.sizeInBytes(); } break; case 255: // FULL_FRAME this.offsetDelta= u2At(classFileBytes, 1, offset); int tempLocals= u2At(classFileBytes, 3, offset); this.numberOfLocals= tempLocals; this.readOffset= 5; if (tempLocals != 0) { this.locals= new IVerificationTypeInfo[tempLocals]; for (int i= 0; i < tempLocals; i++) { VerificationInfo verificationInfo= new VerificationInfo(classFileBytes, constantPool, offset + this.readOffset); this.locals[i]= verificationInfo; this.readOffset+= verificationInfo.sizeInBytes(); } } else { this.locals= EMPTY_LOCALS_OR_STACK_ITEMS; } int tempStackItems= u2At(classFileBytes, this.readOffset, offset); this.readOffset+= 2; this.numberOfStackItems= tempStackItems; if (tempStackItems != 0) { this.stackItems= new IVerificationTypeInfo[tempStackItems]; for (int i= 0; i < tempStackItems; i++) { VerificationInfo verificationInfo= new VerificationInfo(classFileBytes, constantPool, offset + this.readOffset); this.stackItems[i]= verificationInfo; this.readOffset+= verificationInfo.sizeInBytes(); } } else { this.stackItems= EMPTY_LOCALS_OR_STACK_ITEMS; } break; default: if (type <= 63) { // SAME_FRAME this.offsetDelta= type; this.numberOfStackItems= 0; this.stackItems= EMPTY_LOCALS_OR_STACK_ITEMS; this.locals= EMPTY_LOCALS_OR_STACK_ITEMS; this.numberOfLocals= 0; this.readOffset= 1; } else if (type <= 127) { // SAME_LOCALS_1_STACK_ITEM this.offsetDelta= type - 64; this.numberOfStackItems= 1; this.stackItems= new VerificationInfo[1]; this.readOffset= 1; info= new VerificationInfo(classFileBytes, constantPool, offset + this.readOffset); this.stackItems[0]= info; this.readOffset+= info.sizeInBytes(); this.locals= EMPTY_LOCALS_OR_STACK_ITEMS; this.numberOfLocals= 0; } } } int sizeInBytes() { return this.readOffset; } public int getFrameType() { return this.frameType; } public IVerificationTypeInfo[] getLocals() { return this.locals; } public int getNumberOfLocals() { return this.numberOfLocals; } public int getNumberOfStackItems() { return this.numberOfStackItems; } public int getOffsetDelta() { return this.offsetDelta; } public IVerificationTypeInfo[] getStackItems() { return this.stackItems; } }