Permalink
Browse files

Add framework for detecting stale precompiled modules

  • Loading branch information...
1 parent 661b29c commit eee0cbbe4a49a29379939da6cc6ebee949afdcbd @sorear committed Oct 17, 2011
Showing with 74 additions and 30 deletions.
  1. +9 −4 lib/Builtins.cs
  2. +2 −2 lib/CodeGen.cs
  3. +33 −6 lib/Kernel.cs
  4. +5 −14 lib/Serialize.cs
  5. +9 −0 lib/Utils.cs
  6. +13 −0 src/CompilerBlob.cs
  7. +2 −3 src/NieczaBackendDotnet.pm6
  8. +1 −1 src/NieczaFrontendSTD.pm6
View
@@ -1618,16 +1618,21 @@ class SubstrLValue: Variable {
public static AppDomain up_domain;
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) {
if (up_domain == null)
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;
- string msg = (string) r[new object[] { "eval",
+ string msg = (string) UpCall(new object[] { "eval",
str.Fetch().mo.mro_raw_Str.Get(str),
new Niecza.CLRBackend.Handle(outer)
- }];
+ });
if (msg != null && msg != "")
return Kernel.Die(th, msg);
return th.MakeChild(null, new SubInfo("boot-" +
View
@@ -3559,8 +3559,8 @@ public class DowncallReceiver : CallReceiver {
return null;
} else if (cmd == "new_unit") {
return new Handle(new RuntimeUnit((string)args[1],
- (string)args[2], (string)args[3], (string)args[4],
- (bool)args[5], (bool)args[6]));
+ (string)args[2], (string)args[3],
+ (bool)args[4], (bool)args[5]));
} else if (cmd == "set_current_unit") {
Backend.currentUnit = (RuntimeUnit)Handle.Unbox(args[1]);
Kernel.currentGlobals = Backend.currentUnit.globals;
View
@@ -343,7 +343,8 @@ public class StashEnt : IFreeze {
class CORESavedAttribute : Attribute { }
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 SubInfo mainline, bottom;
public bool is_mainish;
@@ -370,11 +371,13 @@ class IdentityComparer : IEqualityComparer<object> {
private RuntimeUnit() { }
- public RuntimeUnit(string name, string filename, string modtime,
- string obj_dir, bool main, bool runnow) {
+ public RuntimeUnit(string name, string filename, string source,
+ bool main, bool runnow) {
this.name = name;
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.stubbed_stashes = new List<KeyValuePair<int,STable>>();
this.is_mainish = main;
@@ -655,9 +658,22 @@ class IdentityComparer : IEqualityComparer<object> {
void IFreeze.Freeze(FreezeBuffer fb) {
fb.Byte((byte)SerializationCode.RuntimeUnit);
+ // put this FIRST so that we can bail out in Thaw if need be
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(modtime);
+ fb.String(source);
fb.String(asm_name);
fb.String(dll_name);
@@ -689,8 +705,19 @@ class IdentityComparer : IEqualityComparer<object> {
tb.Register(n);
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.modtime = tb.String();
+ n.source = tb.String();
n.asm_name = tb.String();
n.dll_name = tb.String();
View
@@ -60,7 +60,7 @@ struct ObjRef {
Dictionary<string,SerUnit> units =
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 int version = 1;
@@ -708,19 +708,10 @@ class ThawBuffer {
return su.bynum[ix];
badhash:
- StringBuilder sb = new StringBuilder();
- sb.AppendFormat("Hash mismatch for unit {0} referenced from {1}",
- su.name, unit.name);
-
- 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());
+ throw new ThawException(string.Format("Hash mismatch for " +
+ "unit {0} referenced from {1}, wanted {2}, got {3}",
+ su.name, unit.name, Utils.HashToStr(unit.hash),
+ Utils.HashToStr(su.hash)));
}
}
View
@@ -515,6 +515,15 @@ public class Subscription {
}
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) {
for (int offs = 0; offs < heap.Length; offs += 16) {
Console.Write("{0:X6} ", offs);
View
@@ -2,6 +2,7 @@
using System.Collections;
using System.Collections.Generic;
using System.Text;
+using System.Security.Cryptography;
using System.IO;
namespace Niecza {
@@ -173,5 +174,17 @@ public class Downcaller {
refs.CopyTo(args, 3);
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);
+ }
}
}
@@ -301,7 +301,6 @@ class Unit {
}
}
-method create_unit($name, $filename, $modtime, $main, $run) {
- downcall("new_unit", ~$name, ~$filename, ~$modtime,
- ~$!obj_dir, ?$main, ?$run);
+method create_unit($name, $filename, $source, $main, $run) {
+ downcall("new_unit", ~$name, ~$filename, ~$source, ?$main, ?$run);
}
@@ -244,7 +244,7 @@ method parse(:$unitname, :$filename, :$modtime, :$source, :$outer, :$run, :$main
my $*UNIT;
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;
$*unit.set_current;
my $*settingref = $*niecza_outer_ref ||

0 comments on commit eee0cbb

Please sign in to comment.