Browse Source

added compiler generated calls to LeaveA2 / ReenterA2

git-svn-id: https://svn.inf.ethz.ch/svn/lecturers/a2/trunk@7256 8c9fc860-2736-0410-a75d-ab315db34111
felixf 8 years ago
parent
commit
9720f5a024
3 changed files with 34 additions and 64 deletions
  1. 20 2
      source/FoxIntermediateBackend.Mod
  2. 11 59
      source/Generic.Win32.Kernel32.Mod
  3. 3 3
      source/Win32.Objects.Mod

+ 20 - 2
source/FoxIntermediateBackend.Mod

@@ -5476,7 +5476,7 @@ TYPE
 			formalParameter: SyntaxTree.Parameter;
 			formalParameter: SyntaxTree.Parameter;
 			operand, returnValue: Operand;
 			operand, returnValue: Operand;
 			reg, size, mask, dest: IntermediateCode.Operand;
 			reg, size, mask, dest: IntermediateCode.Operand;
-			saved: RegisterEntry;
+			saved,saved2: RegisterEntry;
 			symbol: SyntaxTree.Symbol;
 			symbol: SyntaxTree.Symbol;
 			variable: SyntaxTree.Variable;
 			variable: SyntaxTree.Variable;
 			i,  parametersSize, returnTypeSize : LONGINT;
 			i,  parametersSize, returnTypeSize : LONGINT;
@@ -5898,6 +5898,12 @@ TYPE
 
 
 						
 						
 			ReleaseParameterRegisters();
 			ReleaseParameterRegisters();
+			
+			IF backend.preciseGC & ~isUnchecked & (procedureType.callingConvention = SyntaxTree.WinAPICallingConvention) THEN
+				SaveRegisters();ReleaseUsedRegisters(saved2);
+				CallThis(position,"Objects","LeaveA2",0);
+				RestoreRegisters(saved2);
+			END;
 			IF (procedureType.callingConvention = SyntaxTree.WinAPICallingConvention) OR SysvABI(procedureType.callingConvention) THEN
 			IF (procedureType.callingConvention = SyntaxTree.WinAPICallingConvention) OR SysvABI(procedureType.callingConvention) THEN
 				Emit(Call(position,operand.op,0));
 				Emit(Call(position,operand.op,0));
 			ELSE
 			ELSE
@@ -5913,6 +5919,16 @@ TYPE
 				return := NewRegisterOperand(IntermediateCode.GetType(system,procedureType.returnType));
 				return := NewRegisterOperand(IntermediateCode.GetType(system,procedureType.returnType));
 				Emit(Result(position,return));
 				Emit(Result(position,return));
 			END;
 			END;
+
+			IF  backend.preciseGC & ~isUnchecked & (procedureType.callingConvention = SyntaxTree.WinAPICallingConvention) THEN
+				IF  (procedureType.returnType # NIL) & ~structuredReturnType  THEN 
+					Emit(Push(position, return));
+					CallThis(position,"Objects","ReenterA2",0);
+					Emit(Pop(position, return));
+				ELSE
+					CallThis(position,"Objects","ReenterA2",0);
+				END;
+			END;
 			
 			
 			(* === return parameter space === *)
 			(* === return parameter space === *)
 			IF (procedureType.callingConvention = SyntaxTree.WinAPICallingConvention) & passByRegister THEN
 			IF (procedureType.callingConvention = SyntaxTree.WinAPICallingConvention) & passByRegister THEN
@@ -13457,6 +13473,7 @@ TYPE
 		dump-: Basic.Writer;
 		dump-: Basic.Writer;
 		cellsAreObjects: BOOLEAN;
 		cellsAreObjects: BOOLEAN;
 		preciseGC, writeBarriers: BOOLEAN; 
 		preciseGC, writeBarriers: BOOLEAN; 
+		experiment: BOOLEAN; 
 		
 		
 		PROCEDURE &InitIntermediateBackend*;
 		PROCEDURE &InitIntermediateBackend*;
 		BEGIN
 		BEGIN
@@ -13564,6 +13581,7 @@ TYPE
 			options.Add(0X,"cellsAreObjects", Options.Flag);
 			options.Add(0X,"cellsAreObjects", Options.Flag);
 			options.Add(0X,"preciseGC", Options.Flag);
 			options.Add(0X,"preciseGC", Options.Flag);
 			options.Add(0X,"writeBarriers", Options.Flag);
 			options.Add(0X,"writeBarriers", Options.Flag);
+			options.Add(0X,"experiment", Options.Flag);
 		END DefineOptions;
 		END DefineOptions;
 
 
 		PROCEDURE GetOptions(options: Options.Options);
 		PROCEDURE GetOptions(options: Options.Options);
@@ -13594,7 +13612,7 @@ TYPE
 			cellsAreObjects := options.GetFlag("cellsAreObjects");
 			cellsAreObjects := options.GetFlag("cellsAreObjects");
 			preciseGC := options.GetFlag("preciseGC");
 			preciseGC := options.GetFlag("preciseGC");
 			writeBarriers := options.GetFlag("writeBarriers");
 			writeBarriers := options.GetFlag("writeBarriers");
-
+			experiment := options.GetFlag("experiment");
 		END GetOptions;
 		END GetOptions;
 
 
 		PROCEDURE DefaultSymbolFileFormat(): Formats.SymbolFileFormat;
 		PROCEDURE DefaultSymbolFileFormat(): Formats.SymbolFileFormat;

+ 11 - 59
source/Generic.Win32.Kernel32.Mod

@@ -419,17 +419,10 @@ VAR
 																			 bInheritHandle: BOOL;
 																			 bInheritHandle: BOOL;
 																			 dwOptions: SET ): BOOL;
 																			 dwOptions: SET ): BOOL;
 	(** The EnterCriticalSection function waits for ownership of the specified critical section object. *)
 	(** The EnterCriticalSection function waits for ownership of the specified critical section object. *)
-	enterCriticalSection: PROCEDURE {WINAPI} ( VAR lpCriticalSection: CriticalSection );
+	EnterCriticalSection-: PROCEDURE {WINAPI} ( VAR lpCriticalSection: CriticalSection );
 	
 	
-	PROCEDURE EnterCriticalSection*(VAR lpCriticalSection: CriticalSection);
-	BEGIN
-		LeaveA2;
-		enterCriticalSection(lpCriticalSection);
-		ReenterA2;
-	END EnterCriticalSection;
-
 	(** The EscapeCommFunction function directs a specified communications device to perform an extended function. *)
 	(** The EscapeCommFunction function directs a specified communications device to perform an extended function. *)
-	VAR EscapeCommFunction-: PROCEDURE {WINAPI} ( hFile: HANDLE;
+	EscapeCommFunction-: PROCEDURE {WINAPI} ( hFile: HANDLE;
 																					  dwFunc: LONGINT ): BOOL;
 																					  dwFunc: LONGINT ): BOOL;
 	(** The ExitProcess function ends a process and all its threads. *)
 	(** The ExitProcess function ends a process and all its threads. *)
 	ExitProcess-: PROCEDURE {WINAPI} ( uExitCode: LONGINT );
 	ExitProcess-: PROCEDURE {WINAPI} ( uExitCode: LONGINT );
@@ -634,18 +627,11 @@ VAR
 	InterlockedIncrement-: PROCEDURE {WINAPI} ( VAR lpAddend: LONGINT ): LONGINT;
 	InterlockedIncrement-: PROCEDURE {WINAPI} ( VAR lpAddend: LONGINT ): LONGINT;
 
 
 	(** The LeaveCriticalSection function releases ownership of the specified critical section object. *)
 	(** The LeaveCriticalSection function releases ownership of the specified critical section object. *)
-	leaveCriticalSection-: PROCEDURE {WINAPI} ( VAR lpCriticalSection: CriticalSection );
-	
-	PROCEDURE LeaveCriticalSection*(VAR lpCriticalSection: CriticalSection);
-	BEGIN
-		LeaveA2;
-		leaveCriticalSection(lpCriticalSection);
-		ReenterA2;
-	END LeaveCriticalSection;
-	
+	LeaveCriticalSection-: PROCEDURE {WINAPI} ( VAR lpCriticalSection: CriticalSection );
+		
 	(** The LocalFileTimeToFileTime function converts a local file time to a file time based on the Coordinated
 	(** The LocalFileTimeToFileTime function converts a local file time to a file time based on the Coordinated
 			Universal Time (UTC). *)
 			Universal Time (UTC). *)
-	VAR LocalFileTimeToFileTime-: PROCEDURE {WINAPI} ( VAR lpLocalFileTime: FileTime;
+	LocalFileTimeToFileTime-: PROCEDURE {WINAPI} ( VAR lpLocalFileTime: FileTime;
 																						   VAR lpFileTime: FileTime ): BOOL;
 																						   VAR lpFileTime: FileTime ): BOOL;
 	(** The MoveFileEx function renames an existing file or directory. *)
 	(** The MoveFileEx function renames an existing file or directory. *)
 	MoveFileEx-: PROCEDURE {WINAPI} ( VAR lpExistingFileName, lpNewFileName: ARRAY   OF CHAR;
 	MoveFileEx-: PROCEDURE {WINAPI} ( VAR lpExistingFileName, lpNewFileName: ARRAY   OF CHAR;
@@ -674,25 +660,12 @@ VAR
 	(** Retrieves the cycle time for the specified thread (both user and kernel mode, Windows Vista and newer) *)
 	(** Retrieves the cycle time for the specified thread (both user and kernel mode, Windows Vista and newer) *)
 	QueryThreadCycleTime- : PROCEDURE {WINAPI} (hThread : HANDLE; VAR cycleTime : HUGEINT) : BOOL;
 	QueryThreadCycleTime- : PROCEDURE {WINAPI} (hThread : HANDLE; VAR cycleTime : HUGEINT) : BOOL;
 	(** The ReadFile function reads data from a file, starting at the position indicated by the file pointer. *)
 	(** The ReadFile function reads data from a file, starting at the position indicated by the file pointer. *)
-	readFile-: PROCEDURE {WINAPI} ( hFile: HANDLE;
+	ReadFile-: PROCEDURE {WINAPI} ( hFile: HANDLE;
 															  VAR lpBuffer: ARRAY OF SYSTEM.BYTE;
 															  VAR lpBuffer: ARRAY OF SYSTEM.BYTE;
 															  nNumberOfBytesToRead: LONGINT;
 															  nNumberOfBytesToRead: LONGINT;
 															  VAR lpNumberOfBytesRead: LONGINT;
 															  VAR lpNumberOfBytesRead: LONGINT;
 															  lpOverlapped: ADDRESS ): BOOL;
 															  lpOverlapped: ADDRESS ): BOOL;
 
 
-	PROCEDURE ReadFile- ( hFile: HANDLE;
-															  VAR lpBuffer: ARRAY OF SYSTEM.BYTE;
-															  nNumberOfBytesToRead: LONGINT;
-															  VAR lpNumberOfBytesRead: LONGINT;
-															  lpOverlapped: ADDRESS ): BOOL;
-	VAR b: BOOL;
-	BEGIN
-		LeaveA2;
-		b := readFile(hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped);
-		ReenterA2;
-		RETURN b;
-	END ReadFile;
-	VAR
 	(** The ReadProcessMemory function reads data from an area of memory in a specified process. *)
 	(** The ReadProcessMemory function reads data from an area of memory in a specified process. *)
 	ReadProcessMemory-: PROCEDURE {WINAPI} ( hProcess: HANDLE;
 	ReadProcessMemory-: PROCEDURE {WINAPI} ( hProcess: HANDLE;
 																				   lpBaseAddress: ADDRESS;
 																				   lpBaseAddress: ADDRESS;
@@ -792,32 +765,17 @@ VAR
 	WaitForSingleObject-: PROCEDURE {WINAPI} ( hHandle: HANDLE;
 	WaitForSingleObject-: PROCEDURE {WINAPI} ( hHandle: HANDLE;
 																				   dwMilliseconds: LONGINT ): LONGINT;
 																				   dwMilliseconds: LONGINT ): LONGINT;
 	(** The WriteFile function writes data to a file and is designed for both synchronous and asynchronous operation. *)
 	(** The WriteFile function writes data to a file and is designed for both synchronous and asynchronous operation. *)
-	writeFile-: PROCEDURE {WINAPI} ( hFile: HANDLE;
+	WriteFile-: PROCEDURE {WINAPI} ( hFile: HANDLE;
 															   CONST lpBuffer: ARRAY   OF SYSTEM.BYTE;
 															   CONST lpBuffer: ARRAY   OF SYSTEM.BYTE;
 															   nNumberOfBytesToWrite: LONGINT;
 															   nNumberOfBytesToWrite: LONGINT;
 															   VAR lpNumberOfBytesWritten: LONGINT;
 															   VAR lpNumberOfBytesWritten: LONGINT;
 															   lpOverlapped: ADDRESS ): BOOL;
 															   lpOverlapped: ADDRESS ): BOOL;
 	(** Thread abort notifier, parameter is the threads id. Note this should only be used in modules which
 	(** Thread abort notifier, parameter is the threads id. Note this should only be used in modules which
 			can't use the exception handling mechanism provided by module Exceptions. *)
 			can't use the exception handling mechanism provided by module Exceptions. *)
-	PROCEDURE WriteFile- ( hFile: HANDLE;
-															   CONST lpBuffer: ARRAY   OF SYSTEM.BYTE;
-															   nNumberOfBytesToWrite: LONGINT;
-															   VAR lpNumberOfBytesWritten: LONGINT;
-															   lpOverlapped: ADDRESS ): BOOL;
-	VAR b: BOOL;
-	BEGIN
-		LeaveA2;
-		b := writeFile(hFile,lpBuffer,nNumberOfBytesToWrite, lpNumberOfBytesWritten,lpOverlapped);
-		ReenterA2;
-		RETURN b;
-	END WriteFile;
-	VAR
 	
 	
 	(** Method used to write text to the Console. *)
 	(** Method used to write text to the Console. *)
 	OutputString*: PROCEDURE ( CONST a: ARRAY OF CHAR );
 	OutputString*: PROCEDURE ( CONST a: ARRAY OF CHAR );
 	
 	
-	(** methods to store the GC context before temporarily escaping to Windows -- required because GetContext does not work correctly any more  *)
-	LeaveA2*, ReenterA2*: PROCEDURE;
 
 
 	(* OutputString*: OutputStringProc; *)
 	(* OutputString*: OutputStringProc; *)
 	Shutdown*: PROCEDURE ( code: LONGINT );
 	Shutdown*: PROCEDURE ( code: LONGINT );
@@ -870,15 +828,9 @@ VAR
 		ExitProcess(l);
 		ExitProcess(l);
 	END ShutdownP;
 	END ShutdownP;
 	
 	
-	PROCEDURE Nothing;
-	BEGIN
-	END Nothing;
-
 	PROCEDURE Init*;
 	PROCEDURE Init*;
 	VAR mod: HMODULE;
 	VAR mod: HMODULE;
 	BEGIN
 	BEGIN
-		LeaveA2 := Nothing;
-		ReenterA2 := Nothing;
 		Shutdown := ShutdownP;
 		Shutdown := ShutdownP;
 		mod := LoadLibrary("Kernel32.DLL");
 		mod := LoadLibrary("Kernel32.DLL");
 		GetProcAddress(mod, "AllocConsole",SYSTEM.VAL(ADDRESS,AllocConsole));
 		GetProcAddress(mod, "AllocConsole",SYSTEM.VAL(ADDRESS,AllocConsole));
@@ -897,7 +849,7 @@ VAR
 		GetProcAddress(mod, "DeleteFileA",SYSTEM.VAL(ADDRESS,DeleteFile));
 		GetProcAddress(mod, "DeleteFileA",SYSTEM.VAL(ADDRESS,DeleteFile));
 		GetProcAddress(mod, "DisableThreadLibraryCalls",SYSTEM.VAL(ADDRESS,DisableThreadLibraryCalls));
 		GetProcAddress(mod, "DisableThreadLibraryCalls",SYSTEM.VAL(ADDRESS,DisableThreadLibraryCalls));
 		GetProcAddress(mod, "DuplicateHandle",SYSTEM.VAL(ADDRESS,DuplicateHandle));
 		GetProcAddress(mod, "DuplicateHandle",SYSTEM.VAL(ADDRESS,DuplicateHandle));
-		GetProcAddress(mod, "EnterCriticalSection",SYSTEM.VAL(ADDRESS,enterCriticalSection));
+		GetProcAddress(mod, "EnterCriticalSection",SYSTEM.VAL(ADDRESS,EnterCriticalSection));
 		GetProcAddress(mod, "EscapeCommFunction",SYSTEM.VAL(ADDRESS,EscapeCommFunction));
 		GetProcAddress(mod, "EscapeCommFunction",SYSTEM.VAL(ADDRESS,EscapeCommFunction));
 		GetProcAddress(mod, "ExitProcess",SYSTEM.VAL(ADDRESS,ExitProcess));
 		GetProcAddress(mod, "ExitProcess",SYSTEM.VAL(ADDRESS,ExitProcess));
 		GetProcAddress(mod, "ExitThread",SYSTEM.VAL(ADDRESS,ExitThread));
 		GetProcAddress(mod, "ExitThread",SYSTEM.VAL(ADDRESS,ExitThread));
@@ -965,7 +917,7 @@ VAR
 		GetProcAddress(mod, "InterlockedDecrement",SYSTEM.VAL(ADDRESS,InterlockedDecrement));
 		GetProcAddress(mod, "InterlockedDecrement",SYSTEM.VAL(ADDRESS,InterlockedDecrement));
 		GetProcAddress(mod, "InterlockedIncrement",SYSTEM.VAL(ADDRESS,InterlockedIncrement));
 		GetProcAddress(mod, "InterlockedIncrement",SYSTEM.VAL(ADDRESS,InterlockedIncrement));
 		GetProcAddress(mod, "IsDebuggerPresent",SYSTEM.VAL(ADDRESS,IsDebuggerPresent));
 		GetProcAddress(mod, "IsDebuggerPresent",SYSTEM.VAL(ADDRESS,IsDebuggerPresent));
-		GetProcAddress(mod, "LeaveCriticalSection",SYSTEM.VAL(ADDRESS,leaveCriticalSection));
+		GetProcAddress(mod, "LeaveCriticalSection",SYSTEM.VAL(ADDRESS,LeaveCriticalSection));
 		(* must be done by linker: GetProcAddress(mod, "LoadLibraryA",SYSTEM.VAL(ADDRESS,LoadLibrary)); *)
 		(* must be done by linker: GetProcAddress(mod, "LoadLibraryA",SYSTEM.VAL(ADDRESS,LoadLibrary)); *)
 		GetProcAddress(mod, "LocalFileTimeToFileTime",SYSTEM.VAL(ADDRESS,LocalFileTimeToFileTime));
 		GetProcAddress(mod, "LocalFileTimeToFileTime",SYSTEM.VAL(ADDRESS,LocalFileTimeToFileTime));
 		GetProcAddress(mod, "MoveFileExA",SYSTEM.VAL(ADDRESS,MoveFileEx));
 		GetProcAddress(mod, "MoveFileExA",SYSTEM.VAL(ADDRESS,MoveFileEx));
@@ -975,7 +927,7 @@ VAR
 		GetProcAddress(mod, "QueryPerformanceCounter",SYSTEM.VAL(ADDRESS,QueryPerformanceCounter));
 		GetProcAddress(mod, "QueryPerformanceCounter",SYSTEM.VAL(ADDRESS,QueryPerformanceCounter));
 		GetProcAddress(mod, "QueryPerformanceFrequency",SYSTEM.VAL(ADDRESS,QueryPerformanceFrequency));
 		GetProcAddress(mod, "QueryPerformanceFrequency",SYSTEM.VAL(ADDRESS,QueryPerformanceFrequency));
 		GetProcAddress(mod, "QueryThreadCycleTime", SYSTEM.VAL(ADDRESS, QueryThreadCycleTime));
 		GetProcAddress(mod, "QueryThreadCycleTime", SYSTEM.VAL(ADDRESS, QueryThreadCycleTime));
-		GetProcAddress(mod, "ReadFile",SYSTEM.VAL(ADDRESS,readFile));
+		GetProcAddress(mod, "ReadFile",SYSTEM.VAL(ADDRESS,ReadFile));
 		GetProcAddress(mod, "ReadProcessMemory",SYSTEM.VAL(ADDRESS,ReadProcessMemory));
 		GetProcAddress(mod, "ReadProcessMemory",SYSTEM.VAL(ADDRESS,ReadProcessMemory));
 		GetProcAddress(mod, "RemoveDirectoryA",SYSTEM.VAL(ADDRESS,RemoveDirectory));
 		GetProcAddress(mod, "RemoveDirectoryA",SYSTEM.VAL(ADDRESS,RemoveDirectory));
 		GetProcAddress(mod, "ResetEvent",SYSTEM.VAL(ADDRESS,ResetEvent));
 		GetProcAddress(mod, "ResetEvent",SYSTEM.VAL(ADDRESS,ResetEvent));
@@ -1013,7 +965,7 @@ VAR
 		GetProcAddress(mod, "VirtualAlloc",SYSTEM.VAL(ADDRESS,VirtualAlloc));
 		GetProcAddress(mod, "VirtualAlloc",SYSTEM.VAL(ADDRESS,VirtualAlloc));
 		GetProcAddress(mod, "VirtualFree",SYSTEM.VAL(ADDRESS,VirtualFree));
 		GetProcAddress(mod, "VirtualFree",SYSTEM.VAL(ADDRESS,VirtualFree));
 		GetProcAddress(mod, "WaitForSingleObject",SYSTEM.VAL(ADDRESS,WaitForSingleObject));
 		GetProcAddress(mod, "WaitForSingleObject",SYSTEM.VAL(ADDRESS,WaitForSingleObject));
-		GetProcAddress(mod, "WriteFile",SYSTEM.VAL(ADDRESS,writeFile));
+		GetProcAddress(mod, "WriteFile",SYSTEM.VAL(ADDRESS,WriteFile));
 		GetProcAddress(mod, "GlobalMemoryStatusEx",SYSTEM.VAL(ADDRESS,GlobalMemoryStatusEx));
 		GetProcAddress(mod, "GlobalMemoryStatusEx",SYSTEM.VAL(ADDRESS,GlobalMemoryStatusEx));
 		isEXE := hInstance = NULL;
 		isEXE := hInstance = NULL;
 		IF isEXE THEN hInstance := GetModuleHandle( NIL ) END;
 		IF isEXE THEN hInstance := GetModuleHandle( NIL ) END;

+ 3 - 3
source/Win32.Objects.Mod

@@ -428,7 +428,7 @@ END Yield;
 
 
 (** Return current process. (DEPRECATED, use ActiveObject) *)
 (** Return current process. (DEPRECATED, use ActiveObject) *)
 PROCEDURE CurrentProcess*( ): Process;
 PROCEDURE CurrentProcess*( ): Process;
-BEGIN
+BEGIN{UNCHECKED} (* makes sure that Enter and Leave are not emitted *)
 	RETURN SYSTEM.VAL(Process, Kernel32.TlsGetValue(tlsIndex));
 	RETURN SYSTEM.VAL(Process, Kernel32.TlsGetValue(tlsIndex));
 END CurrentProcess;
 END CurrentProcess;
 
 
@@ -1132,8 +1132,6 @@ BEGIN
 	ASSERT(t.handle # 0);
 	ASSERT(t.handle # 0);
 	Machine.Release(Machine.Objects);
 	Machine.Release(Machine.Objects);
 	InitEventHandling; (* implicit call of NewProcess! *)
 	InitEventHandling; (* implicit call of NewProcess! *)
-	Kernel32.LeaveA2 := LeaveA2;
-	Kernel32.ReenterA2 := ReenterA2;
 	InitGCHandling; (* do. *)
 	InitGCHandling; (* do. *)
 	Heaps.gcStatus := GCStatusFactory()
 	Heaps.gcStatus := GCStatusFactory()
 END Init;
 END Init;
@@ -1278,6 +1276,7 @@ VAR GetProcedureName*: PROCEDURE (pc: ADDRESS; VAR n: ARRAY OF CHAR; VAR spc: AD
 PROCEDURE LeaveA2;
 PROCEDURE LeaveA2;
 VAR cur: Process; ebp,n: ADDRESS;
 VAR cur: Process; ebp,n: ADDRESS;
 BEGIN
 BEGIN
+	IF clock = NIL THEN RETURN END;
 	cur := CurrentProcess();
 	cur := CurrentProcess();
 	IF cur # NIL THEN 
 	IF cur # NIL THEN 
 		ebp := Machine.CurrentBP();
 		ebp := Machine.CurrentBP();
@@ -1290,6 +1289,7 @@ END LeaveA2;
 PROCEDURE ReenterA2;
 PROCEDURE ReenterA2;
 VAR cur: Process;
 VAR cur: Process;
 BEGIN
 BEGIN
+	IF clock = NIL THEN RETURN END;
 	cur := CurrentProcess();
 	cur := CurrentProcess();
 	IF cur # NIL THEN 
 	IF cur # NIL THEN 
 		cur.gcContext.ebp := NIL;
 		cur.gcContext.ebp := NIL;