Jelajahi Sumber

Updated to newest version of Generic.Modules.Mod

git-svn-id: https://svn.inf.ethz.ch/svn/lecturers/a2/trunk@7332 8c9fc860-2736-0410-a75d-ab315db34111
negelef 8 tahun lalu
induk
melakukan
b000cda2ab
1 mengubah file dengan 156 tambahan dan 36 penghapusan
  1. 156 36
      source/Coop.Modules.Mod

+ 156 - 36
source/Coop.Modules.Mod

@@ -61,8 +61,8 @@ TYPE
 	(* all implicit or explicit pointers in the subsequent data structures are protected with one pointer array
 	*)
 
-	TypeDesc* = POINTER TO RECORD 
-		descSize-: LONGINT;
+	TypeDesc* = POINTER  TO RECORD 
+		descSize-: SIZE;
 		sentinel-: LONGINT;	(* = MPO-4 *)
 		tag-: ADDRESS; (* pointer to static type descriptor, only used by linker and loader *)
 		flags-: SET;
@@ -96,10 +96,10 @@ TYPE
 			sb*: ADDRESS; (* reference address between constants and local variables *)
 			entry*: POINTER TO ARRAY OF ADDRESS;
 			command*: POINTER TO ARRAY OF Command;
-			ptrAdr*: POINTER TO ARRAY OF ADDRESS;
-			typeInfo*: POINTER TO ARRAY OF TypeDesc;	(* traced explicitly in FindRoots *)
+			ptrAdr*: POINTER TO ARRAY OF ADDRESS; (* traced explicitly in FindRoots *)
+			typeInfo*: POINTER TO ARRAY OF TypeDesc;	
 			module*: POINTER TO ARRAY OF Module; (* imported modules: for reference counting *)
-			procTable*: ProcedureDescs; (* information inserted by loader, removed after use in Publish *)
+			procTable*: ProcedureDescs; (* information inserted by loader, sorted by pc after loading *)
 			data*, code*, staticTypeDescs* (* ug *), refs*: Bytes;
 			export*: ExportDesc;
 			term*: TerminationHandler;
@@ -108,6 +108,7 @@ TYPE
 			internal-: POINTER TO ARRAY OF ANY;
 			crc*: LONGINT;
 			body*: PROCEDURE;
+			flags*: SET;	 (* e.g. compilation flags *)
 
 	END Module;
 
@@ -130,10 +131,15 @@ VAR
 	
 	(* global sorted table of all procedures , basically for GC *)
 	procedureDescriptors-: ProcedureDescs;
-	mayAllocate: BOOLEAN;
 
 (** Register a module loader. *)
 
+PROCEDURE Halt(CONST reason: ARRAY OF CHAR);
+BEGIN
+	HALT(999);
+END Halt;
+
+
 PROCEDURE AddLoader*(CONST ext: ARRAY OF CHAR; proc: LoaderProc);
 BEGIN
 	Machine.Acquire(Machine.Modules);
@@ -172,17 +178,17 @@ BEGIN
 	to[j] := 0X
 END Append;
 
+
 (** Add a module to the pool of accessible modules, or return named module. *)
 PROCEDURE Publish*(VAR m: Module; VAR new: BOOLEAN);
-VAR n: Module; i: LONGINT;
+VAR n: Module; i: LONGINT; name: Name;
 BEGIN
 	Machine.Acquire(Machine.Modules);
 	n := root; WHILE (n # NIL) & (n.name # m.name) DO n := n.next END;
 	IF n # NIL THEN	(* module with same name exists, return it and ignore new m *)
-		m := n; new := FALSE;
-		Machine.Release(Machine.Modules);
+		m := n; new := FALSE
 	ELSE
-		IF TraceBoot THEN
+		IF TraceBoot OR trace THEN
 			Machine.Acquire(Machine.TraceOutput);
 			Trace.String("publish "); Trace.String(m.name);
 			Trace.Ln;
@@ -198,22 +204,90 @@ BEGIN
 		IF m.module # NIL THEN
 			FOR i := 0 TO LEN(m.module)-1 DO INC(m.module[i].refcnt) END;
 		END;
+
 		new := TRUE;
-		Machine.Release(Machine.Modules);
 	END;
+	Machine.Release(Machine.Modules);
 END Publish;
 
 PROCEDURE Initialize*(VAR module: Module);
-VAR new: BOOLEAN;
+VAR new: BOOLEAN; import: LONGINT;
 BEGIN
 	IF (module = NIL) THEN RETURN END;
 	Publish (module, new);
 	IF new THEN
-		IF module.body # NIL THEN module.body END;
+		FOR import := 0 TO LEN (module.module) - 1 DO
+			IF ~module.module[import].published THEN
+				ASSERT(register.first # NIL);
+				Initialize(module.module[import]);
+			END
+		END;
+		IF (module.code # NIL) & (LEN(module.code) > 0)  THEN
+			Machine.FlushDCacheRange(ADDRESSOF(module.code[0]), LEN(module.code));
+		END;
+		IF module.body # NIL THEN
+			module.body
+		END;
 		module.init := TRUE;
 	END;
 END Initialize;
 
+	VAR callagain: BOOLEAN;
+
+	PROCEDURE Initialize0*(module: Module);
+	VAR new: BOOLEAN;
+	BEGIN
+		(*TRACE(module.name);*)
+		(* module MUST have been removed from register list and must not have been initialized yet *)
+		(* ASSERT(module.next = NIL); *)
+		Publish (module, new);
+		callagain := FALSE;
+		IF new THEN
+			IF module.name = "Objects" THEN
+				callagain := TRUE;
+				module.init := TRUE;
+			END;
+			(*
+			Trace.Memory(SYSTEM.VAL(ADDRESS, module), 256);
+			TRACE(module, module.name, module.body);
+			TRACE(module);
+			TRACE(ADDRESS OF module.next);
+			TRACE(ADDRESS OF module.name);
+			TRACE(ADDRESS OF module.init);
+			TRACE(ADDRESS OF module.published);
+			TRACE(ADDRESS OF module.body);
+			TRACE(ADDRESS OF module.refcnt);
+			TRACE(ADDRESS OF module.sb);
+			TRACE(ADDRESS OF module.entry);
+			TRACE(ADDRESS OF module.command); 
+			TRACE(ADDRESS OF module.ptrAdr);
+			TRACE(ADDRESS OF module.typeInfo);
+			TRACE(ADDRESS OF module.module);
+			TRACE(ADDRESS OF module.procTable);
+			TRACE(ADDRESS OF module.ptrTable);
+			TRACE(ADDRESS OF module.data); 
+			TRACE(ADDRESS OF module.code);
+			TRACE(ADDRESS OF module.staticTypeDescs);
+			TRACE(ADDRESS OF module.refs);
+			TRACE(ADDRESS OF module.export);
+			TRACE(ADDRESS OF module.term);
+			TRACE(ADDRESS OF module.exTable);
+			TRACE(ADDRESS OF module.noProcs);
+			TRACE(ADDRESS OF module.firstProc);
+			TRACE(ADDRESS OF module.maxPtrs);
+			TRACE(ADDRESS OF module.crc);
+			TRACE(ADDRESS OF module.body);
+			*)
+						
+			IF module.body # NIL THEN module.body END;
+			IF callagain THEN
+				PublishRegisteredModules (* does not return on intel architecture. Returns on ARM but looses procedure stack frame: we are not allowed to refer to local variables after this *)
+			ELSE
+				module.init := TRUE;
+			END;
+		END;
+	END Initialize0;
+
 	(** Return the named module or NIL if it is not loaded yet. *)
 	PROCEDURE ModuleByName*(CONST name: ARRAY OF CHAR): Module;
 	VAR m: Module;
@@ -223,6 +297,20 @@ END Initialize;
 		Machine.Release(Machine.Modules);
 		RETURN m
 	END ModuleByName;
+	
+	PROCEDURE ByName(CONST name: ARRAY OF CHAR; VAR referenced: BOOLEAN): Module;
+	VAR m: Module;
+	BEGIN
+		Machine.Acquire(Machine.Modules);
+		referenced := FALSE;
+		m := root; WHILE (m # NIL) & (m.name # name) DO m := m.next END;
+		IF m = NIL THEN
+			referenced := TRUE;
+			m := register.first; WHILE (m#NIL) & (m.name # name) DO m := m.next END;
+		END;
+		Machine.Release(Machine.Modules);
+		RETURN m
+	END ByName;
 
 	(* Generate a module file name. *)
 	PROCEDURE GetFileName(CONST name, extension: ARRAY OF CHAR; VAR fileName: ARRAY OF CHAR);
@@ -312,16 +400,29 @@ END Initialize;
 		Quick(0, LEN(p)-1);
 	END SortExceptionTable;
 	
-		
 (** Load the module if it is not already loaded. *)	(* Algorithm J. Templ, ETHZ, 1994 *)
 PROCEDURE ThisModule*(CONST name: ARRAY OF CHAR; VAR res: LONGINT; VAR msg: ARRAY OF CHAR): Module;
-VAR m, p: Module; fileName: ARRAY 64 OF CHAR; i: LONGINT;
+VAR m: Module; fileName: ARRAY 64 OF CHAR; i: LONGINT; registered: BOOLEAN;
 BEGIN
-	res := Ok; msg[0] := 0X; m := ModuleByName(name);
-	IF m = NIL THEN
+	res := Ok; msg[0] := 0X; m := ByName(name, registered);
+	IF (m#NIL) & (registered) THEN
+		IF trace THEN
+			Machine.Acquire (Machine.TraceOutput);
+			Trace.String(">R>"); Trace.StringLn (name);
+			Machine.Release (Machine.TraceOutput);
+		END;
+		IF ~m.published THEN	(* no race on m.published, as update is done in Publish *)
+			Initialize(m);
+		END;
+		IF trace THEN
+			Machine.Acquire (Machine.TraceOutput);
+			Trace.String("<R<"); Trace.StringLn (name);
+			Machine.Release (Machine.TraceOutput);
+		END;
+	ELSIF m = NIL THEN
 		IF trace THEN
 			Machine.Acquire (Machine.TraceOutput);
-			Trace.String(">"); Trace.StringLn (name);
+			Trace.String(">L>"); Trace.StringLn (name);
 			Machine.Release (Machine.TraceOutput);
 		END;
 		IF numLoaders = 0 THEN
@@ -339,7 +440,6 @@ BEGIN
 			Trace.String("?"); Trace.StringLn (name);
 			Machine.Release (Machine.TraceOutput);
 		END;
-		p := m;
 		IF (m # NIL) & ~m.published THEN	(* no race on m.published, as update is done below in Publish *)
 			Initialize(m);
 		END;
@@ -350,7 +450,7 @@ BEGIN
 			ELSIF ~m.published THEN
 				Trace.String("not published "); Trace.StringLn(name)
 			ELSE
-				Trace.String("<"); Trace.StringLn (name);
+				Trace.String("<L<"); Trace.StringLn (name);
 			END;
 			Machine.Release (Machine.TraceOutput);
 		END;
@@ -495,7 +595,9 @@ BEGIN
 		IF m.term # NIL THEN	(* call termination handler *)
 			term := m.term; m.term := NIL; term	(* may trap *)
 		END;
-		Heaps.CleanupModuleFinalizers(ADDRESSOF(m.code[0]), LEN(m.code), m.name)
+		IF m.code # NIL THEN
+			Heaps.CleanupModuleFinalizers(ADDRESSOF(m.code[0]), LEN(m.code), m.name)
+		END;
 	END;
 	res := Ok; msg[0] := 0X;
 	Machine.Acquire(Machine.Modules);
@@ -558,7 +660,7 @@ BEGIN
 		(* clean up finalizers *)
 		m := root;
 		WHILE m # NIL DO
-			IF LEN(m.code)>0 THEN
+			IF (m.code # NIL) & (LEN(m.code)>0) THEN
 				Heaps.CleanupModuleFinalizers(ADDRESSOF(m.code[0]), LEN(m.code), m.name)
 			END;
 			m := m.next
@@ -633,18 +735,6 @@ BEGIN
 	RETURN m.init;
 END Initialized;
 
-PROCEDURE Init;
-VAR
-	s: ARRAY 4 OF CHAR;
-BEGIN
-	(* root and initBlock are initialized by the linker *)
-	shutdown := None;
-	numLoaders := 0;
-	freeRoot := NIL;
-	Machine.GetConfig("TraceModules", s);
-	trace := (s[0] = "1");
-END Init;
-
 PROCEDURE Register- (module {UNTRACED}: Module);
 BEGIN {UNCOOPERATIVE, UNCHECKED}
 	IF register.first = NIL THEN
@@ -684,10 +774,28 @@ BEGIN
 		m := register.first;
 		IF m.module # NIL THEN
 			FOR import := 0 TO LEN (m.module) - 1 DO
-				Initialize (m.module[import]);
+				IF ~m.module[import].published THEN
+					ASSERT(register.first # NIL);
+					(*prev := NIL;
+					cur := register.first;
+					WHILE (cur # NIL) & (cur # m.module[import]) DO
+						prev := cur;
+						cur := cur.next
+					END;
+					(*ASSERT(cur = m.module[import]);*)
+					ASSERT(cur = m.module[import]);
+					IF prev = NIL THEN
+						register.first := cur.next
+					ELSE
+						prev.next := cur.next;
+					END;
+					cur.next := NIL;
+					*)
+					Initialize0 (m.module[import]);
+				END
 			END;
 		END;
-		Initialize (m);
+		Initialize0 (m);
 	END;
 END PublishRegisteredModules;
 
@@ -721,6 +829,18 @@ BEGIN {UNCOOPERATIVE, UNCHECKED}
 	Environment.Exit (Environment.status);
 END Main;
 
+PROCEDURE Init;
+VAR
+	s: ARRAY 4 OF CHAR;
+BEGIN
+	(* root and initBlock are initialized by the linker *)
+	shutdown := None;
+	numLoaders := 0;
+	freeRoot := NIL;
+	Machine.GetConfig("TraceModules", s);
+	trace := (s[0] = "1");
+END Init;
+
 BEGIN
 	Init
 END Modules.