internal void WriteFrame(StackMapFrame frame) { _writer.WriteU1(frame.Tag); switch (frame) { case SameLocals1StackItemFrame sameLocals1StackItemFrame: WriteFrame(sameLocals1StackItemFrame); break; case SameLocals1StackItemFrameExtended sameLocals1StackItemFrameExtended: WriteFrame(sameLocals1StackItemFrameExtended); break; case ChopFrame chopFrame: WriteFrame(chopFrame); break; case SameFrameExtended sameFrameExtended: WriteFrame(sameFrameExtended); break; case AppendFrame appendFrame: WriteFrame(appendFrame); break; } }
public StackMapFrame[] ReadStackMapFrames(ushort numberOfEntries) { var stackMapFrames = new StackMapFrame[numberOfEntries]; for (var i = 0; i < numberOfEntries; i++) { stackMapFrames[i] = new StackMapFrame().Read(_classData); } return(stackMapFrames); }
private StackMapFrame GetInitialFrame() { var frame = new StackMapFrame(); var argTypes = Method.Parameters.Select(x => x.Type).ToList(); var len = argTypes.Count; var count = 0; if (!Method.Modifiers.HasFlag(Modifier.Static)) { Type thisType = Method.DeclaringType; frame.Locals = new Type[len + 1]; if (Method.Name == "<init>" && thisType.GetDescriptor(true) != "java/lang/Object") { frame.Locals[count++] = UninitializedType.UninitializedThis(thisType); } else { frame.Locals[count++] = thisType; } } else { frame.Locals = new Type[len]; } foreach (var argType in argTypes) { frame.Locals[count++] = argType; } frame.PC = -1; frame.Stack = null; return frame; }
private void EmitStackMapFrame() { if (lastFrame == null) { // first frame lastFrame = GetInitialFrame(); } else if (lastFrame.PC == length) { // drop existing stackmap at this offset stackMapTableBuffer[--stackMapBufferSize] = null; lastFrame = frameBeforeLast; frameBeforeLast = null; } var frame = new StackMapFrame { PC = length }; var localCount = 0; var locals = new Type[variableCount]; for (var i = 0; i < variableCount; i++, localCount++) { var variable = GetVariable(i); if (variable == null || !variable.IsDefined) continue; var vtype = variable.Type; locals[i] = vtype; if (TypeCodeHelper.Width(vtype) > 1) i++; } frame.Locals = new Type[localCount]; for (int i = 0, j = 0; i < variableCount; i++, j++) { Debug.Assert(j < localCount); frame.Locals[j] = locals[i]; if (TypeCodeHelper.Width(locals[i]) > 1) i++; } var stackCount = 0; for (var i = 0; i < state.StackSize; i++) { if (state.GetStack(i) != null) { stackCount++; } } frame.Stack = new Type[stackCount]; stackCount = 0; for (var i = 0; i < state.StackSize; i++) { if (state.GetStack(i) != null) { frame.Stack[stackCount++] = state.GetStack(i); } } if (stackMapTableBuffer == null) { stackMapTableBuffer = new CompileAttributeStackMapTable.StackMapFrame[20]; } else if (stackMapTableBuffer.Length == stackMapBufferSize) { var newStackMapTableBuffer = new CompileAttributeStackMapTable.StackMapFrame[stackMapBufferSize << 1]; Array.Copy(stackMapTableBuffer, 0, newStackMapTableBuffer, 0, stackMapBufferSize); stackMapTableBuffer = newStackMapTableBuffer; } stackMapTableBuffer[stackMapBufferSize++] = CompileAttributeStackMapTable.StackMapFrame.GetInstance(this, frame, lastFrame.PC, lastFrame.Locals); frameBeforeLast = lastFrame; lastFrame = frame; }
public override CompileAttribute Read(EndianBinaryReader reader, List<CompileConstant> constants, int length) { Entries = new List<StackMapFrame>(); short entryCount = reader.ReadInt16(); for (int i = 0; i < entryCount; i++) { var entry = new StackMapFrame(); entry.Type = reader.ReadByte(); if (entry.Type <= 63) { // SAME } else if (entry.Type >= 64 && entry.Type <= 127) { // SAME_LOCALS_1_STACK_ITEM var item = new VerificationTypeInfo(); item.Read(reader); entry.Stack.Add(item); } else if (entry.Type == 247) { // SAME_LOCALS_1_STACK_ITEM_EXTENDED entry.OffsetDelta = reader.ReadInt16(); var item = new VerificationTypeInfo(); item.Read(reader); entry.Stack.Add(item); } else if (entry.Type >= 248 && entry.Type <= 250) { // CHOP entry.OffsetDelta = reader.ReadInt16(); } else if (entry.Type == 251) { // SAME_FRAME_EXTENDED entry.OffsetDelta = reader.ReadInt16(); } else if (entry.Type >= 252 && entry.Type <= 254) { // APPEND entry.OffsetDelta = reader.ReadInt16(); var type = (short)entry.Type; for (int x = 251; x < type; x++) { var item = new VerificationTypeInfo(); item.Read(reader); entry.Locals.Add(item); } } else if (entry.Type == 255) { // FULL_FRAME entry.OffsetDelta = reader.ReadInt16(); short localCount = reader.ReadInt16(); for (int x = 0; x < localCount; x++) { var item = new VerificationTypeInfo(); item.Read(reader); entry.Locals.Add(item); } short stackCount = reader.ReadInt16(); for (int x = 0; x < stackCount; x++) { var item = new VerificationTypeInfo(); item.Read(reader); entry.Stack.Add(item); } } Entries.Add(entry); } return this; }