3541 lines · 70.4 KB · Brainfuck
RawDownload
implement JavaClassLoader; ##	Java Class Loader.# include "sys.m";	sys:	Sys; stderr:	ref Sys->FD; include "keyring.m";	kr:	Keyring; include "string.m";	str:    String; include "math.m";	math:	Math; include "hash.m";	hash:	Hash; include "loader.m";include "classloader.m";	ld:		Loader;	Niladt:		import Loader;	jassist:	JavaAssist;	jtrace:		JavaTrace; 	JDEBUG, JVERBOSE:	import JavaTrace; 	getint, getintarray, getptr:		import jassist;	getreloc, getrtreloc, getstring:	import jassist;	getclassadt, getabsint, getadtstring:	import jassist;	getbytearray, getstrarray, arrayof:	import jassist;	getmd, putclass, putint, putmod:	import jassist;	putobj, putptr, putstring, makeadt:	import jassist;	bytearraytoJS, intarraytoJS:		import jassist;	bigarraytoJS, realarraytoJS:		import jassist;	ArraytoJS, JStoObject:			import jassist; this:		JavaClassLoader;thisnil:	Nilmod;sysnil:		Nilmod;loadlinks:	array of Loader->Link;syslinks:	array of Loader->Link;relocs:		list of ref Class;relocd:		list of ref Class;interf:		list of ref Class;interfx:	list of ref Class;initcl:		list of ref Class;main:		ref Class;arrayclass:	ref Class;arraymd:	ref Loader->Niladt;stringclass:	ref Class;fsindir:	int;cur:		string; interfaces:	array of ref Class;ninterfaces:	int = 0;linterfaces:	int = 0; INITINTER:	con 32; acqchan:	chan of int;relchan:	chan of int;exitchan:	chan of int; MSHUTDOWN, MENTER, MEXIT, MWAIT, MNOTIFY, MSLEEP, MINTERRUPT, MTIMER, MSYNC:		con iota; monitorctl:	chan of (int, ref ThreadData, ref Object, int);threadctl:	chan of (ref ThreadData, int); threadcount:	int = 0;daemoncount:	int = 0;stopped:	int = 0; ident:		con "ClassLoader";warn:		int = 1;debug:		int = 0;verbose:	int = 0;errors:		int = 0; # for generating ClassLoader exceptions use# the following con's.  They will be turned# into a corresponding Java Exception by # sysexcetion# when thrown the format is:# raise( ex +":"+detail );# see loaderror();## NOTE: the "raise" string has limited size#       hence the "e"+<int>#JCLDREX       : con "JLD:";   #prefixnoclassdeffound,classcircularity,classformat,nosuchmethod,nosuchfield,unsatisfiedlink,linkageerr,exceptionininitializer	          : con "e" + (string iota); badcallindex  : con "call index";nocloneindex  : con "clone index"; encoding :=	array[] of{	'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',	'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',	'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',	'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',	'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',	'o', 'p', 'q', 'r', 's', 't', 'u', 'v',	'w', 'x', 'y', 'z', '0', '1', '2', '3',	'4', '5', '6', '7', '8', '9', '+', '-',}; bits :=		array[] of { 16r80, 16r40, 16r20, 16r10, 16r08, 16r04, 16r02, 16r01 };mbits :=	array[] of { 16r80, 16r20, 16r08, 16r02 }; ##	Diagnostics.# mesg(s: string){	sys->fprint(stderr, "%s: %s\n", ident, s);} diag(s: string){	if (cur != nil)		s = cur + ": " + s;	mesg(s);	errors++;} loaderror( ex : string, msg : string ){	s := msg; 	# if prefix exists then just rethrow msg	if ( str->prefix( JCLDREX+ex, msg ) == 0 )	{		if ( cur != nil )			s = cur +": " + s; 		s = sys->sprint( "%s%s:%s", JCLDREX, ex, s );	} 	trace(JDEBUG,s); 	raise s;} error(s: string){	if ( s == nil )		s = JCLDREX + "fatal error";	else	{		# if prefix exists then just re-throw s		if ( str->prefix(JCLDREX,s) == 0 )		{			# add prefix to tag as a Loader ex			s = sys->sprint( "%s%s:%s", JCLDREX, s, cur );		}	} 	trace(JDEBUG,s); 	raise s;} warning(s: string){	if (!warn)		return;	if (cur != nil)		s = cur + ": " + s;	sys->fprint(stderr, "%s: warning: %s\n", ident, s);} trace(c: int, s: string){	if (jtrace != nil)		jtrace->trace(c, s);} loadtrace(){	if (jtrace != nil)		return;	jtrace = load JavaTrace JavaTrace->PATH;	if (jtrace == nil)		error(sys->sprint("could not load %s: %r", JavaTrace->PATH));	jtrace->init(jassist);} ##	Load synchronization.  Allow only one thread to be loading at a time.# loadsync(){	for (;;) {		alt {		<- acqchan =>			;		<- exitchan =>			return;		}		alt {		<- relchan =>			;		<- exitchan =>			return;		}	}} acquire(){	acqchan <-= 0;} release(){	relchan <-= 0;} context: ref Draw->Context; ##	Initialize loader.  Entry.#init(j: JavaClassLoader, ctxt: ref Draw->Context){	sys = load Sys Sys->PATH;	stderr = sys->fildes(2);	context = ctxt;	kr = load Keyring Keyring->PATH;	if (kr == nil)		error(sys->sprint("could not load %s: %r", Keyring->PATH));	str = load String String->PATH;	if (str == nil)		error(sys->sprint("could not load %s: %r", String->PATH));	math = load Math Math->PATH;	if (math == nil)		error(sys->sprint("could not load %s: %r", Math->PATH));	math->FPcontrol(0, Math->INVAL|Math->ZDIV|Math->OVFL|Math->UNFL|Math->INEX);	hash = load Hash Hash->PATH;	if (hash == nil)		error(sys->sprint("could not load %s: %r", Hash->PATH));	ld = load Loader Loader->PATH;	if (ld == nil)		error(sys->sprint("could not load %s: %r", Loader->PATH));	jassist = load JavaAssist JavaAssist->PATH;	if (jassist == nil)		error(sys->sprint("could not load %s: %r", JavaAssist->PATH));	if (verbose) {		loadtrace();		if (debug)			jtrace->level = JDEBUG;		else			jtrace->level = JVERBOSE;	}	fsindir = jassist->little_endian();	this = j;	thisnil = jassist->jclnilmod(j);	sysnil = jassist->sysnilmod(sys);	loadlinks = ld->link(thisnil);	syslinks = ld->link(sysnil);	if (loadlinks == nil || syslinks == nil)		error(sys->sprint("Loader->link failed: %r"));	initloadhash();	acqchan = chan of int;	relchan = chan of int;	exitchan = chan of int;	spawn loadsync();	monitorctl = chan of (int, ref ThreadData, ref Object, int);	spawn monitor();	threadctl = chan of (ref ThreadData, int);	spawn threadmanager();	jniinit();} loadarrayclass(){	arrayclass = loader(ARRAYCLASS);	arraymd = arrayclass.moddata;} loadstringclass(){	stringclass = loader(STRINGCLASS);} ##	Native interface initialization.#jniinit(){	j := load JavaNative JavaNative->PATH;	if (j == nil)		error(sys->sprint("could not load %s: %r", JavaNative->PATH));	e := j->init(sys, ld, this, jassist);	if (e != nil)		error(sys->sprint("JavaNative->init failed: %s", e));} ##	Shutdown loader.  Entry.#shutdown(){	if (exitchan != nil) {		exitchan <-= 0;		exitchan = nil;	}	if (monitorctl != nil) {		monitorctl <-= (MSHUTDOWN, nil, nil, 0);		monitorctl = nil;	}	if (threadctl != nil) {		threadctl <-= (nil, ThreadData.SHUTDOWN);		threadctl = nil;	}} ##	Load a class and print information about it.#	Does not resolve the class and should not be#	called in the execution environment.  Entry.#info(name: string){	c := getclass(name);	if (c.state == NEW)		c.loadclass();	loadtrace();	jtrace->info(c);} ##	Perform outstanding relocation on loaded classes.#doreloc(){	#	#	Load classes we need for relocation.	#	while (relocs != nil) {		r: list of ref Class;		r = nil;		reloc := hd relocs;		relocs = tl relocs;		trace(JDEBUG, sys->sprint("reloc %s", reloc.name));		i := CLASSREF;		while ((s := getstring(reloc.mod, i)) != nil) {			if (s != LOADER)				r = loadhierarchy(s) :: r;			else				r = nil :: r;			i += 2 * WORDZ;		}		reloc.refs = mkclarray(r);		reloc.relocate();		relocd = reloc :: relocd;	}	#	#	Patch the module data of the relocated classes.	#	while (relocd != nil) {		patch := hd relocd;		relocd = tl relocd;		trace(JDEBUG, sys->sprint("modpatch %s", patch.name));		patch.modpatch();		if (patch.native != nil || patch.classinit != nil) {			initcl = patch :: initcl;			patch.state = LOADED;		} else			patch.state = INITED;	}	#	#	Extend interfaces.	#	while (interfx != nil) {		extend := hd interfx;		interfx = tl interfx;		extend.interdirect = extend.interextends;		extend.extinterfaces();	}	#	#	Make interface linkage tables for classes that implement interfaces.	#	while (interf != nil) {		inter := hd interf;		interf = tl interf;		inter.interdirect = inter.interextends;		inter.linkinterfaces();	}	#	#	Call class initializers.	#	initc : ref Class;	t     : ref ThreadData; 	{		while (initcl != nil) {			initc = hd initcl;			initcl = tl initcl;			initc.state = INITED;			trace(JVERBOSE, sys->sprint("Switching class %s state to INITED", initc.name));			t = getthreaddata();			release();			unblock(t);			if (initc.native != nil)				initc.initjni();			if (initc.classinit != nil) {				trace(JVERBOSE, sys->sprint("%s-><clinit>()", initc.name));				jassist->mcall0(initc.mod, initc.classinit.value);				trace(JDEBUG, sys->sprint("clinit done"));			}			block(t);			acquire();		}	}	exception e	{		"*disabled" =>			#NOTE: a raise is only expected from the init calls therefore			#      when we reach here we need to block and acquire			block(t);			acquire();			trace(JVERBOSE, sys->sprint("Some exception: %s", e));			raise e;			if ( str->prefix(JCLDREX+exceptionininitializer, e ) == 1 )				loaderror(exceptionininitializer, e ); #rethrow			else						{				# clear any java exception; we are replacing it				t.culprit = nil;				loaderror(exceptionininitializer, sys->sprint("%s[unk]", initc.name));			}	}} ##	Main "load class" routine.  Load a class hierarchy and#	its dependencies and prepare it for use.  Entry.#	No return on error.#loader(name: string): ref Class{	released := 0;	t := getthreaddata();	{		trace(JDEBUG, sys->sprint("load class %s", name));		block(t);		acquire();		c := loadhierarchy(name);		if (relocs != nil)			doreloc();		release();		unblock(t);		released = 1;		trace(JDEBUG, sys->sprint("loader() exit"));#		if (errors)#			error(nil);		return c;	}	exception e	{		"*disabled" =>			if(released == 0) {				release();				unblock(t);			}			if (e == nil)				e = "exit";						if ( str->prefix(JCLDREX, e) == 1 )				error(e);						error( sys->sprint( "%s", e) );						#else if (e.name == noclassdeffound)			#{					#	error(nil);			#}			#else			#	error(sys->sprint("loader exception: %s: %s: %d", e.mod, e.name, e.pc));	}	return nil;

Lines 1–500 of 3541.