⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 todo.text

📁 idel虚拟机源码
💻 TEXT
字号:
external api to interpreterexternal function access (review how mite & glulx do it) (& omniware?)tracking source-file positionsensure source syntax can express everything in object fileapi for object filesbasic debuggerimprove speed of interpreter with automatically specialized instructionsuse `inline' in codegen.cjit implementation for x86improve compactness of object format with macros/millicodedocumentation & examplesfloating pointindirect callsthrow/catch or somethingrounding options for signed divisionextended arithmeticruntime code generationjump-table primitivedoes>notes:A counted-loop form would make it fairly easy to move the enough-fuelcheck out of the loop in favorable cases.  It could also help do thesame for memory bounds checks.Hm, I wonder if there's any way to combine the fuel check with thestack overflow check...  (Obviously we could use the host OS processmechanisms for both, but that kind of defeats our purpose...)  Yeah,there is.  Put the stack space and fuel remaining in two fields in onecell, with padding fields on the `overflow' side of each.  The widthof the padding depends on the maximum delta possible.  On a CALL, youadd a constant combining the stack and fuel deltas, then test for anynonzero bits in the padding fields.Each label comes with a statically-checked stack effect annotation.This means we'll need both static and dynamic checking for theindirect-call op.Tuning note: a tail call to self never needs a dynamic stack check.The same would hold true for a `larger' loop if the dynamic check atthe head accounted for all possible paths, but ensuring that would bemore complicated and would give you a more conservative check, solet's work on that later if at all.I think register assignment is going to be a serious problem in thejit compiler.  We can probably use a convention like: the deeper aparameter's position on the stack, the less important it is to have ina register.  Maybe the object format will need more info to help.1. Add a `macro' definition top-level form.  Macros are grouped in   the object file, and there's an opcode for invoking them.2. All unused opcodes become invocations of one of the first N macros   defined.  Macros may not be recursive; a simple way to enforce that   is by allowing them to refer only to lower-numbered macros.3. The decompression format uses default predefinitions of the first   N words as macros for compressing `typical' code and for invoking   standard external decompression functions.  (Among those functions   should be `decompress as .gz', etc.)  If you supply macro    definitions with those numbers, then they override the default.4. Write a code-compressor a la Proebsting to build the macro set.Alternatively, define millicode routines instead of macros.  Againthey can't be recursive, but furthermore they can't use the CALLinstruction, and they're required to be well-formed like functions.However, they can use the caller's locals, plus they come with anoperand mask word: a `1' in the mask corresponds to an operand fetchedinline from the instruction stream of the caller.  (The bits arenumbered to correspond to operands in the millicode instructions asthey're encountered.  We need to decide on how, or whether, branchesare allowed...)  The advantages of this variant: it's simpler tointerpret without expanding out the `macros' at compile time.  (Couldbe important on tiny processors.)  Disadvantages: it's more complexand imposes restrictions on factoring.  Indifferent: it permitsabstracting over immediate operands -- the macro approach could befixed to do that too.This macro/millicode stuff is worthwhile because it lets us define thevm as a bare minimum with no complicated set of redundant instructionsadded for size/speed.  It's simpler and more flexible than the ad-hocinstruction combinations in the JVM.The active-packets standard would have a different set of macropredefinitions.OK, the object file format will need a standard for debugging info andexternal linking, etc., and you know how complicated that kind ofstuff gets.  Norman Ramsey worked on defining that stuff in a simpleand portable way by embedding runnable code inside the file.  But, um,we already have portable runnable code here!  So look into his design-- this sounds like the way to do it.Here's how we'll do indirect calls.  Add opcodes for indirectcall/tailcall, with the signature of the called word as an operand.Add some way of getting the address of a word to pass later as anargument to an indirect call op.  The code for any such word ispreceded by a bitpattern that appears in code segments *only* beforesuch words with the same signature.  (The bitpattern istarget-dependent and might need more than one memory cell.)  So anindirect jump has to: bounds-check the pointer, fetch the cell(s)before it, test them, then do the actual jump.  For the bounds checkwe might want to dedicate an extra register or two, bleah.An alternative design would allow you to only pass around handles toprocedures, with the actual pointers kept in a protected table.That's more cumbersome, though, and leaves the implementation with yetanother memory block to manage.  Hm, you could make it look the sameto the client program, though, except for the actual integer values ofthe handles/pointers (which are of course unspecified).  Er, wait, no,I'm being stupid.  If we want to be able to serialize the runtimestate portably, we need the procedure pointers to be portable.  Sincethey are not opaque, we need to define exactly what values they have.(That, or pass along the integer values of the pointers so thedestination machine can map them to its own values at runtime -- ugh-- or else give up on serializing the *entire* state.)  So I guess thehandles are the way to go.All this still can't do calls that are generic wrt signature, butthere'll be runtime code generation available to take up the slack.We'll want the object file to give some local indication of whichdefinitions are possible entry points from indirect calls, so theimplementation can avoid adding a header in the typical case, orwhatever other tricks it might do, without extra analysis work.  Thisbrings up the question of how to encode such info in the object file-- it's not the only such flag we might want.  (Tell which are leafprocedures, for instance.)  I'd expect the escaping set to betypically sparse (and when it's dense you'll have efficiency problemsregardless), but the leaf set typically dense...done:compilernested localsmemory access instructionsvariablesportable object formatdebug rev.forthlink loader with vm.cgenerate implementation from opcode descriptionstail call optimizationportable semi-efficient threaded-code implementation using Gnu C labelsforward refssafety & fuelremove hard limitsserializationstring constants0.1 releaseeliminate pc-relative arguments

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -