diff --git a/compiler/asmjit.stanza b/compiler/asmjit.stanza index 2c382c43b..124162690 100644 --- a/compiler/asmjit.stanza +++ b/compiler/asmjit.stanza @@ -61,6 +61,7 @@ extern assembler_div_reg: (ptr, ptr) -> int extern assembler_mod_reg: (ptr, ptr) -> int extern assembler_cqo_reg: (ptr) -> int extern assembler_cdq_reg: (ptr) -> int +extern assembler_nop: (ptr) -> int extern assembler_and_reg: (ptr, ptr, ptr) -> int extern assembler_and_int: (ptr, ptr, int) -> int extern assembler_or_reg: (ptr, ptr, ptr) -> int @@ -186,7 +187,7 @@ public lostanza deftype MemPtr : ;------------------------------------------------------------ defmethod equal? (a:Gp, b:Gp) -> True|False : id(a) == id(b) - + defmethod equal? (a:Xmm, b:Xmm) -> True|False : id(a) == id(b) @@ -697,6 +698,9 @@ public lostanza defn btr (a:ref, dst:ref, src:ref) -> ref public lostanza defn btr (a:ref, ptr:ref, src:ref) -> ref : call-c assembler_btr_ptr_reg(a.value, ptr.value, src.value) return src +public lostanza defn nop (a:ref) -> ref : + call-c assembler_nop(a.value) + return false ;------------------------------------------------------------ ;-------------------- Comparisons and Jumps ----------------- @@ -912,4 +916,3 @@ public lostanza defn ucomiss (a:ref, x:ref, y:ref) -> ref, x:ref, y:ref) -> ref : call-c assembler_ucomisd(a.value, x.value, y.value) return false - diff --git a/compiler/code-table.stanza b/compiler/code-table.stanza index c40f628d4..6572d9c8e 100644 --- a/compiler/code-table.stanza +++ b/compiler/code-table.stanza @@ -12,7 +12,7 @@ defpackage stz/code-table : ;============================================================ ;This contains all the generated code for the functions ;loaded into the virtual machine, as well as any additional -;tables for performing the code encoding. +;tables for performing the code encoding. public deftype CodeTable @@ -37,6 +37,9 @@ public defmulti load-function (t:CodeTable, public defstruct LoadedFunction : address:Long trace-entries:Vector + safepoint-entries:Vector + local-var-context:Vector + local-var-map-entries:Vector ;Represents the entry for use during backtraces. public defstruct TraceTableEntry : @@ -45,6 +48,18 @@ public defstruct TraceTableEntry : with: printer => true +public defstruct SafepointTableEntry : + pc: Long + id: Int +with: + printer => true + +public defstruct LocalVarMapEntry : + pc: Long + indices: Tuple ;Sorted in increasing order, in local-var-context +with: + printer => true + ;============================================================ ;================== Launch ================================== ;============================================================ @@ -80,7 +95,7 @@ public deftype EncodingResolver ;- live: The set of locals that are live at the moment. public defmulti liveness-map (r:EncodingResolver, live:Seqable, num-locals:Int) -> Int -;Return the number of bytes used for the tag word of each object. +;Return the number of bytes used for the tag word of each object. public defmulti object-header-size (r:EncodingResolver) -> Int ;Return the number of bytes used to store an object on the heap. @@ -120,10 +135,10 @@ public defmulti marker? (r:EncodingResolver, n:Int) -> True|False public defmulti tagbits (r:EncodingResolver, typeid:Int) -> Int ;Return the address of the given extern address. -public defmulti extern-address (r:EncodingResolver, id:Int) -> Long +public defmulti extern-address (r:EncodingResolver, id:Int) -> Long ;Return the address of the given extern defn address. -public defmulti extern-defn-address (r:EncodingResolver, id:Int) -> Long +public defmulti extern-defn-address (r:EncodingResolver, id:Int) -> Long ;------------------------------------------------------------ ;----------------------- Convenience ------------------------ diff --git a/compiler/cvm-code-table.stanza b/compiler/cvm-code-table.stanza index 0577b180b..9f785c477 100644 --- a/compiler/cvm-code-table.stanza +++ b/compiler/cvm-code-table.stanza @@ -46,15 +46,24 @@ lostanza defmethod load-function (table:ref, ;Add the offset to the trace entries so that we know their absolute position. val relocated-trace-entries = add-offset(trace-entries(encoded-function), new Long{offset}) + val relocated-safepoint-entries = add-offset(safepoint-entries(encoded-function), new Long{offset}) + val relocated-local-var-map-entries = add-offset(local-var-map-entries(encoded-function), new Long{offset}) ;Return the new loaded function - return LoadedFunction(new Long{offset}, relocated-trace-entries) + return LoadedFunction(new Long{offset}, relocated-trace-entries, relocated-safepoint-entries, + local-var-context(encoded-function), relocated-local-var-map-entries) ;Add 'offset' to the 'pc' of every entry in 'trace-entries' and return ;the result. defn add-offset (trace-entries:Seqable, offset:Long) -> Vector : to-vector $ for e in trace-entries seq : TraceTableEntry(pc(e) + offset, entry(e)) +defn add-offset (safepoint-entries:Seqable, offset:Long) -> Vector : + to-vector $ for e in safepoint-entries seq : + SafepointTableEntry(pc(e) + offset, id(e)) +defn add-offset (local-var-map-entries:Seqable, offset:Long) -> Vector : + to-vector $ for e in local-var-map-entries seq : + LocalVarMapEntry(pc(e) + offset, indices(e)) ;============================================================ ;================== Launch ================================== diff --git a/compiler/cvm-encoder.stanza b/compiler/cvm-encoder.stanza index 0d96d72e8..6135ca848 100644 --- a/compiler/cvm-encoder.stanza +++ b/compiler/cvm-encoder.stanza @@ -18,13 +18,16 @@ defpackage stz/cvm-encoder : public defstruct EncodedFunction : buffer: ByteBuffer trace-entries: Vector + safepoint-entries: Vector + local-var-context:Vector + local-var-map-entries:Vector public defn encode (func:VMFunction, resolver:EncodingResolver, backend:Backend) -> EncodedFunction : ;Encode instructions into this byte buffer val buffer = ByteBuffer() - + ;All instructions are sized to be multiples of 4 bytes, and thus ;we use address / 4 as a "position" in the instruction stream. defn buffer-pos () : write-position(buffer) / 4 @@ -32,9 +35,12 @@ public defn encode (func:VMFunction, ;Accumulate file information entries for implementing ;stack traces. val trace-entry-table = Vector() + val safepoint-entry-table = Vector() defn record-trace-entry (entry:StackTraceInfo|False) : match(entry:StackTraceInfo) : add(trace-entry-table, TraceTableEntry(to-long(write-position(buffer)), entry)) + val local-var-context = Vector() + val local-var-maps = Vector() ;Delay the generation of this instruction, ;Instruction takes up the given number of 'instruction-words'. @@ -698,7 +704,7 @@ public defn encode (func:VMFunction, ;Use delayed actions and encode instructions within delay-actions() : encode(func as VMMultifn|VMFunc) - EncodedFunction(buffer, trace-entry-table) + EncodedFunction(buffer, trace-entry-table, safepoint-entry-table, local-var-context, local-var-maps) ;============================================================ ;====================== Utilities =========================== diff --git a/compiler/dl-ir.stanza b/compiler/dl-ir.stanza index 5ae0c0a04..90b42cba5 100644 --- a/compiler/dl-ir.stanza +++ b/compiler/dl-ir.stanza @@ -1106,6 +1106,13 @@ public val CORE-FULL-LIST-ID = register $ core-typeid(`FullList) public val CORE-NIL-LIST-ID = register $ core-typeid(`NilList) public val CORE-STRING-ID = register $ core-typeid(`String) public val CORE-SYMBOL-ID = register $ core-typeid(`Symbol) +public val CORE-STRING-SYMBOL-ID = register $ core-typeid(`StringSymbol) +public val CORE-BYTE-ARRAY-ID = register $ core-typeid(`ByteArray) +public val CORE-CHAR-ARRAY-ID = register $ core-typeid(`CharArray) +public val CORE-INT-ARRAY-ID = register $ core-typeid(`IntArray) +public val CORE-LONG-ARRAY-ID = register $ core-typeid(`LongArray) +public val CORE-FLOAT-ARRAY-ID = register $ core-typeid(`FloatArray) +public val CORE-DOUBLE-ARRAY-ID = register $ core-typeid(`DoubleArray) public val CORE-UNIQUE-ID = register $ core-typeid(`Unique) public val CORE-MAYBE-ID = register $ core-typeid(`Maybe) public val CORE-ONE-ID = register $ core-typeid(`One) diff --git a/compiler/jit-code-table.stanza b/compiler/jit-code-table.stanza index 981dfba63..e07cb16e3 100644 --- a/compiler/jit-code-table.stanza +++ b/compiler/jit-code-table.stanza @@ -31,7 +31,7 @@ public defstruct JITStubs : public defn JITCodeTable (resolver:EncodingResolver, backend:Backend) -> JITCodeTable : val runtime = jit-runtime-new() - val stubs = make-jit-stubs(runtime, resolver, backend) + val stubs = make-jit-stubs(runtime, resolver, backend) #JITCodeTable(runtime, stubs) ;============================================================ @@ -52,12 +52,13 @@ defmethod load-function (table:JITCodeTable, val oldf = get?(funcs(table), fid) match(oldf:Func) : release(runtime(table), oldf) - + ;Add the function into the table so that we can release them later. put(funcs(table), fid, func(encoded-function)) ;Return the loaded function - LoadedFunction(value(func(encoded-function)), trace-entries(encoded-function)) + LoadedFunction(value(func(encoded-function)), trace-entries(encoded-function), safepoint-entries(encoded-function), + local-var-context(encoded-function), local-var-maps(encoded-function)) ;============================================================ ;================== Launch ================================== @@ -68,7 +69,7 @@ lostanza defmethod launch (vmstate-address:ref, table:ref, f val fptr = launch as ptr<( (ptr, long, long) -> int )> val vmstate = vmstate-address.value as ptr call-c [fptr](vmstate, call-prim crsp() as long, func-id.value) - return false + return false ;============================================================ ;===================== Free ================================= @@ -96,6 +97,6 @@ defn put (xs:Vector, k:Int, v:T) : if k >= length(xs) : lengthen(xs, k + 1, false) xs[k] = v - + defn get? (xs:Vector, k:Int) -> T|False : if k < length(xs) : xs[k] diff --git a/compiler/jit-encoder.stanza b/compiler/jit-encoder.stanza index 2a97291b1..2fdce62eb 100644 --- a/compiler/jit-encoder.stanza +++ b/compiler/jit-encoder.stanza @@ -51,6 +51,9 @@ val COMPUTE-ABSOLUTE-ADDRESSES = TimerLabel(JIT-ENCODER, suffix("Compute absolut public defstruct EncodedFunction : func: Func trace-entries: Vector + safepoint-entries: Vector + local-var-context: Vector + local-var-maps: Vector ;============================================================ ;=================== Configuration ========================== @@ -89,7 +92,7 @@ lostanza defn call-collect-stack-trace-addr () -> ref : ;================== Register Conventions ==================== ;============================================================ ;Decide on which x86 registers to use for all our virtual machine -;quantities. This is backend-specific. +;quantities. This is backend-specific. ; ;# Notes about Assignment # ;- X86 div and shl instructions uses RAX, RDX, RCX as special registers. @@ -330,7 +333,7 @@ defn branch-is-final? (resolver:EncodingResolver, b:VMBranch) : ; ;- vmstate.current_stack.stack_pointer.locals[0 to n]: Locali ; JIT code for single function assumes cached in register. -; Needs to be written to in-memory structure when current stack frame changes. +; Needs to be written to in-memory structure when current stack frame changes. ; ;- vmstate.registers[0 to n]: VMRegi ; JIT code assumes cached in register. @@ -351,6 +354,7 @@ defenum EnterExit: (Enter, Exit) ;The information about a function's local frame. defstruct FuncInfo : deftable:IntTable + name-table:IntTable ;empty if no debug info present used-labels:IntSet max-local:Int num-locals:Int @@ -366,7 +370,10 @@ defn AsmGen (code:CodeHolder, a:Assembler, resolver:EncodingResolver, func-info:FuncInfo|False, - trace-entry-table:Vector|False, + trace-entry-table:Vector, + safepoint-entry-table:Vector, + local-var-context:Vector, + local-var-maps:Vector, backend:Backend) : ;========================================================= @@ -386,29 +393,35 @@ defn AsmGen (code:CodeHolder, val local-deftable = match(func-info:FuncInfo) : deftable(func-info) + ;Extract the local name table if there is one. + val local-name-table = match(func-info:FuncInfo) : name-table(func-info) + else : IntTable() ;Force retrieve the input FuncInfo. defn func-info! () -> FuncInfo : if func-info is False : fatal("No function information is given.") func-info as FuncInfo + ;Retrieve the stack frame slot that the local is stored in. + defn name? (l:Local) : + get?(local-name-table, index(l)) + ;Force retrieve the deftable. defn deftable! () -> IntTable : local-deftable as IntTable - ;Retrieve the stack frame slot that the local is - ;stored in. + ;Retrieve the stack frame slot that the local is stored in. defn slot (l:Local) -> Int : /local(deftable!()[index(l)]) ;Call slot if x is a Local otherwise return dummy value 0. ;The dummy value is fine because in this case the instruction - ;doesn't have a return value anyway. + ;doesn't have a return value anyway. defn slot? (x:Local|False) -> Int : match(x:Local) : slot(x) else : 0 - ;Call slot if x is a Local otherwise return dummy value 0. + ;Call slot if x is a Local, otherwise report an error. defn slot! (x:Local|False) -> Int : match(x:Local) : slot(x) else : fatal("x is expected to be a Local.") @@ -444,7 +457,7 @@ defn AsmGen (code:CodeHolder, ;========================================================= val label-table = IntTable