To protect your data, the CISO officer has suggested users to enable GitLab 2FA as soon as possible.

Commit f77642c3 authored by Kunshan Wang's avatar Kunshan Wang
Browse files

Configurable logging levels.

parent b3330486
......@@ -41,6 +41,8 @@ or::
losSize = 2*1024*1024,
globalSize = 4*1024*1024,
stackSize = 63*1024,
gcLog = "WARN",
vmLog = "INFO",
)
A ``MuCtx`` instance can be created from the ``MuVM`` object::
......@@ -162,6 +164,9 @@ else:
import _libmuprivpython3 as _priv
import ctypes, ctypes.util
import logging
logger = logging.getLogger(__name__)
_libc = ctypes.CDLL(ctypes.util.find_library("c"))
_libc.malloc.restype = ctypes.c_void_p
......@@ -921,7 +926,7 @@ def _initialize_methods(high_level_class, methods):
# make low-level struct field (function pointer)
low_level_restype = _to_low_level_type(restype)
low_level_argtypes = [_to_low_level_type(ty) for ty in argtypes]
print("Python binding:", name, low_level_restype, low_level_argtypes)
logger.debug("Python binding: %s :: %s %s", name, low_level_restype, low_level_argtypes)
funcptr = _funcptr(
low_level_restype, # return value
objtype_p, *low_level_argtypes # params. Start with a struct ptr
......@@ -1132,7 +1137,7 @@ class MuRefImpl2StartDLL(object):
self.dll = dll
def mu_refimpl2_new(self):
"""Create a MuVM instance using the default heap/global/stack sizes."""
"""Create a MuVM instance using the default configuration."""
ptr = self.dll.mu_refimpl2_new()
return MuVM(ptr, self)
......@@ -1144,6 +1149,15 @@ class MuRefImpl2StartDLL(object):
losSize: large object space size (bytes, must be 4096-byte aligned)
globalSize: global space size (bytes, must be 4096-byte aligned)
stackSize: stack size (bytes)
vmLog: log level for the micro VM
gcLog: log level fof the garbage collector
possible values for log levels (strings, case insensitive):
ALL, TRACE, DEBUG, INFO, WARN, ERROR, OFF
Setting to WARN will disable almost all logs. Set vmLog to INFO to see
the execution of each instruction; Set gcLog to DEBUG to see GC logs.
"""
conf = "".join("{}={}\n".format(k,v) for k,v in kwargs.items())
ptr = self.dll.mu_refimpl2_new_ex(_priv._encode(conf, "utf8"))
......
......@@ -12,39 +12,6 @@ import uvm.refimpl.mem.TypeSizes.Word
import uvm.refimpl.nat.NativeCallHelper
import uvm.staticanalysis.StaticAnalyzer
object GCConf {
val ReComment = """^\s*#.*$""".r
val ReBlank = """^\s*$""".r
val ReConf = """^\s*(\w+)=(\w+)\s*$""".r
def apply(confStr: String): GCConf = {
var sosSize = MicroVM.DEFAULT_SOS_SIZE
var losSize = MicroVM.DEFAULT_LOS_SIZE
var globalSize = MicroVM.DEFAULT_GLOBAL_SIZE
var stackSize = MicroVM.DEFAULT_GLOBAL_SIZE
confStr.lines foreach {
case ReComment() =>
case ReBlank() =>
case ReConf(key, value) => {
key match {
case "sosSize" => sosSize = value.toLong
case "losSize" => losSize = value.toLong
case "globalSize" => globalSize = value.toLong
case "stackSize" => stackSize = value.toLong
case _ => throw new UvmRefImplException("Unrecognized option %s".format(key))
}
}
}
new GCConf(sosSize, losSize, globalSize, stackSize)
}
}
class GCConf(
val sosSize: Word = MicroVM.DEFAULT_SOS_SIZE,
val losSize: Word = MicroVM.DEFAULT_LOS_SIZE,
val globalSize: Word = MicroVM.DEFAULT_GLOBAL_SIZE,
val stackSize: Word = MicroVM.DEFAULT_STACK_SIZE)
object MicroVM {
val DEFAULT_SOS_SIZE: Word = 2L * 1024L * 1024L; // 2MiB
val DEFAULT_LOS_SIZE: Word = 2L * 1024L * 1024L; // 2MiB
......@@ -54,23 +21,23 @@ object MicroVM {
val FIRST_CLIENT_USABLE_ID: Int = 65536
def apply(): MicroVM = {
val gcConf = new GCConf()
new MicroVM(gcConf)
val vmConf = new VMConf()
new MicroVM(vmConf)
}
def apply(confStr: String): MicroVM = {
val gcConf = GCConf(confStr)
new MicroVM(gcConf)
val vmConf = VMConf(confStr)
new MicroVM(vmConf)
}
}
class MicroVM(gcConf: GCConf) {
class MicroVM(vmConf: VMConf) {
// implicitly injected resources
private implicit val microVM = this
val globalBundle = new GlobalBundle()
val constantPool = new ConstantPool()
val memoryManager = new MemoryManager(gcConf)
val memoryManager = new MemoryManager(vmConf)
private implicit val memorySupport = memoryManager.memorySupport
......
/**
* This class allows the MicroVM to be configured from a text string. It increases the flexibility of language bindings.
* Other programming languages can set heap/global sizes and logging via this interface. It is less static than a fixed
* MicroVM constructor signature, but more options can be added/removed without changing the C binding API.
*/
package uvm.refimpl
import uvm.refimpl.mem.TypeSizes._
object VMConf {
val ReComment = """^\s*#.*$""".r
val ReBlank = """^\s*$""".r
val ReConf = """^\s*(\w+)=(\w+)\s*$""".r
def apply(confStr: String): VMConf = {
var sosSize = MicroVM.DEFAULT_SOS_SIZE
var losSize = MicroVM.DEFAULT_LOS_SIZE
var globalSize = MicroVM.DEFAULT_GLOBAL_SIZE
var stackSize = MicroVM.DEFAULT_GLOBAL_SIZE
confStr.lines foreach {
case ReComment() =>
case ReBlank() =>
case ReConf(key, value) => {
key match {
case "sosSize" => sosSize = value.toLong
case "losSize" => losSize = value.toLong
case "globalSize" => globalSize = value.toLong
case "stackSize" => stackSize = value.toLong
case "vmLog" => setLog("uvm.refimpl", value)
case "gcLog" => setLog("uvm.refimpl.mem", value)
case _ => throw new UvmRefImplException("Unrecognized option %s".format(key))
}
}
}
new VMConf(sosSize, losSize, globalSize, stackSize)
}
def setLog(name: String, levelStr: String): Unit = {
import org.slf4j.LoggerFactory
import org.slf4j.{ Logger => SLogger }
import ch.qos.logback.classic.{ Logger => LLogger, Level }
import ch.qos.logback.classic.Level._
val level = Level.toLevel(levelStr)
LoggerFactory.getLogger(name).asInstanceOf[LLogger].setLevel(level)
}
}
class VMConf(
val sosSize: Word = MicroVM.DEFAULT_SOS_SIZE,
val losSize: Word = MicroVM.DEFAULT_LOS_SIZE,
val globalSize: Word = MicroVM.DEFAULT_GLOBAL_SIZE,
val stackSize: Word = MicroVM.DEFAULT_STACK_SIZE)
......@@ -11,41 +11,46 @@ object MemoryManager {
val logger = Logger(LoggerFactory.getLogger(getClass.getName))
}
class MemoryManager(val gcConf: GCConf)(implicit microVM: MicroVM) {
class MemoryManager(val vmConf: VMConf)(implicit microVM: MicroVM) {
import MemoryManager._
logger.info("sosSize=%d, losSize=%d, globalSize=%d, stackSize=%d".format(
gcConf.sosSize, gcConf.losSize, gcConf.globalSize, gcConf.stackSize))
vmConf.sosSize, vmConf.losSize, vmConf.globalSize, vmConf.stackSize))
private val sosAlign = SimpleImmixSpace.BLOCK_SIZE
private val losAlign = LargeObjectSpace.BLOCK_SIZE
private val globalAlign = 4096L
require(gcConf.sosSize % SimpleImmixSpace.BLOCK_SIZE == 0, "Small object space size must be a multiple of %d bytes. actual size: %d".format(
SimpleImmixSpace.BLOCK_SIZE, gcConf.sosSize))
require(gcConf.losSize % LargeObjectSpace.BLOCK_SIZE == 0, "Large object space size must a multiple of %d bytes. actual size: %d".format(
LargeObjectSpace.BLOCK_SIZE, gcConf.losSize))
require(gcConf.globalSize % 4096L == 0, "Global space size must be 4096 bytes aligned. actual size: %d".format(gcConf.globalSize))
require(vmConf.sosSize % sosAlign == 0, "Small object space size must be a multiple of %d bytes. actual size: %d".format(
sosAlign, vmConf.sosSize))
require(vmConf.losSize % losAlign == 0, "Large object space size must a multiple of %d bytes. actual size: %d".format(
losAlign, vmConf.losSize))
require(vmConf.globalSize % globalAlign == 0, "Global space size must be a multiple of %d bytes. actual size: %d".format(
globalAlign, vmConf.globalSize))
val totalMemorySize = gcConf.sosSize + gcConf.losSize + gcConf.globalSize
val totalMemorySize = vmConf.sosSize.alignUpAndAdd(losAlign, vmConf.losSize).alignUpAndAdd(globalAlign, vmConf.globalSize)
// Allocate slightly more memory to meet the SimpleImmixSpace's alignment requirement.
implicit val memorySupport = new MemorySupport(totalMemorySize + SimpleImmixSpace.BLOCK_SIZE)
val memoryBegin = memorySupport.muMemoryBegin
val heapBegin = TypeSizes.alignUp(memoryBegin, SimpleImmixSpace.BLOCK_SIZE)
val globalBegin = heapBegin + gcConf.sosSize + gcConf.losSize
val globalEnd = globalBegin + gcConf.globalSize
val globalBegin = heapBegin + vmConf.sosSize + vmConf.losSize
val globalEnd = globalBegin + vmConf.globalSize
logger.info(("Mu memory allocated.\n memoryBegin=%d 0x%x\n heapBegin=%d 0x%x\n" +
" globalBegin=%d 0x%x\n memory end=%d 0x%x").format(
memoryBegin, memoryBegin, heapBegin, heapBegin, globalBegin, globalBegin, globalEnd, globalEnd
))
val heap = new SimpleImmixHeap(heapBegin, gcConf.sosSize, gcConf.losSize)
val globalMemory = new GlobalMemory(globalBegin, gcConf.globalSize)
val heap = new SimpleImmixHeap(heapBegin, vmConf.sosSize, vmConf.losSize)
val globalMemory = new GlobalMemory(globalBegin, vmConf.globalSize)
def makeMutator(): Mutator = heap.makeMutator()
def makeStackMemory(mutator: Mutator): StackMemory = {
val objRef = mutator.newHybrid(InternalTypes.BYTE_ARRAY, gcConf.stackSize)
val stackMemory = new StackMemory(objRef, gcConf.stackSize)
val objRef = mutator.newHybrid(InternalTypes.BYTE_ARRAY, vmConf.stackSize)
val stackMemory = new StackMemory(objRef, vmConf.stackSize)
stackMemory
}
}
......@@ -160,4 +160,10 @@ object TypeSizes {
def alignDown(n: Word, alignment: Word): Word = {
return n & ~(alignment - 1);
}
implicit class MagicalWord(val word: Word) extends AnyVal {
def alignUpAndAdd(align: Word, size: Word): Word = {
return alignUp(word, align) + size
}
}
}
\ No newline at end of file
......@@ -23,7 +23,7 @@ class UvmInterpreterSpec extends UvmBundleTesterBase {
//"uvm.refimpl.mem.simpleimmix.SimpleImmixCollector$" -> DEBUG,
"uvm.refimpl.itpr" -> DEBUG)
override def makeMicroVM = new MicroVM(new GCConf(sosSize = 4L * 1024L * 1024L, losSize = 4L * 1024L * 1024L))
override def makeMicroVM = new MicroVM(new VMConf(sosSize = 4L * 1024L * 1024L, losSize = 4L * 1024L * 1024L))
preloadBundles("tests/uvm-refimpl-test/primitives.uir",
"tests/uvm-refimpl-test/basic-tests.uir")
......
......@@ -40,7 +40,7 @@ class UvmInterpreterStackGCTests extends UvmBundleTesterBase {
}
// With 1MiB space is LOS. It can accommodate 16 stacks.
override def makeMicroVM = new MicroVM(new GCConf(losSize = 1L * 1024L * 1024L, stackSize = 63L * 1024L))
override def makeMicroVM = new MicroVM(new VMConf(losSize = 1L * 1024L * 1024L, stackSize = 63L * 1024L))
"The memory manager" should "collect unreachable stacks." in {
val ctx = microVM.newContext()
......
......@@ -20,7 +20,7 @@ class ObjectPinningTest extends UvmBundleTesterBase {
"uvm.refimpl.mem" -> INFO,
"uvm.refimpl.mem.simpleimmix.SimpleImmixCollector$" -> DEBUG)
override def makeMicroVM() = new MicroVM(new GCConf(sosSize = 256L*1024L, losSize = 256L * 1024L))
override def makeMicroVM() = new MicroVM(new VMConf(sosSize = 256L*1024L, losSize = 256L * 1024L))
def gc() = microVM.memoryManager.heap.mutatorTriggerAndWaitForGCEnd(false)
......
......@@ -15,7 +15,7 @@ class UvmMemOperationsSpec extends UvmBundleTesterBase {
// The heap size is intentionally reduced to make GC more often
// The heap is divided in two halves. There is a 256KiB small object space (with 8 32KiB blocks) and a 256KiB large
// object space.
override def makeMicroVM() = new MicroVM(new GCConf(sosSize = 256L*1024L, losSize = 256L * 1024L))
override def makeMicroVM() = new MicroVM(new VMConf(sosSize = 256L*1024L, losSize = 256L * 1024L))
microVM.memoryManager.heap.space.debugLogBlockStates()
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment