blob: 10dcf8efbb9cd3f2eada89d5d139dbec2b626385 [file] [log] [blame]
/*******************************************************************************
* 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;
}
}