Commit f77642c3 authored by Kunshan Wang's avatar Kunshan Wang

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