Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Implement isolating compartment system
  • Loading branch information
sorear committed Oct 25, 2011
1 parent f82b5ae commit 5f9e2f8
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 14 deletions.
6 changes: 6 additions & 0 deletions lib/CodeGen.cs
Expand Up @@ -3616,6 +3616,12 @@ public class DowncallReceiver : CallReceiver {
} else if (cmd == "set_parent") {
Builtins.up_domain = (AppDomain)args[1];
return null;
} else if (cmd == "push_compartment") {
Compartment.Push();
return null;
} else if (cmd == "pop_compartment") {
Compartment.Pop();
return null;
} else if (cmd == "new_unit") {
RuntimeUnit ru = new RuntimeUnit((string)args[1],
(string)args[2], (string)args[3],
Expand Down
89 changes: 80 additions & 9 deletions lib/Kernel.cs
Expand Up @@ -401,7 +401,7 @@ sealed class EmitUnit {
public ModuleBuilder mod_builder;
public TypeBuilder type_builder;
public int nextid;
public Dictionary<object, FieldBuilder> constants;
public Dictionary<object, FieldInfo> constants;
internal Dictionary<string, CpsOp> val_constants;

internal CpsOp TypeConstant(STable s) {
Expand All @@ -414,7 +414,7 @@ sealed class EmitUnit {
internal CpsOp RefConstant(string name, object val, Type nty) {
if (val == null)
return CpsOp.Null(nty);
FieldBuilder fi;
FieldInfo fi;
if (!constants.TryGetValue(val, out fi))
constants[val] = fi = NewField(name, val is Variable ? typeof(Variable) : val.GetType());
return CpsOp.IsConst(CpsOp.GetSField(fi));
Expand Down Expand Up @@ -570,12 +570,12 @@ public sealed class RuntimeUnit : IFreeze {
public Type type;
public Assembly assembly;
public List<SubInfo> our_subs;
public Dictionary<object, FieldInfo> constants;

bool prepared = false;

// used during construction only
public List<KeyValuePair<int,STable>> stubbed_stashes;
public Dictionary<object, FieldBuilder> constants;
internal List<RuntimeUnit> cosaved_evals = new List<RuntimeUnit>();
public int nextid;

Expand Down Expand Up @@ -618,7 +618,7 @@ public sealed class RuntimeUnit : IFreeze {
TypeAttributes.Abstract | TypeAttributes.Class |
TypeAttributes.BeforeFieldInit);

eu.constants = new Dictionary<object,FieldBuilder>(new IdentityComparer());
eu.constants = new Dictionary<object,FieldInfo>(new IdentityComparer());
eu.val_constants = new Dictionary<string,CpsOp>();
NamProcessor[] ths = new NamProcessor[our_subs.Count];
for (int i = 0; i < ths.Length; i++) {
Expand Down Expand Up @@ -666,6 +666,13 @@ public sealed class RuntimeUnit : IFreeze {
reg.SaveUnit(asm_name, this);
}

internal void SetConstants() {
if (type != null) {
foreach (KeyValuePair<object, FieldInfo> kv in constants)
type.GetField(kv.Value.Name).SetValue(null, kv.Key);
}
}

public void PrepareEval() {
if (prepared) return;
prepared = true;
Expand All @@ -675,9 +682,7 @@ public sealed class RuntimeUnit : IFreeze {

if (type == null) {
GenerateCode(true);

foreach (KeyValuePair<object, FieldBuilder> kv in constants)
type.GetField(kv.Value.Name).SetValue(null, kv.Key);
SetConstants();
}

foreach (SubInfo z in our_subs)
Expand Down Expand Up @@ -817,7 +822,7 @@ public sealed class RuntimeUnit : IFreeze {
fb.Refs(dep);

fb.Int(constants.Count);
foreach (KeyValuePair<object,FieldBuilder> kv in constants) {
foreach (KeyValuePair<object,FieldInfo> kv in constants) {
fb.String(kv.Value.Name);
fb.ObjRef(kv.Key);
}
Expand Down Expand Up @@ -871,9 +876,12 @@ public sealed class RuntimeUnit : IFreeze {
n.type = tb.type = n.assembly.GetType(n.name, true);

int ncon = tb.Int();
n.constants = new Dictionary<object,FieldInfo>();
while (ncon-- > 0) {
FieldInfo fi = n.type.GetField(tb.String());
fi.SetValue(null, tb.ObjRef());
object val = tb.ObjRef();
n.constants[val] = fi;
fi.SetValue(null, val);
}

int ct = tb.Int();
Expand Down Expand Up @@ -3879,6 +3887,66 @@ public struct StashCursor {
}
}

class Compartment {
[Immutable] static readonly FieldInfo[] fieldsToSave;

static Compartment() {
var typesToCheck = new Type[] {
typeof(Kernel), typeof(RuntimeUnit), typeof(CLRWrapperProvider),
typeof(RxFrame), typeof(Builtins)
};

List<FieldInfo> fields = new List<FieldInfo>();
foreach (Type ty in typesToCheck) {
foreach (FieldInfo fi in ty.GetFields(BindingFlags.NonPublic |
BindingFlags.Public | BindingFlags.Static)) {
foreach (object o in fi.GetCustomAttributes(true)) {
if (o is CORESavedAttribute) goto saveme;
if (o is CompartmentGlobalAttribute) goto saveme;
}
continue;
saveme:
fields.Add(fi);
}
}

fieldsToSave = fields.ToArray();
}

Compartment prev;
object[] saved_values;
private Compartment() { }

[TrueGlobal]
public static Compartment Top = new Compartment();

internal static void Push() {
Compartment n = new Compartment();
n.prev = Top;
n.saved_values = new object[fieldsToSave.Length];

for (int i = 0; i < fieldsToSave.Length; i++) {
n.saved_values[i] = fieldsToSave[i].GetValue(null);
fieldsToSave[i].SetValue(null, null);
}

Kernel.InitCompartment();
Top = n;
}

internal static void Pop() {
for (int i = 0; i < fieldsToSave.Length; i++) {
fieldsToSave[i].SetValue(null, Top.saved_values[i]);
}

if (Kernel.containerRootUnit != null) {
foreach (RuntimeUnit ru in Kernel.containerRootUnit.depended_units)
ru.SetConstants();
}
Top = Top.prev;
}
}

// A bunch of stuff which raises big circularity issues if done in the
// setting itself.
public class Kernel {
Expand Down Expand Up @@ -5211,6 +5279,7 @@ class ExitRunloopException : Exception {
class LastFrameNode {
public LastFrameNode next, prev;
public Frame cur, root;
public Compartment compartment = Compartment.Top;
}
[ThreadStatic] static LastFrameNode rlstack;
public static void SetTopFrame(Frame f) {
Expand All @@ -5228,6 +5297,8 @@ class LastFrameNode {
lfn.next.prev = lfn;
}
Frame l = lfn.cur;
if (lfn.compartment != Compartment.Top)
l = null; // hide other objects
rlstack = lfn.next;
return lfn.next.cur = lfn.next.root = ((l == null ?
new Frame(null, null, ExitRunloopSI, Kernel.AnyP) :
Expand Down
3 changes: 3 additions & 0 deletions src/NieczaBackendDotnet.pm6
Expand Up @@ -272,6 +272,9 @@ class Unit {
}
}

method push_compartment() { downcall("push_compartment") }
method pop_compartment() { downcall("pop_compartment") }

method create_unit($name, $filename, $source, $main, $run) {
downcall("new_unit", ~$name, ~$filename, ~$source, ?$main, ?$run);
}
4 changes: 1 addition & 3 deletions src/NieczaCompiler.pm6
Expand Up @@ -27,9 +27,7 @@ method !compile($unitname, $filename, $modtime, $source, $main, $run, $end, $eva
my $start = times[0] - $!discount-time;

my $ast = $!frontend.parse(:$unitname, :$filename, :$modtime,
:$source, :$outer, :$main, :$run);

$!backend.accept($unitname, $ast, :$main, :$run, :$evalmode, :$repl);
:$source, :$outer, :$main, :$run, :$evalmode, :$repl);

my $time = times[0] - $!discount-time - $start;

Expand Down
8 changes: 6 additions & 2 deletions src/NieczaFrontendSTD.pm6
Expand Up @@ -201,7 +201,7 @@ augment class Cursor {
has $.lang;
has $.safemode;

method parse(:$unitname, :$filename, :$modtime, :$source, :$outer, :$run, :$main) {
method parse(:$unitname, :$filename, :$modtime, :$source, :$outer, :$run, :$main, :$evalmode, :$repl) {

my $*SAFEMODE = $.safemode;
my $*UNITNAME = $unitname;
Expand Down Expand Up @@ -244,6 +244,8 @@ method parse(:$unitname, :$filename, :$modtime, :$source, :$outer, :$run, :$main
my $*UNIT;
my $*CCSTATE; my $*BORG; my %*RX; my $*XACT; my $*VAR; my $*IN_REDUCE;

$*backend.push_compartment unless $evalmode;
LEAVE { $*backend.pop_compartment unless $evalmode };
my $*unit = $*backend.create_unit($unitname, $filename, $source, $main, $run);
my $*settingref = $*niecza_outer_ref ||
($lang ne 'NULL' ?? $*unit.need_unit($lang).bottom !! Any);
Expand All @@ -255,5 +257,7 @@ method parse(:$unitname, :$filename, :$modtime, :$source, :$outer, :$run, :$main

@STD::herestub_queue = @save_herestub;

$ast;
$*backend.accept($unitname, $ast, :$main, :$run, :$evalmode, :$repl);

$evalmode ?? $ast !! Nil;
}

0 comments on commit 5f9e2f8

Please sign in to comment.