Skip to content

Commit

Permalink
Add framework for detecting stale precompiled modules
Browse files Browse the repository at this point in the history
  • Loading branch information
sorear committed Oct 17, 2011
1 parent 661b29c commit eee0cbb
Show file tree
Hide file tree
Showing 8 changed files with 74 additions and 30 deletions.
13 changes: 9 additions & 4 deletions lib/Builtins.cs
Expand Up @@ -1618,16 +1618,21 @@ class SubstrLValue: Variable {


public static AppDomain up_domain; public static AppDomain up_domain;
public static DynBlockDelegate eval_result; public static DynBlockDelegate eval_result;
static System.Collections.IDictionary upcall_receiver;
internal static object UpCall(object[] args) {
if (upcall_receiver == null)
upcall_receiver = (System.Collections.IDictionary)
up_domain.CreateInstanceAndUnwrap("CompilerBlob", "Niecza.UpcallReceiver");
return upcall_receiver[args];
}
public static Frame simple_eval(Frame th, Variable str) { public static Frame simple_eval(Frame th, Variable str) {
if (up_domain == null) if (up_domain == null)
return Kernel.Die(th, "Cannot eval; no compiler available"); return Kernel.Die(th, "Cannot eval; no compiler available");
System.Collections.IDictionary r = (System.Collections.IDictionary)
up_domain.CreateInstanceAndUnwrap("CompilerBlob", "Niecza.UpcallReceiver");
SubInfo outer = th.caller.info; SubInfo outer = th.caller.info;
string msg = (string) r[new object[] { "eval", string msg = (string) UpCall(new object[] { "eval",
str.Fetch().mo.mro_raw_Str.Get(str), str.Fetch().mo.mro_raw_Str.Get(str),
new Niecza.CLRBackend.Handle(outer) new Niecza.CLRBackend.Handle(outer)
}]; });
if (msg != null && msg != "") if (msg != null && msg != "")
return Kernel.Die(th, msg); return Kernel.Die(th, msg);
return th.MakeChild(null, new SubInfo("boot-" + return th.MakeChild(null, new SubInfo("boot-" +
Expand Down
4 changes: 2 additions & 2 deletions lib/CodeGen.cs
Expand Up @@ -3559,8 +3559,8 @@ public class DowncallReceiver : CallReceiver {
return null; return null;
} else if (cmd == "new_unit") { } else if (cmd == "new_unit") {
return new Handle(new RuntimeUnit((string)args[1], return new Handle(new RuntimeUnit((string)args[1],
(string)args[2], (string)args[3], (string)args[4], (string)args[2], (string)args[3],
(bool)args[5], (bool)args[6])); (bool)args[4], (bool)args[5]));
} else if (cmd == "set_current_unit") { } else if (cmd == "set_current_unit") {
Backend.currentUnit = (RuntimeUnit)Handle.Unbox(args[1]); Backend.currentUnit = (RuntimeUnit)Handle.Unbox(args[1]);
Kernel.currentGlobals = Backend.currentUnit.globals; Kernel.currentGlobals = Backend.currentUnit.globals;
Expand Down
39 changes: 33 additions & 6 deletions lib/Kernel.cs
Expand Up @@ -343,7 +343,8 @@ public class StashEnt : IFreeze {
class CORESavedAttribute : Attribute { } class CORESavedAttribute : Attribute { }


public sealed class RuntimeUnit : IFreeze { public sealed class RuntimeUnit : IFreeze {
public string name, filename, modtime, asm_name, dll_name; public string name, filename, source, asm_name, dll_name;
public HashSet<RuntimeUnit> depended_units;
public Dictionary<string, StashEnt> globals; public Dictionary<string, StashEnt> globals;
public SubInfo mainline, bottom; public SubInfo mainline, bottom;
public bool is_mainish; public bool is_mainish;
Expand All @@ -370,11 +371,13 @@ class IdentityComparer : IEqualityComparer<object> {


private RuntimeUnit() { } private RuntimeUnit() { }


public RuntimeUnit(string name, string filename, string modtime, public RuntimeUnit(string name, string filename, string source,
string obj_dir, bool main, bool runnow) { bool main, bool runnow) {
this.name = name; this.name = name;
this.filename = filename; this.filename = filename;
this.modtime = modtime; this.source = source;
this.depended_units = new HashSet<RuntimeUnit>();
this.depended_units.Add(this);
this.globals = new Dictionary<string,StashEnt>(); this.globals = new Dictionary<string,StashEnt>();
this.stubbed_stashes = new List<KeyValuePair<int,STable>>(); this.stubbed_stashes = new List<KeyValuePair<int,STable>>();
this.is_mainish = main; this.is_mainish = main;
Expand Down Expand Up @@ -655,9 +658,22 @@ class IdentityComparer : IEqualityComparer<object> {
void IFreeze.Freeze(FreezeBuffer fb) { void IFreeze.Freeze(FreezeBuffer fb) {
fb.Byte((byte)SerializationCode.RuntimeUnit); fb.Byte((byte)SerializationCode.RuntimeUnit);


// put this FIRST so that we can bail out in Thaw if need be
fb.String(name); fb.String(name);
RuntimeUnit[] dep = new List<RuntimeUnit>(depended_units).ToArray();
Array.Sort<RuntimeUnit>(dep, (a, b) =>
string.CompareOrdinal(a.name, b.name));
string[] srcinfo = new string[dep.Length * 2];
for (int i = 0; i < dep.Length; i++) {
srcinfo[i*2] = dep[i].name;
srcinfo[i*2+1] = Utils.HashToStr(
ObjectRegistry.hash.ComputeHash(
new UTF8Encoding().GetBytes(dep[i].source)));
}
fb.Strings(srcinfo);

fb.String(filename); fb.String(filename);
fb.String(modtime); fb.String(source);
fb.String(asm_name); fb.String(asm_name);
fb.String(dll_name); fb.String(dll_name);


Expand Down Expand Up @@ -689,8 +705,19 @@ class IdentityComparer : IEqualityComparer<object> {
tb.Register(n); tb.Register(n);


n.name = tb.String(); n.name = tb.String();
string[] srcinfo = tb.Strings();
if (Builtins.up_domain != null) {
object[] args = new object[srcinfo.Length + 1];
Array.Copy(srcinfo, 0, args, 1, srcinfo.Length);
args[0] = "check_dated";
string result = (string) Builtins.UpCall(args);
if (result != "ok")
throw new ThawException("dated sources");
}
// load assembly here

n.filename = tb.String(); n.filename = tb.String();
n.modtime = tb.String(); n.source = tb.String();
n.asm_name = tb.String(); n.asm_name = tb.String();
n.dll_name = tb.String(); n.dll_name = tb.String();


Expand Down
19 changes: 5 additions & 14 deletions lib/Serialize.cs
Expand Up @@ -60,7 +60,7 @@ struct ObjRef {
Dictionary<string,SerUnit> units = Dictionary<string,SerUnit> units =
new Dictionary<string,SerUnit>(); new Dictionary<string,SerUnit>();


static readonly HashAlgorithm hash = SHA256.Create(); internal static readonly HashAlgorithm hash = SHA256.Create();
static readonly string signature = "Niecza-Serialized-Module"; static readonly string signature = "Niecza-Serialized-Module";
static readonly int version = 1; static readonly int version = 1;


Expand Down Expand Up @@ -708,19 +708,10 @@ class ThawBuffer {
return su.bynum[ix]; return su.bynum[ix];


badhash: badhash:
StringBuilder sb = new StringBuilder(); throw new ThawException(string.Format("Hash mismatch for " +
sb.AppendFormat("Hash mismatch for unit {0} referenced from {1}", "unit {0} referenced from {1}, wanted {2}, got {3}",
su.name, unit.name); su.name, unit.name, Utils.HashToStr(unit.hash),

Utils.HashToStr(su.hash)));
sb.Append(", wanted ");
foreach (byte b in hash)
sb.AppendFormat("{0:X2}", b);

sb.Append(", got ");
foreach (byte b in su.hash)
sb.AppendFormat("{0:X2}", b);

throw new ThawException(sb.ToString());
} }
} }


Expand Down
9 changes: 9 additions & 0 deletions lib/Utils.cs
Expand Up @@ -515,6 +515,15 @@ public class Subscription {
} }


public class Utils { public class Utils {
public static string HashToStr(byte[] hash) {
char[] buf = new char[hash.Length * 2];
for (int i = 0; i < hash.Length; i++) {
buf[i*2] = "0123456789abcdef"[hash[i] >> 4];
buf[i*2+1] = "0123456789abcdef"[hash[i] & 15];
}
return new string(buf);
}

public static void HexDump(byte[] heap) { public static void HexDump(byte[] heap) {
for (int offs = 0; offs < heap.Length; offs += 16) { for (int offs = 0; offs < heap.Length; offs += 16) {
Console.Write("{0:X6} ", offs); Console.Write("{0:X6} ", offs);
Expand Down
13 changes: 13 additions & 0 deletions src/CompilerBlob.cs
Expand Up @@ -2,6 +2,7 @@
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
using System.Security.Cryptography;
using System.IO; using System.IO;


namespace Niecza { namespace Niecza {
Expand Down Expand Up @@ -173,5 +174,17 @@ public class Downcaller {
refs.CopyTo(args, 3); refs.CopyTo(args, 3);
return DCResult(RawDowncall(args)); return DCResult(RawDowncall(args));
} }

public static string DoHash(string input) {
HashAlgorithm sha = SHA256.Create();
byte[] ibytes = new UTF8Encoding().GetBytes(input);
byte[] hash = sha.ComputeHash(ibytes);
char[] buf = new char[hash.Length * 2];
for (int i = 0; i < hash.Length; i++) {
buf[i*2] = "0123456789abcdef"[hash[i] >> 4];
buf[i*2+1] = "0123456789abcdef"[hash[i] & 15];
}
return new string(buf);
}
} }
} }
5 changes: 2 additions & 3 deletions src/NieczaBackendDotnet.pm6
Expand Up @@ -301,7 +301,6 @@ class Unit {
} }
} }


method create_unit($name, $filename, $modtime, $main, $run) { method create_unit($name, $filename, $source, $main, $run) {
downcall("new_unit", ~$name, ~$filename, ~$modtime, downcall("new_unit", ~$name, ~$filename, ~$source, ?$main, ?$run);
~$!obj_dir, ?$main, ?$run);
} }
2 changes: 1 addition & 1 deletion src/NieczaFrontendSTD.pm6
Expand Up @@ -244,7 +244,7 @@ method parse(:$unitname, :$filename, :$modtime, :$source, :$outer, :$run, :$main
my $*UNIT; my $*UNIT;
my $*CCSTATE; my $*BORG; my %*RX; my $*XACT; my $*VAR; my $*IN_REDUCE; my $*CCSTATE; my $*BORG; my %*RX; my $*XACT; my $*VAR; my $*IN_REDUCE;


my $*unit = $*backend.create_unit($unitname, $filename, $modtime, $main, $run); my $*unit = $*backend.create_unit($unitname, $filename, $source, $main, $run);
%*units{$unitname} = $*unit; %*units{$unitname} = $*unit;
$*unit.set_current; $*unit.set_current;
my $*settingref = $*niecza_outer_ref || my $*settingref = $*niecza_outer_ref ||
Expand Down

0 comments on commit eee0cbb

Please sign in to comment.