|
//------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------
namespace System.ServiceModel.Dispatcher
{
using System;
using System.Runtime;
internal struct StackFrame
{
internal int basePtr;
internal int endPtr;
#if NO
internal StackFrame(int basePtr)
{
Fx.Assert(basePtr >= 0, "");
this.basePtr = basePtr;
this.endPtr = this.basePtr - 1;
}
internal StackFrame(int basePtr, int count)
{
Fx.Assert(basePtr >= 0, "");
this.basePtr = basePtr;
this.endPtr = basePtr + count - 1;
}
#endif
internal int Count
{
get
{
return this.endPtr - this.basePtr + 1;
}
}
internal int EndPtr
{
#if NO
get
{
return this.endPtr;
}
#endif
set
{
Fx.Assert(value >= this.basePtr, "");
this.endPtr = value;
}
}
#if NO
internal void Clear()
{
this.endPtr = this.basePtr - 1;
}
#endif
internal int this[int offset]
{
get
{
Fx.Assert(this.IsValidPtr(this.basePtr + offset), "");
return this.basePtr + offset;
}
}
#if NO
internal void Set(int basePtr)
{
Fx.Assert(basePtr >= 0, "");
this.basePtr = basePtr;
this.endPtr = this.basePtr - 1;
}
#endif
internal bool IsValidPtr(int ptr)
{
return (ptr >= this.basePtr && ptr <= this.endPtr);
}
}
internal struct StackRegion
{
internal QueryRange bounds;
internal int stackPtr;
internal StackRegion(QueryRange bounds)
{
this.bounds = bounds;
this.stackPtr = bounds.start - 1;
}
#if NO
internal StackRegion(QueryRange bounds, int stackPtr)
{
Fx.Assert(bounds.IsInRange(stackPtr), "");
this.bounds = bounds;
this.stackPtr = stackPtr;
}
#endif
internal int Count
{
get
{
return this.stackPtr - this.bounds.start + 1;
}
}
#if NO
internal bool IsReady
{
get
{
return this.bounds.IsNotEmpty;
}
}
#endif
internal bool NeedsGrowth
{
get
{
return (this.stackPtr > this.bounds.end);
}
}
internal void Clear()
{
this.stackPtr = this.bounds.start - 1;
}
internal void Grow(int growBy)
{
this.bounds.end += growBy;
}
internal bool IsValidStackPtr()
{
return this.bounds.IsInRange(this.stackPtr);
}
internal bool IsValidStackPtr(int stackPtr)
{
return this.bounds.IsInRange(stackPtr);
}
#if NO
internal void Set(int start, int end)
{
this.bounds.Set(start, end);
this.stackPtr += start;
}
#endif
internal void Shift(int shiftBy)
{
this.bounds.Shift(shiftBy);
this.stackPtr += shiftBy;
}
}
// The eval stack as well as all its contained data structures are STRUCTs
// fast to allocate
internal struct EvalStack
{
internal QueryBuffer<Value> buffer;
internal StackRegion frames;
internal StackRegion stack;
internal const int DefaultSize = 2;
internal bool contextOnTopOfStack;
internal EvalStack(int frameCapacity, int stackCapacity)
{
Fx.Assert(frameCapacity >= 0 && stackCapacity >= 0, "");
// All structs! Cost of allocation is relatively mild...
this.buffer = new QueryBuffer<Value>(frameCapacity + stackCapacity);
this.stack = new StackRegion(new QueryRange(0, stackCapacity - 1));
this.buffer.Reserve(stackCapacity);
this.frames = new StackRegion(new QueryRange(stackCapacity, stackCapacity + frameCapacity - 1));
this.buffer.Reserve(frameCapacity);
this.contextOnTopOfStack = false;
}
#if NO
internal EvalStack(ref EvalStack stack)
{
this.buffer = new QueryBuffer<Value>(stack.buffer);
this.stackCapacity = stack.stackCapacity;
this.frameCapacity = stack.frameCapacity;
this.stack = stack.stack;
this.frames = stack.frames;
}
#endif
internal Value[] Buffer
{
get
{
return this.buffer.buffer;
}
}
#if NO
internal int FrameCount
{
get
{
return this.frames.Count;
}
}
internal int FramePtr
{
get
{
return this.frames.stackPtr;
}
}
#endif
internal StackFrame this[int frameIndex]
{
get
{
return this.buffer.buffer[this.frames.stackPtr - frameIndex].Frame;
}
}
#if NO
internal bool IsReady
{
get
{
return (this.buffer.count > 0);
}
}
#endif
internal StackFrame SecondArg
{
get
{
return this[1];
}
}
#if NO
internal int StackPtr
{
get
{
return this.stack.stackPtr;
}
}
#endif
internal StackFrame TopArg
{
get
{
return this[0];
}
}
internal void Clear()
{
this.stack.Clear();
this.frames.Clear();
this.contextOnTopOfStack = false;
}
internal void CopyFrom(ref EvalStack stack)
{
this.buffer.CopyFrom(ref stack.buffer);
this.frames = stack.frames;
this.stack = stack.stack;
this.contextOnTopOfStack = stack.contextOnTopOfStack;
}
internal int CalculateNodecount()
{
if (this.stack.stackPtr < 0)
{
return 0;
}
StackFrame topFrame = this.TopArg;
int count = 0;
for (int i = topFrame.basePtr; i <= topFrame.endPtr; ++i)
{
Fx.Assert(this.buffer[i].IsType(ValueDataType.Sequence), "");
count += this.buffer[i].NodeCount;
}
return count;
}
#if NO
internal void Erase()
{
this.buffer.Erase();
}
#endif
void GrowFrames()
{
int growBy = this.frames.Count;
this.buffer.ReserveAt(this.frames.bounds.end + 1, growBy);
this.frames.Grow(growBy);
}
void GrowStack(int growthNeeded)
{
int growBy = this.stack.bounds.Count;
if (growthNeeded > growBy)
{
growBy = growthNeeded;
}
this.buffer.ReserveAt(this.stack.bounds.end + 1, growBy);
this.stack.Grow(growBy);
this.frames.Shift(growBy);
}
#if NO
internal void Init()
{
this.buffer.Reserve(this.stackCapacity);
this.stack.Set(0, stackCapacity - 1);
this.buffer.Reserve(this.frameCapacity);
this.frames.Set(stackCapacity, stackCapacity + frameCapacity - 1);
}
internal void Init(Value[] buffer, int stackCapacity, int frameCapacity)
{
Fx.Assert(null != buffer, "");
this.stackCapacity = stackCapacity;
this.frameCapacity = frameCapacity;
this.buffer = new QueryBuffer<Value>(buffer);
this.stack = new StackRegion(new QueryRange(0, stackCapacity - 1));
this.buffer.Reserve(stackCapacity);
this.frames = new StackRegion(new QueryRange(stackCapacity, stackCapacity + frameCapacity - 1));
this.buffer.Reserve(frameCapacity);
}
#endif
internal bool InUse
{
get
{
if (contextOnTopOfStack)
return (this.frames.Count > 1);
else
return (this.frames.Count > 0);
}
}
internal bool PeekBoolean(int index)
{
Fx.Assert(this.stack.IsValidStackPtr(index), "");
return this.buffer.buffer[index].GetBoolean();
}
internal double PeekDouble(int index)
{
Fx.Assert(this.stack.IsValidStackPtr(index), "");
return this.buffer.buffer[index].GetDouble();
}
#if NO
internal int PeekInteger(int index)
{
Fx.Assert(this.stack.IsValidStackPtr(index), "");
return (int)this.buffer.buffer[index].GetDouble();
}
#endif
internal NodeSequence PeekSequence(int index)
{
Fx.Assert(this.stack.IsValidStackPtr(index), "");
return this.buffer.buffer[index].GetSequence();
}
internal string PeekString(int index)
{
Fx.Assert(this.stack.IsValidStackPtr(index), "");
return this.buffer.buffer[index].GetString();
}
#if NO
internal void Pop()
{
this.stack.stackPtr--;
Fx.Assert(this.stack.IsValidStackPtr(), "");
this.buffer.buffer[this.frames.stackPtr].FrameEndPtr = this.stack.stackPtr;
}
internal void PopFrame()
{
Fx.Assert(this.frames.IsValidStackPtr(), "");
this.stack.stackPtr = this.buffer.buffer[this.frames.stackPtr].StackPtr;
this.frames.stackPtr--;
}
#endif
internal void PopFrame(ProcessingContext context)
{
Fx.Assert(this.frames.IsValidStackPtr(), "");
StackFrame topArg = this.TopArg;
for (int i = topArg.basePtr; i <= topArg.endPtr; ++i)
{
this.buffer.buffer[i].Clear(context);
}
this.stack.stackPtr = topArg.basePtr - 1;
this.frames.stackPtr--;
}
internal void PushFrame()
{
this.frames.stackPtr++;
if (this.frames.NeedsGrowth)
{
this.GrowFrames();
}
//
// The first element in the new frame will be the NEXT item pushed onto the stack
// We save offsets because stacks may get moved and repositioned
//
this.buffer.buffer[this.frames.stackPtr].StartFrame(this.stack.stackPtr);
}
internal void PopSequenceFrameTo(ref EvalStack dest)
{
StackFrame topFrame = this.TopArg;
dest.PushFrame();
int argCount = topFrame.Count;
switch (argCount)
{
default:
dest.Push(this.buffer.buffer, topFrame.basePtr, argCount);
break;
case 0:
break;
case 1:
dest.Push(this.buffer.buffer[topFrame.basePtr].Sequence);
break;
}
// Pop original fame
this.stack.stackPtr = topFrame.basePtr - 1;
this.frames.stackPtr--;
}
#if NO
internal void Push()
{
this.stack.stackPtr++;
if (this.stack.NeedsGrowth)
{
this.GrowStack(1);
}
this.buffer.buffer[this.frames.stackPtr].FrameEndPtr = this.stack.stackPtr;
}
internal void Push(int count)
{
this.stack.stackPtr += count;
if (this.stack.NeedsGrowth)
{
this.GrowStack(count);
}
this.buffer.buffer[this.frames.stackPtr].FrameEndPtr = this.stack.stackPtr;
}
#endif
internal void Push(string val)
{
this.stack.stackPtr++;
if (this.stack.NeedsGrowth)
{
this.GrowStack(1);
}
this.buffer.buffer[this.stack.stackPtr].String = val;
this.buffer.buffer[this.frames.stackPtr].FrameEndPtr = this.stack.stackPtr;
}
internal void Push(string val, int addCount)
{
int stackPtr = this.stack.stackPtr;
this.stack.stackPtr += addCount;
if (this.stack.NeedsGrowth)
{
this.GrowStack(addCount);
}
int stackMax = stackPtr + addCount;
while (stackPtr < stackMax)
{
this.buffer.buffer[++stackPtr].String = val;
}
this.buffer.buffer[this.frames.stackPtr].FrameEndPtr = this.stack.stackPtr;
}
internal void Push(bool val)
{
this.stack.stackPtr++;
if (this.stack.NeedsGrowth)
{
this.GrowStack(1);
}
this.buffer.buffer[this.stack.stackPtr].Boolean = val;
this.buffer.buffer[this.frames.stackPtr].FrameEndPtr = this.stack.stackPtr;
}
internal void Push(bool val, int addCount)
{
int stackPtr = this.stack.stackPtr;
this.stack.stackPtr += addCount;
if (this.stack.NeedsGrowth)
{
this.GrowStack(addCount);
}
int stackMax = stackPtr + addCount;
while (stackPtr < stackMax)
{
this.buffer.buffer[++stackPtr].Boolean = val;
}
this.buffer.buffer[this.frames.stackPtr].FrameEndPtr = this.stack.stackPtr;
}
internal void Push(double val)
{
this.stack.stackPtr++;
if (this.stack.NeedsGrowth)
{
this.GrowStack(1);
}
this.buffer.buffer[this.stack.stackPtr].Double = val;
this.buffer.buffer[this.frames.stackPtr].FrameEndPtr = this.stack.stackPtr;
}
internal void Push(double val, int addCount)
{
int stackPtr = this.stack.stackPtr;
this.stack.stackPtr += addCount;
if (this.stack.NeedsGrowth)
{
this.GrowStack(addCount);
}
int stackMax = stackPtr + addCount;
while (stackPtr < stackMax)
{
this.buffer.buffer[++stackPtr].Double = val;
}
this.buffer.buffer[this.frames.stackPtr].FrameEndPtr = this.stack.stackPtr;
}
internal void Push(NodeSequence val)
{
this.stack.stackPtr++;
if (this.stack.NeedsGrowth)
{
this.GrowStack(1);
}
this.buffer.buffer[this.stack.stackPtr].Sequence = val;
this.buffer.buffer[this.frames.stackPtr].FrameEndPtr = this.stack.stackPtr;
}
internal void Push(NodeSequence val, int addCount)
{
// One of the addCount refs was added by the call to CreateSequence
val.refCount += addCount - 1;
int stackPtr = this.stack.stackPtr;
this.stack.stackPtr += addCount;
if (this.stack.NeedsGrowth)
{
this.GrowStack(addCount);
}
int stackMax = stackPtr + addCount;
while (stackPtr < stackMax)
{
this.buffer.buffer[++stackPtr].Sequence = val;
}
this.buffer.buffer[this.frames.stackPtr].FrameEndPtr = this.stack.stackPtr;
}
internal void Push(Value[] buffer, int startAt, int addCount)
{
if (addCount > 0)
{
int stackPtr = this.stack.stackPtr + 1;
this.stack.stackPtr += addCount;
if (this.stack.NeedsGrowth)
{
this.GrowStack(addCount);
}
if (1 == addCount)
{
this.buffer.buffer[stackPtr] = buffer[startAt];
}
else
{
Array.Copy(buffer, startAt, this.buffer.buffer, stackPtr, addCount);
}
this.buffer.buffer[this.frames.stackPtr].FrameEndPtr = this.stack.stackPtr;
}
}
#if NO
internal void Push(ref EvalStack source)
{
this.Push(source.buffer.buffer, source.stack.bounds.start, source.frames.bounds.end + 1);
}
#endif
internal void ReplaceAt(int index, NodeSequence seq)
{
Fx.Assert(this.stack.IsValidStackPtr(index) && this.buffer.buffer[index].IsType(ValueDataType.Sequence), "");
this.buffer.buffer[index].Sequence = seq;
}
internal void SetValue(ProcessingContext context, int index, bool val)
{
Fx.Assert(this.stack.IsValidStackPtr(index), "");
this.buffer.buffer[index].Update(context, val);
}
internal void SetValue(ProcessingContext context, int index, double val)
{
Fx.Assert(this.stack.IsValidStackPtr(index), "");
this.buffer.buffer[index].Update(context, val);
}
internal void SetValue(ProcessingContext context, int index, string val)
{
Fx.Assert(this.stack.IsValidStackPtr(index), "");
this.buffer.buffer[index].Update(context, val);
}
internal void SetValue(ProcessingContext context, int index, NodeSequence val)
{
Fx.Assert(this.stack.IsValidStackPtr(index), "");
this.buffer.buffer[index].Update(context, val);
}
internal void TransferPositionsTo(ref EvalStack stack)
{
StackFrame arg = this.TopArg;
stack.PushFrame();
for (int i = arg.basePtr; i <= arg.endPtr; ++i)
{
NodeSequence seq = this.buffer.buffer[i].Sequence;
int nodeCount = seq.Count;
if ((this.stack.stackPtr + nodeCount) > this.stack.bounds.end)
{
this.GrowStack(nodeCount);
}
for (int n = 0; n < nodeCount; ++n)
{
stack.Push((double)seq.Items[n].Position);
}
}
}
internal void TransferSequenceSizeTo(ref EvalStack stack)
{
StackFrame arg = this.TopArg;
stack.PushFrame();
for (int i = arg.basePtr; i <= arg.endPtr; ++i)
{
NodeSequence seq = this.buffer.buffer[i].Sequence;
int nodeCount = seq.Count;
if ((this.stack.stackPtr + nodeCount) > this.stack.bounds.end)
{
this.GrowStack(nodeCount);
}
for (int n = 0; n < nodeCount; ++n)
{
stack.Push((double)NodeSequence.GetContextSize(seq, n));
}
}
}
#if NO
internal void Trim()
{
this.buffer.TrimToCount();
}
#endif
}
#if NO
internal struct BoundedStack<T>
{
QueryBuffer<T> buffer;
int maxSize;
internal BoundedStack(int capacity)
{
this.buffer = new QueryBuffer<T>(0);
this.maxSize = capacity;
}
internal bool HasItems
{
get
{
return (this.buffer.count > 0);
}
}
internal bool HasSpace
{
get
{
return (this.buffer.count < this.maxSize);
}
}
internal int MaxSize
{
get
{
return this.maxSize;
}
set
{
Fx.Assert(value >= 0, "");
this.maxSize = value;
if (value < this.buffer.count)
{
this.buffer.count = value;
this.buffer.TrimToCount();
}
}
}
internal T Pop()
{
return this.buffer.Pop();
}
internal void Push(T t)
{
if (this.buffer.count == this.maxSize)
{
return;
}
this.buffer.Push(t);
}
internal void Trim()
{
this.buffer.TrimToCount();
}
}
#endif
}
|