private void POPLIST_Handler(Instruction instruction) { runtimeVerify(ProtoCore.DSASM.AddressType.Int == instruction.op1.optype); int depth = (int)instruction.op1.opdata; runtimeVerify(ProtoCore.DSASM.AddressType.Int == instruction.op2.optype); int scope = (int)instruction.op2.opdata; runtimeVerify(ProtoCore.DSASM.AddressType.BlockIndex == instruction.op3.optype); int blockId = (int)instruction.op3.opdata; // TODO(Jun/Jiong): Find a more reliable way to update the current block Id //core.DebugProps.CurrentBlockId = blockId; DSASM.RTSymbol[] listInfo = new RTSymbol[depth]; for (int n = 0; n < depth; ++n) { listInfo[n].Sv = rmem.Pop(); if (listInfo[n].Sv.optype == AddressType.StaticMemVarIndex) { StackValue block = rmem.Pop(); Validity.Assert(block.optype == AddressType.BlockIndex); listInfo[n].BlockId = (int)block.opdata; } int dim = (int)rmem.Pop().opdata; if (dim == 0) listInfo[n].Dimlist = null; else listInfo[n].Dimlist = new int[dim]; for (int d = 0; d < dim; ++d) { listInfo[n].Dimlist[d] = (int)rmem.Pop().opdata; } } // Handle depth until one before the last pointer StackValue finalPointer = StackValue.Null; int classsccope = (int)listInfo.Last().Sv.metaData.type; for (int n = listInfo.Length - 1; n >= 1; --n) { if (n == listInfo.Length - 1) finalPointer = listInfo[n].Sv; else { //resolve dynamic reference if (listInfo[n].Sv.optype == AddressType.Dynamic) { classsccope = (int)listInfo[n + 1].Sv.metaData.type; bool succeeded = ProcessDynamicVariable((listInfo[n].Dimlist != null), ref listInfo[n].Sv, classsccope); //if the identifier is unbounded. Push null if (!succeeded) { finalPointer = StackValue.Null; break; } } if (listInfo[n].Sv.optype == AddressType.StaticMemVarIndex) finalPointer = listInfo[n].Sv = GetOperandData(blockId, listInfo[n].Sv, new StackValue()); else finalPointer = listInfo[n].Sv = core.Heap.Heaplist[(int)finalPointer.opdata].Stack[(int)listInfo[n].Sv.opdata]; } if (listInfo[n].Dimlist != null) { for (int d = listInfo[n].Dimlist.Length - 1; d >= 0; --d) { finalPointer = listInfo[n].Sv = core.Heap.Heaplist[(int)finalPointer.opdata].GetValue(listInfo[n].Dimlist[d], core); } } } // Handle the last pointer StackValue tryPointer = StackValue.Null; StackValue data = rmem.Pop(); GCRetain(data); if (finalPointer.optype != AddressType.Null) { if (listInfo[0].Sv.optype == AddressType.Dynamic) { classsccope = (int)listInfo[1].Sv.metaData.type; bool succeeded = ProcessDynamicVariable((listInfo[0].Dimlist != null), ref listInfo[0].Sv, classsccope); //if the identifier is unbounded. Push null if (!succeeded) { tryPointer = StackValue.Null; } else { if (listInfo[0].Sv.optype == AddressType.StaticMemVarIndex) { SetOperandData(listInfo[0].Sv, data, listInfo[0].BlockId); ++pc; return; } tryPointer = core.Heap.Heaplist[(int)finalPointer.opdata].Stack[listInfo[0].Sv.opdata]; } } else if (listInfo[0].Sv.optype == AddressType.StaticMemVarIndex) { SetOperandData(listInfo[0].Sv, data, listInfo[0].BlockId); ++pc; return; } else { tryPointer = core.Heap.Heaplist[(int)finalPointer.opdata].Stack[listInfo[0].Sv.opdata]; } } else { tryPointer = StackValue.Null; } if (listInfo[0].Dimlist != null) { finalPointer = tryPointer; for (int d = listInfo[0].Dimlist.Length - 1; d >= 1; --d) finalPointer = core.Heap.Heaplist[(int)finalPointer.opdata].GetValue(listInfo[0].Dimlist[d], core); tryPointer = core.Heap.Heaplist[(int)finalPointer.opdata].GetValue(listInfo[0].Dimlist[0], core); } if (tryPointer.optype == AddressType.Null) { //do nothing } else if (core.Heap.Heaplist[(int)tryPointer.opdata].Stack.Length == 1 && core.Heap.Heaplist[(int)tryPointer.opdata].Stack[0].optype != AddressType.Pointer && core.Heap.Heaplist[(int)tryPointer.opdata].Stack[0].optype != AddressType.ArrayPointer) { // TODO Jun: // Spawn GC here lock (core.Heap.cslock) { // Setting a primitive DX = core.Heap.Heaplist[(int)tryPointer.opdata].Stack[0]; core.Heap.Heaplist[(int)tryPointer.opdata].Stack[0] = data; // GCPointer(DX); No need to spawn GC here, the data been replaced is not a pointer or array } } else if (finalPointer.optype == AddressType.Pointer || data.optype == AddressType.Null) { if (data.optype == AddressType.Null) { int ptr = core.Heap.Allocate(1); lock (core.Heap.cslock) { core.Heap.Heaplist[ptr].Stack = new[] { data }; data = StackValue.BuildPointer(ptr); // TODO Jun/Jiong, write test case for this GCRetain(data); } } lock (core.Heap.cslock) { // Setting a pointer int idx = (int)listInfo[0].Sv.opdata; DX = ArrayUtils.GetValueFromIndex(finalPointer, idx, core); GCRelease(DX); core.Heap.Heaplist[(int)finalPointer.opdata].Stack[listInfo[0].Sv.opdata] = data; } } else { // TODO Jun: // Spawn GC here runtimeVerify(finalPointer.optype == AddressType.ArrayPointer); lock (core.Heap.cslock) { // Setting an array DX = core.Heap.Heaplist[(int)finalPointer.opdata].GetValue(listInfo[0].Dimlist[0], core); GCRelease(DX); core.Heap.Heaplist[(int)finalPointer.opdata].SetValue(listInfo[0].Dimlist[0], data); } } //List<int> pointerList = new List<int>(); //for (int n = 0; n < depth; ++n) //{ // StackValue sv = rmem.Pop(); // runtimeVerify(ProtoCore.DSASM.AddressType.Pointer == sv.optype); // pointerList.Add((int)sv.opdata); // // TODO Jun: Support popping to a list of indexed arrays // // a.b[0].c[1] = 10; // StackValue svDim = rmem.Pop(); // runtimeVerify(AddressType.ArrayDim == svDim.optype); // int dimensions = (int)svDim.opdata; // for (int i = 0; i < dimensions; ++i) // { // Validity.Assert(false, "To implement: Indexing into function calls."); // } //} //pointerList.Reverse(); //if (ProtoCore.DSASM.Constants.kGlobalScope == scope) //{ // StackValue data = rmem.Pop(); // int n = 0; // int ptr = pointerList[0]; // for (n = 1; n < pointerList.Count - 1; ++n) // { // ptr = (int)core.heap.heaplist[ptr].stack[pointerList[n]].opdata; // } // // If the src data is a pointer then make the last variable in the resolution op point to that. // // Otherwise move to the pointed location and assign the source data (a primitive) // if (AddressType.Pointer == data.optype) // { // // TODO Jun: // // Spawn GC here // lock (core.heap.cslock) // { // core.heap.heaplist[ptr].stack[pointerList[n - 1]] = data; // } // } // else // { // ptr = (int)core.heap.heaplist[ptr].stack[pointerList[n]].opdata; // lock (core.heap.cslock) // { // core.heap.heaplist[ptr].stack[0] = data; // } // } //} ++pc; return; }
private void POPLIST_Handler(Instruction instruction) { runtimeVerify(instruction.op1.IsInteger); int depth = (int)instruction.op1.opdata; runtimeVerify(instruction.op2.IsInteger); runtimeVerify(instruction.op3.IsBlockIndex); int blockId = (int)instruction.op3.opdata; // TODO(Jun/Jiong): Find a more reliable way to update the current block Id //runtimeCore.DebugProps.CurrentBlockId = blockId; RTSymbol[] listInfo = new RTSymbol[depth]; for (int n = 0; n < depth; ++n) { listInfo[n].Sv = rmem.Pop(); if (listInfo[n].Sv.IsStaticVariableIndex) { StackValue block = rmem.Pop(); Validity.Assert(block.IsBlockIndex); listInfo[n].BlockId = (int)block.opdata; } int dim = (int)rmem.Pop().opdata; if (dim == 0) listInfo[n].Dimlist = null; else listInfo[n].Dimlist = new int[dim]; for (int d = 0; d < dim; ++d) { listInfo[n].Dimlist[d] = (int)rmem.Pop().opdata; } } // Handle depth until one before the last pointer StackValue finalPointer = StackValue.Null; int classsccope = listInfo.Last().Sv.metaData.type; for (int n = listInfo.Length - 1; n >= 1; --n) { if (n == listInfo.Length - 1) finalPointer = listInfo[n].Sv; else { //resolve dynamic reference if (listInfo[n].Sv.IsDynamic) { classsccope = listInfo[n + 1].Sv.metaData.type; bool succeeded = ProcessDynamicVariable((listInfo[n].Dimlist != null), ref listInfo[n].Sv, classsccope); //if the identifier is unbounded. Push null if (!succeeded) { finalPointer = StackValue.Null; break; } } if (listInfo[n].Sv.IsStaticVariableIndex) finalPointer = listInfo[n].Sv = GetOperandData(blockId, listInfo[n].Sv, new StackValue()); else finalPointer = listInfo[n].Sv = rmem.Heap.ToHeapObject<DSObject>(finalPointer).GetValueFromIndex((int)listInfo[n].Sv.opdata, runtimeCore); } if (listInfo[n].Dimlist != null) { for (int d = listInfo[n].Dimlist.Length - 1; d >= 0; --d) { finalPointer = listInfo[n].Sv = rmem.Heap.ToHeapObject<DSObject>(finalPointer).GetValueFromIndex(listInfo[n].Dimlist[d], runtimeCore); } } } // Handle the last pointer StackValue tryPointer = StackValue.Null; StackValue data = rmem.Pop(); if (!finalPointer.IsNull) { StackValue rtSymbol = listInfo[0].Sv; if (rtSymbol.IsDynamic) { classsccope = listInfo[1].Sv.metaData.type; bool succeeded = ProcessDynamicVariable((listInfo[0].Dimlist != null), ref rtSymbol, classsccope); //if the identifier is unbounded. Push null if (!succeeded) { tryPointer = StackValue.Null; } else { if (rtSymbol.IsStaticVariableIndex) { SetOperandData(rtSymbol, data, listInfo[0].BlockId); ++pc; return; } tryPointer = rmem.Heap.ToHeapObject<DSObject>(finalPointer).GetValueFromIndex((int)rtSymbol.opdata, runtimeCore); } } else if (rtSymbol.IsStaticVariableIndex) { SetOperandData(rtSymbol, data, listInfo[0].BlockId); ++pc; return; } else { tryPointer = rmem.Heap.ToHeapObject<DSObject>(finalPointer).GetValueFromIndex((int)rtSymbol.opdata, runtimeCore); } } else { tryPointer = StackValue.Null; } if (listInfo[0].Dimlist != null) { finalPointer = tryPointer; for (int d = listInfo[0].Dimlist.Length - 1; d >= 1; --d) finalPointer = rmem.Heap.ToHeapObject<DSObject>(finalPointer).GetValueFromIndex(listInfo[0].Dimlist[d], runtimeCore); tryPointer = rmem.Heap.ToHeapObject<DSObject>(finalPointer).GetValueFromIndex(listInfo[0].Dimlist[0], runtimeCore); } if (tryPointer.IsNull) { //do nothing } else { var pointer = rmem.Heap.ToHeapObject<DSObject>(tryPointer); var firstItem = pointer.Count == 1 ? pointer.GetValueFromIndex(0, runtimeCore) : StackValue.Null; if (pointer.Count == 1 && !firstItem.IsPointer && !firstItem.IsArray) { // TODO Jun: // Spawn GC here // Setting a primitive DX = firstItem; pointer.SetValueAtIndex(0, data, null); } else if (finalPointer.IsPointer || data.IsNull) { if (data.IsNull) { StackValue ptr = rmem.Heap.AllocatePointer(new[] { data }); } // Setting a pointer int idx = (int)listInfo[0].Sv.opdata; DSObject dsObject = rmem.Heap.ToHeapObject<DSObject>(finalPointer); DX = dsObject.GetValueFromIndex(idx, runtimeCore); dsObject.SetValueAtIndex(idx, data, runtimeCore); } else { // TODO Jun: // Spawn GC here runtimeVerify(finalPointer.IsArray); // Setting an array var finalPointerArray = rmem.Heap.ToHeapObject<DSArray>(finalPointer); var index = listInfo[0].Dimlist[0]; DX = finalPointerArray.GetValueFromIndex(index, runtimeCore); finalPointerArray.SetValueForIndex(index, data, runtimeCore); } } ++pc; }
private StackValue GetFinalPointer(int depth, bool isDotFunctionBody = false) { RTSymbol[] rtSymbols = new RTSymbol[depth]; bool isInvalidIdentList = false; for (int i = depth - 1; i >= 0; --i) { // Get the symbol rtSymbols[i].Sv = rmem.Pop(); AddressType optype = rtSymbols[i].Sv.optype; if (!isDotFunctionBody && optype != AddressType.Pointer && optype != AddressType.ArrayPointer && optype != AddressType.Dynamic && optype != AddressType.ClassIndex) { isInvalidIdentList = true; } if (isDotFunctionBody && i != 0) { StackValue dimSv = rmem.Pop(); dimSv.optype = AddressType.ArrayDim; rmem.Push(dimSv); } if (rmem.Stack[rmem.Stack.Count - 1].IsArrayDimension) { // Get the number of demension pushed StackValue svDim = rmem.Pop(); int dimensions = (int)svDim.opdata; if (dimensions > 0) { if (isDotFunctionBody && i != 0) { //push its dimension value StackValue dimValArraySv = rmem.Pop(); var dimValArray = rmem.Heap.ToHeapObject<DSArray>(dimValArraySv); foreach (StackValue dimValSv in dimValArray.Values) { rmem.Push(dimValSv); } } // Pop off each dimension rtSymbols[i].Dimlist = new int[dimensions]; for (int j = dimensions - 1; j >= 0; --j) { svDim = rmem.Pop(); if (!svDim.IsInteger) { isInvalidIdentList = true; } rtSymbols[i].Dimlist[j] = (int)svDim.opdata; } } else if (isDotFunctionBody && i != 0) { rmem.Pop(); //pop the rhsDimExprList (arrayPointer) } } } if (isInvalidIdentList) { return StackValue.Null; } if (isDotFunctionBody) { if (rtSymbols[0].Sv.IsInteger) // static, class UID { // if static, the opdata of rtSymbols[0] is not used, no need to bother that int type = (int)rtSymbols[0].Sv.opdata; rtSymbols[0].Sv.metaData.type = type; rtSymbols[0].Sv.optype = AddressType.ClassIndex; } rtSymbols[1].Sv.optype = AddressType.Dynamic; } if (1 == depth) { return GetIndexedArray(rtSymbols[0].Sv, rtSymbols[0].Dimlist); } // Get first stackvalue of the first elemnt in the ident list // Get its indexed value rtSymbols[0].Sv = GetIndexedArray(rtSymbols[0].Sv, rtSymbols[0].Dimlist); //If the value of the first identifier is null, return null stack value if (rtSymbols[0].Sv.IsNull) { return rtSymbols[0].Sv; } int index = -1; StackValue ptr = rtSymbols[0].Sv; // Traverse the heap until the last pointer int n; int classsccope = rtSymbols[0].Sv.metaData.type; for (n = 1; n < rtSymbols.Length; ++n) { // Index into the current pointer // 'index' is the index of the member variable // class f { // x : var; y : var // index of x = 0, y = 1 // } //resolve dynamic reference if (rtSymbols[n].Sv.IsDynamic) { classsccope = rtSymbols[n - 1].Sv.metaData.type; bool succeeded = ProcessDynamicVariable((rtSymbols[n].Dimlist != null), ref rtSymbols[n].Sv, classsccope); //if the identifier is unbounded. Push null if (!succeeded) { return StackValue.Null; } } if (rtSymbols[n].Sv.IsStaticVariableIndex) { StackValue op2 = StackValue.BuildClassIndex(Constants.kInvalidIndex); rtSymbols[n].Sv = GetOperandData(0, rtSymbols[n].Sv, op2); } else { index = (int)rtSymbols[n].Sv.opdata; rtSymbols[n].Sv = rmem.Heap.ToHeapObject<DSObject>(ptr).GetValueFromIndex(index, runtimeCore); } // Once a pointer to the member is retrieved, get its indexed value rtSymbols[n].Sv = GetIndexedArray(rtSymbols[n].Sv, rtSymbols[n].Dimlist); ptr = rtSymbols[n].Sv; } // Check the last pointer StackValue opVal = rtSymbols[n - 1].Sv; if (opVal.IsPointer || opVal.IsInvalid) { // Determine if we still need to move one more time on the heap // Peek into the pointed data using nextPtr. // If nextPtr is not a pointer (a primitive) then return the data at nextPtr StackValue nextPtr = opVal; var data = rmem.Heap.ToHeapObject<DSObject>(nextPtr).GetValueFromIndex(0, runtimeCore); bool isActualData = !data.IsPointer && !data.IsArray && !data.IsInvalid; if (isActualData) { // Move one more and get the value at the first heapstack opVal = data; } } return opVal; }
private void POPLIST_Handler(Instruction instruction) { runtimeVerify(instruction.op1.IsInteger); int depth = (int)instruction.op1.opdata; runtimeVerify(instruction.op2.IsInteger); runtimeVerify(instruction.op3.IsBlockIndex); int blockId = (int)instruction.op3.opdata; // TODO(Jun/Jiong): Find a more reliable way to update the current block Id //core.DebugProps.CurrentBlockId = blockId; RTSymbol[] listInfo = new RTSymbol[depth]; for (int n = 0; n < depth; ++n) { listInfo[n].Sv = rmem.Pop(); if (listInfo[n].Sv.IsStaticVariableIndex) { StackValue block = rmem.Pop(); Validity.Assert(block.IsBlockIndex); listInfo[n].BlockId = (int)block.opdata; } int dim = (int)rmem.Pop().opdata; if (dim == 0) listInfo[n].Dimlist = null; else listInfo[n].Dimlist = new int[dim]; for (int d = 0; d < dim; ++d) { listInfo[n].Dimlist[d] = (int)rmem.Pop().opdata; } } // Handle depth until one before the last pointer StackValue finalPointer = StackValue.Null; int classsccope = listInfo.Last().Sv.metaData.type; for (int n = listInfo.Length - 1; n >= 1; --n) { if (n == listInfo.Length - 1) finalPointer = listInfo[n].Sv; else { //resolve dynamic reference if (listInfo[n].Sv.IsDynamic) { classsccope = listInfo[n + 1].Sv.metaData.type; bool succeeded = ProcessDynamicVariable((listInfo[n].Dimlist != null), ref listInfo[n].Sv, classsccope); //if the identifier is unbounded. Push null if (!succeeded) { finalPointer = StackValue.Null; break; } } if (listInfo[n].Sv.IsStaticVariableIndex) finalPointer = listInfo[n].Sv = GetOperandData(blockId, listInfo[n].Sv, new StackValue()); else finalPointer = listInfo[n].Sv = core.Heap.GetHeapElement(finalPointer).Stack[(int)listInfo[n].Sv.opdata]; } if (listInfo[n].Dimlist != null) { for (int d = listInfo[n].Dimlist.Length - 1; d >= 0; --d) { finalPointer = listInfo[n].Sv = core.Heap.GetHeapElement(finalPointer).GetValue(listInfo[n].Dimlist[d], core); } } } // Handle the last pointer StackValue tryPointer = StackValue.Null; StackValue data = rmem.Pop(); GCRetain(data); if (!finalPointer.IsNull) { if (listInfo[0].Sv.IsDynamic) { classsccope = listInfo[1].Sv.metaData.type; bool succeeded = ProcessDynamicVariable((listInfo[0].Dimlist != null), ref listInfo[0].Sv, classsccope); //if the identifier is unbounded. Push null if (!succeeded) { tryPointer = StackValue.Null; } else { if (listInfo[0].Sv.IsStaticVariableIndex) { SetOperandData(listInfo[0].Sv, data, listInfo[0].BlockId); ++pc; return; } tryPointer = core.Heap.GetHeapElement(finalPointer).Stack[listInfo[0].Sv.opdata]; } } else if (listInfo[0].Sv.IsStaticVariableIndex) { SetOperandData(listInfo[0].Sv, data, listInfo[0].BlockId); ++pc; return; } else { tryPointer = core.Heap.GetHeapElement(finalPointer).Stack[listInfo[0].Sv.opdata]; } } else { tryPointer = StackValue.Null; } if (listInfo[0].Dimlist != null) { finalPointer = tryPointer; for (int d = listInfo[0].Dimlist.Length - 1; d >= 1; --d) finalPointer = core.Heap.GetHeapElement(finalPointer).GetValue(listInfo[0].Dimlist[d], core); tryPointer = core.Heap.GetHeapElement(finalPointer).GetValue(listInfo[0].Dimlist[0], core); } if (tryPointer.IsNull) { //do nothing } else if (core.Heap.GetHeapElement(tryPointer).Stack.Length == 1 && !core.Heap.GetHeapElement(tryPointer).Stack[0].IsPointer && !core.Heap.GetHeapElement(tryPointer).Stack[0].IsArray) { // TODO Jun: // Spawn GC here // Setting a primitive DX = core.Heap.GetHeapElement(tryPointer).Stack[0]; core.Heap.GetHeapElement(tryPointer).Stack[0] = data; } else if (finalPointer.IsPointer || data.IsNull) { if (data.IsNull) { StackValue ptr = core.Heap.AllocatePointer(new [] { data }); GCRetain(data); } // Setting a pointer int idx = (int)listInfo[0].Sv.opdata; DX = ArrayUtils.GetValueFromIndex(finalPointer, idx, core); GCRelease(DX); core.Heap.GetHeapElement(finalPointer).Stack[listInfo[0].Sv.opdata] = data; } else { // TODO Jun: // Spawn GC here runtimeVerify(finalPointer.IsArray); // Setting an array DX = core.Heap.GetHeapElement(finalPointer).GetValue(listInfo[0].Dimlist[0], core); GCRelease(DX); core.Heap.GetHeapElement(finalPointer).SetValue(listInfo[0].Dimlist[0], data); } ++pc; }