Skip to content
Browse files

Change constant table to use instance fields

By allowing different loads of the same load module to have independent
constant tables, this is the first step towards allowing concurrent use
of compartments in the same kernel instance.
  • Loading branch information...
1 parent a8aa70b commit c592587baa7fc1e6f6a3fcb3c210e9402a4c8b21 @sorear committed Sep 13, 2012
Showing with 67 additions and 42 deletions.
  1. +39 −21 lib/CodeGen.cs
  2. +24 −19 lib/Kernel.cs
  3. +1 −1 lib/Niecza/UCD.pm6
  4. +3 −1 lib/Serialize.cs
View
60 lib/CodeGen.cs
@@ -593,7 +593,7 @@ class ClrMethodCall : ClrOp {
}
public override void CodeGen(CgContext cx) {
if (HasCases) {
- cx.il.Emit(OpCodes.Ldarg_0);
+ cx.il.Emit(OpCodes.Ldarg_1);
cx.EmitInt(cx.next_case);
cx.il.Emit(OpCodes.Stfld, Tokens.Frame_ip);
}
@@ -625,7 +625,7 @@ class ClrMethodCall : ClrOp {
}
// this needs to come AFTER the invocant
if (HasCases)
- cx.il.Emit(OpCodes.Ldarg_0);
+ cx.il.Emit(OpCodes.Ldarg_1);
for (; i < Zyg.Length; i++) {
Zyg[i].CodeGen(cx);
@@ -854,6 +854,22 @@ class ClrSetField : ClrOp {
}
}
+ class ClrGetConst : ClrOp {
+ public readonly FieldInfo f;
+
+ public override ClrOp Sink() { return ClrNoop.Instance; }
+ public override void CodeGen(CgContext cx) {
+ cx.il.Emit(OpCodes.Ldarg_0);
+ cx.il.Emit(OpCodes.Ldfld, f);
+ }
+
+ public ClrGetConst(FieldInfo f) {
+ Returns = f.FieldType;
+ this.f = f;
+ }
+ }
+
+ // RETIREME
class ClrGetSField : ClrOp {
public readonly FieldInfo f;
@@ -891,7 +907,7 @@ class ClrPadGet : ClrOp {
public override ClrOp Sink() { return ClrNoop.Instance; }
public override void CodeGen(CgContext cx) {
- cx.il.Emit(OpCodes.Ldarg_0);
+ cx.il.Emit(OpCodes.Ldarg_1);
for (int i = 0; i < up; i++)
cx.il.Emit(OpCodes.Ldfld, Tokens.Frame_outer);
cx.EmitGetlex(index + Tokens.NumInt32, Tokens.Variable);
@@ -910,7 +926,7 @@ class ClrPadSet : ClrOp {
public readonly ClrOp zyg;
public override void CodeGen(CgContext cx) {
- cx.il.Emit(OpCodes.Ldarg_0);
+ cx.il.Emit(OpCodes.Ldarg_1);
for (int i = 0; i < up; i++)
cx.il.Emit(OpCodes.Ldfld, Tokens.Frame_outer);
cx.EmitPreSetlex(index + Tokens.NumInt32);
@@ -1069,7 +1085,7 @@ class ClrSync : ClrOp {
}
public override void ListCases(CgContext cx) { cx.num_cases++; }
public override void CodeGen(CgContext cx) {
- cx.il.Emit(OpCodes.Ldarg_0);
+ cx.il.Emit(OpCodes.Ldarg_1);
cx.EmitInt(cx.next_case);
cx.il.Emit(OpCodes.Stfld, Tokens.Frame_ip);
cx.il.MarkLabel(cx.cases[cx.next_case++]);
@@ -1167,7 +1183,7 @@ class ClrSubyCall : ClrOp {
}
public override void CodeGen(CgContext cx) {
- cx.il.Emit(OpCodes.Ldarg_0);
+ cx.il.Emit(OpCodes.Ldarg_1);
cx.EmitInt(cx.next_case);
cx.il.Emit(OpCodes.Stfld, Tokens.Frame_ip);
@@ -1178,7 +1194,7 @@ class ClrSubyCall : ClrOp {
cx.il.Emit(OpCodes.Stloc, cx.sspill);
cx.il.Emit(OpCodes.Callvirt, Tokens.Variable_Fetch);
}
- cx.il.Emit(OpCodes.Ldarg_0);
+ cx.il.Emit(OpCodes.Ldarg_1);
if (ismethod)
zyg[0].CodeGen(cx);
@@ -1228,7 +1244,7 @@ class ClrPushLet : ClrOp {
while (ix < cx.let_types.Length && cx.let_types[ix] != null)
ix++;
- cx.il.Emit(OpCodes.Ldarg_0);
+ cx.il.Emit(OpCodes.Ldarg_1);
cx.EmitPreSetlex(ix);
// Initial must not have a net effect on cx.let_types
@@ -1263,7 +1279,7 @@ class ClrPokeLet : ClrOp {
if (ix == cx.let_names.Length)
throw new Exception("let " + Name + " not found");
- cx.il.Emit(OpCodes.Ldarg_0);
+ cx.il.Emit(OpCodes.Ldarg_1);
cx.EmitPreSetlex(ix);
// Initial must not have a net effect on cx.let_types
@@ -1288,7 +1304,7 @@ class ClrPeekLet : ClrOp {
if (ix == cx.let_names.Length)
throw new Exception("let " + Name + " not found");
- cx.il.Emit(OpCodes.Ldarg_0);
+ cx.il.Emit(OpCodes.Ldarg_1);
cx.EmitGetlex(ix, Returns);
}
}
@@ -1300,7 +1316,7 @@ class ClrSetResult : ClrOp {
this.zyg = zyg;
}
public override void CodeGen(CgContext cx) {
- cx.il.Emit(OpCodes.Ldarg_0);
+ cx.il.Emit(OpCodes.Ldarg_1);
zyg.CodeGen(cx);
if (zyg.Returns.IsValueType)
cx.il.Emit(OpCodes.Box, zyg.Returns);
@@ -1316,7 +1332,7 @@ class ClrResult : ClrOp {
public override void CodeGen(CgContext cx) {
if (Returns == Tokens.Void)
return;
- cx.il.Emit(OpCodes.Ldarg_0);
+ cx.il.Emit(OpCodes.Ldarg_1);
cx.il.Emit(OpCodes.Ldfld, Tokens.Frame_resultSlot);
if (Config.CGVerifiable || Returns.IsValueType)
cx.il.Emit(OpCodes.Unbox_Any, Returns);
@@ -1409,12 +1425,12 @@ class ClrCpsReturn : ClrOp {
}
public override void CodeGen(CgContext cx) {
if (child != null) {
- cx.il.Emit(OpCodes.Ldarg_0);
+ cx.il.Emit(OpCodes.Ldarg_1);
cx.il.Emit(OpCodes.Ldfld, Tokens.Frame_caller);
child.CodeGen(cx);
cx.il.Emit(OpCodes.Stfld, Tokens.Frame_resultSlot);
}
- cx.il.Emit(OpCodes.Ldarg_0);
+ cx.il.Emit(OpCodes.Ldarg_1);
cx.il.Emit(OpCodes.Call, Tokens.Frame_Return);
cx.il.Emit(OpCodes.Ret);
}
@@ -1441,7 +1457,7 @@ class ClrCpsFrame : ClrOp {
Constant = true;
}
public override void CodeGen(CgContext cx) {
- cx.il.Emit(OpCodes.Ldarg_0);
+ cx.il.Emit(OpCodes.Ldarg_1);
}
[Immutable] public static ClrCpsFrame Instance = new ClrCpsFrame();
}
@@ -2045,6 +2061,9 @@ class CpsOp {
public static CpsOp GetSField(FieldInfo fi) {
return new CpsOp(new ClrGetSField(fi));
}
+ public static CpsOp GetConst(FieldInfo fi) {
+ return new CpsOp(new ClrGetConst(fi));
+ }
public static CpsOp SetField(FieldInfo fi, CpsOp za, CpsOp zb) {
return Primitive(new CpsOp[2] { za, zb }, delegate(ClrOp[] heads) {
@@ -2118,8 +2137,7 @@ class CpsBuilder {
public CpsBuilder(EmitUnit eu, string clrname, bool pub) {
this.eu = eu;
this.tb = eu.type_builder;
- mb = tb.DefineMethod(clrname, MethodAttributes.Static |
- (pub ? MethodAttributes.Public : 0),
+ mb = tb.DefineMethod(clrname, (pub ? MethodAttributes.Public : 0),
typeof(Frame), new Type[] { typeof(Frame) });
cx = new CgContext();
cx.tb = tb;
@@ -2152,11 +2170,11 @@ class CpsBuilder {
for (int i = 0; i < cx.num_cases; i++)
cx.cases[i] = cx.il.DefineLabel();
- cx.il.Emit(OpCodes.Ldarg_0);
+ cx.il.Emit(OpCodes.Ldarg_1);
cx.il.Emit(OpCodes.Ldfld, Tokens.Frame_ip);
cx.il.Emit(OpCodes.Switch, cx.cases);
- cx.il.Emit(OpCodes.Ldarg_0);
+ cx.il.Emit(OpCodes.Ldarg_1);
cx.il.Emit(OpCodes.Ldstr, "Invalid IP");
cx.il.Emit(OpCodes.Call, Tokens.Kernel_Die);
cx.il.Emit(OpCodes.Ret);
@@ -3288,7 +3306,7 @@ class NamProcessor {
cpb.Build(Scan(WrapBody(b)));
}
- public void FillSubInfo(Type ty) {
+ public void FillSubInfo(Type ty, object constTable) {
MethodInfo m = ty.GetMethod(cpb.mb.Name);
sub.lines = cpb.cx.lineBuffer.ToArray();
@@ -3305,7 +3323,7 @@ class NamProcessor {
}
sub.code = (DynBlockDelegate) Delegate.CreateDelegate(
- Tokens.DynBlockDelegate, m);
+ Tokens.DynBlockDelegate, constTable, m);
if (sub.protopad != null) {
sub.protopad.code = sub.code;
sub.protopad.EnsureSpills(sub.nspill);
View
43 lib/Kernel.cs
@@ -442,8 +442,7 @@ sealed class EmitUnit {
asm_builder = AppDomain.CurrentDomain.DefineDynamicAssembly(
new AssemblyName(asm_name),
(dll_name == null ? AssemblyBuilderAccess.Run :
- Config.CGForceSave ? AssemblyBuilderAccess.RunAndSave :
- AssemblyBuilderAccess.Save),
+ AssemblyBuilderAccess.RunAndSave),
Backend.obj_dir);
mod_builder = dll_name == null ?
@@ -452,8 +451,7 @@ sealed class EmitUnit {
type_builder = mod_builder.DefineType(asm_name,
TypeAttributes.Public | TypeAttributes.Sealed |
- TypeAttributes.Abstract | TypeAttributes.Class |
- TypeAttributes.BeforeFieldInit);
+ TypeAttributes.Class | TypeAttributes.BeforeFieldInit);
if (is_mainish) {
var mainb = type_builder.DefineMethod("Main",
@@ -496,12 +494,14 @@ sealed class EmitUnit {
}
}
- public Type Finish() {
+ public Type Finish(out object constTable) {
var type = type_builder.CreateType();
+ constTable = Activator.CreateInstance(type);
+
if (dll_name != null)
asm_builder.Save(dll_name);
foreach (NamProcessor th in fill)
- th.FillSubInfo(type);
+ th.FillSubInfo(type, constTable);
var fields = new Dictionary<string,FieldInfo>();
foreach (FieldInfo fi in type.GetFields())
@@ -533,7 +533,7 @@ sealed class EmitUnit {
FieldInfo fi;
if (!constants.TryGetValue(val, out fi))
constants[val] = fi = NewField(n1, n2, nty ?? val.GetType());
- return CpsOp.IsConst(CpsOp.GetSField(fi));
+ return CpsOp.IsConst(CpsOp.GetConst(fi));
}
internal CpsOp ValConstant(string key, object val) {
@@ -679,7 +679,7 @@ sealed class EmitUnit {
}
return type_builder.DefineField(new string(buf, 0, wp),
- ty, FieldAttributes.Public | FieldAttributes.Static);
+ ty, FieldAttributes.Public);
}
}
@@ -710,10 +710,9 @@ public sealed class RuntimeUnit : IFreeze {
// note: type is only set to a non-null value if the type is a
// member of a saved assembly; thus type being non-null implies
- // a significance to freezing and thawing the type, and also
- // implies that the type is potentially shared between compartments
- // and globals must be reset in Compartment.Pop.
+ // a significance to freezing and thawing the type
public Type type;
+ public object constTable;
public Dictionary<object, FieldInfo> constants;
public bool inited = false;
@@ -772,7 +771,8 @@ public sealed class RuntimeUnit : IFreeze {
EmitUnit eu = new EmitUnit(null, "Anon." + Interlocked.Increment(
ref anon_id), null, false);
eu.CgSub(sub, false);
- SetConstants(eu.Finish(), eu.constants);
+ object jit_consts;
+ SetConstants(eu.Finish(out jit_consts), jit_consts, eu.constants);
th.code = th.info.code = sub.code;
th.info.nspill = sub.nspill;
@@ -791,7 +791,7 @@ public sealed class RuntimeUnit : IFreeze {
SaveSubs(eu, !Config.KeepIL);
- type = eu.Finish();
+ type = eu.Finish(out constTable);
constants = eu.constants;
// all co-saved units must remember that their code is here
foreach (RuntimeUnit zu in subordinates)
@@ -800,11 +800,11 @@ public sealed class RuntimeUnit : IFreeze {
reg.SaveUnit(name, this);
}
- internal void SetConstants() { SetConstants(type, constants); }
- static void SetConstants(Type ty, Dictionary<object,FieldInfo> consts) {
+ internal void SetConstants() { SetConstants(type, constTable, constants); }
+ static void SetConstants(Type ty, object ctab, Dictionary<object,FieldInfo> consts) {
if (ty != null) {
foreach (KeyValuePair<object, FieldInfo> kv in consts)
- kv.Value.SetValue(null, kv.Key);
+ kv.Value.SetValue(ctab, kv.Key);
}
}
@@ -817,7 +817,8 @@ public sealed class RuntimeUnit : IFreeze {
ref anon_id) + "." + asm_name, null, false);
SaveSubs(eu, false);
- SetConstants(eu.Finish(), eu.constants);
+ object jit_consts;
+ SetConstants(eu.Finish(out jit_consts), jit_consts, eu.constants);
}
internal void RunMainline() {
@@ -1038,6 +1039,7 @@ public sealed class RuntimeUnit : IFreeze {
} else {
Assembly assembly = Assembly.Load(n.asm_name);
n.type = tb.type = assembly.GetType(n.asm_name, true);
+ n.constTable = Activator.CreateInstance(n.type);
n.constants = new Dictionary<object,FieldInfo>();
var fields = new Dictionary<string,FieldInfo>();
foreach (FieldInfo fi in n.type.GetFields())
@@ -1047,11 +1049,12 @@ public sealed class RuntimeUnit : IFreeze {
foreach (MethodInfo mi in n.type.GetMethods())
meth[mi.Name] = mi;
RuntimeUnit.reg.methods[n.asm_name] = meth;
+ RuntimeUnit.reg.instances[n.asm_name] = n.constTable;
while (ncon-- > 0) {
FieldInfo fi = fields[tb.String()];
object val = tb.ObjRef();
n.constants[val] = fi;
- fi.SetValue(null, val);
+ fi.SetValue(n.constTable, val);
}
}
@@ -2122,6 +2125,7 @@ public class UsedInScopeInfo {
string tn = tb.String();
if (mn != null && (kernel || !Backend.cross_level_load)) {
MethodInfo mi;
+ object obj = null;
if (kernel) {
mi = typeof(Kernel).Assembly.GetType(tn, true)
.GetMethod(mn, BindingFlags.Public |
@@ -2133,9 +2137,10 @@ public class UsedInScopeInfo {
!t1.TryGetValue(mn, out mi)) {
throw new Exception("Thawed sub references nonexistant method " + tn + "::" + mn);
}
+ obj = RuntimeUnit.reg.instances[tn];
}
n.code = (DynBlockDelegate) Delegate.CreateDelegate(
- typeof(DynBlockDelegate), mi);
+ typeof(DynBlockDelegate), obj, mi);
}
n.nspill = tb.Int();
View
2 lib/Niecza/UCD.pm6
@@ -21,4 +21,4 @@ sub value($table, $chr) is export { get_value_num($table, ord $chr) }
sub get_codepoint($name) is export { Q:CgOp { (ucd_get_codepoint {$name}) } }
-sub foldcase($codepoint) is export { Q:CgOp { (ucd_foldcase {$codepoint}) } }}
+#sub foldcase($codepoint) is export { Q:CgOp { (ucd_foldcase {$codepoint}) } }
View
4 lib/Serialize.cs
@@ -68,9 +68,11 @@ struct ObjRef {
internal Dictionary<string,Dictionary<string,MethodInfo>> methods =
new Dictionary<string,Dictionary<string,MethodInfo>>();
+ internal Dictionary<string,object> instances =
+ new Dictionary<string,object>();
static readonly string signature = "Niecza-Serialized-Module";
- static readonly int version = 29;
+ static readonly int version = 30;
// Routines for use by serialization code
public bool CheckWriteObject(SerUnit into, object o,

0 comments on commit c592587

Please sign in to comment.
Something went wrong with that request. Please try again.