## Manage run-time resolution information.# LTLOAD: con 6; ltload := array [LTLOAD] of { "java/lang/Class", "java/lang/Object", "java/lang/String", "java/lang/StringBuffer", "inferno/vm/Array", "java/io/Serializable"}; dortload(name: string): int{ i: int; if(name == nil || name == THISCLASS || name == SUPERCLASS) return 0; for(i = 0; i < LTLOAD; i++) { if(name == ltload[i]) return 0; } return 1;} RTHash: adt { rtc: ref RTClass; next: cyclic ref RTHash;}; rttbl := array [Hashsize] of ref RTHash; # hash table of ref'd classesnrtclasses: int; # no. of classes referenced rtappend(rtc: ref RTClass, rtr: ref RTReloc){ if(rtc.rtr == nil) rtc.rtr = rtr; else rtc.tail.next = rtr; rtc.tail = rtr;} rtprepend(rtc: ref RTClass, rtr: ref RTReloc){ if(rtc.rtr == nil) rtc.tail = rtr; rtr.next = rtc.rtr; rtc.rtr = rtr;} ## Add RTReloc entry.# addRTReloc(rtc: ref RTClass, field: string, sig: string, flags: int): ref RTReloc{ rtr: ref RTReloc; rtr = ref RTReloc(field, sig, flags, nil, nil); rtr.ipatch = ref Ipatch(0, 0, nil, nil); if(field[0] == '@') # these must go first in the list ! rtprepend(rtc, rtr); else rtappend(rtc, rtr); rtc.n += 1; return rtr;} ## Allocate a RTClass structure.# newRTClass(s: string): ref RTClass{ rtc: ref RTClass; rtc = ref RTClass(s, nil, nil, 0, 0); nrtclasses += 1; # want the order: @mp, @np, @adt, @Class addRTReloc(rtc, RCLASS, nil, 0); addRTReloc(rtc, RADT, nil, 0); addRTReloc(rtc, RNP, nil, 0); addRTReloc(rtc, RMP, nil, 0); return rtc;} ## Add RTClass entry for classname.# addRTClass(classname: string): ref RTClass{ h: int; he: ref RTHash; h = hashval(classname); he = ref RTHash(newRTClass(classname), rttbl[h]); rttbl[h] = he; return he.rtc;} ## Get RTClass entry for classname.# getRTClass(classname: string): ref RTClass{ he: ref RTHash; for(he = rttbl[hashval(classname)]; he != nil; he = he.next) { if(classname == he.rtc.classname) return he.rtc; } return addRTClass(classname);} ## Get RTReloc entry. Ignore signature if nil.# getRTReloc(rtc: ref RTClass, field: string, sig: string, flags: int): ref RTReloc{ rtr: ref RTReloc; lowflags: int; lowflags = 0; for(rtr = rtc.rtr; rtr != nil; rtr = rtr.next) { if(rtr.field == field && (sig == nil || rtr.sig == sig)) { if(rtr.flags >> 16 == 0) { rtr.flags |= flags; return rtr; } else if(rtr.flags >> 16 == flags >> 16) return rtr; lowflags = rtr.flags & 16rffff; } } return addRTReloc(rtc, field, sig, flags|lowflags);} ## Add instruction patch information to RTReloc rtr.# RTIpatch(rtr: ref RTReloc, i: ref Inst, operand: int, patchkind: int){ addDreloc(i, operand, patchkind); addIpatch(rtr.ipatch, i, operand, patchkind, SAVEINST);} ## Fix RTClass and RTReloc 'off' fields to prepare for instruction patch.# RTfixoff(off: int){ he: ref RTHash; i: int; if(nrtclasses > 0) { for(i = 0; i < Hashsize; i++) { for(he = rttbl[i]; he != nil; he = he.next) { he.rtc.off = off; off += he.rtc.n * IBY2WD; } } }} ## Patch instructions for run-time relocation.# doRTpatch(){ a: ref Addr; he: ref RTHash; ip: ref Ipatch; rtr: ref RTReloc; i, j: int; off, ltsize: int; if(nrtclasses == 0) return; ltsize = LTrelocsize(); for(i = 0; i < Hashsize; i++) { for(he = rttbl[i]; he != nil; he = he.next) { off = he.rtc.off - ltsize; for(rtr = he.rtc.rtr; rtr != nil; rtr = rtr.next) { ip = rtr.ipatch; for(j = 0; j < ip.n; j++) { case(ip.pinfo[j] & (16r3 << 2)) { PSRC => a = ip.i[j].s; PDST => a = ip.i[j].d; PMID => a = ip.i[j].m; } case (ip.pinfo[j] & 16r3) { PIMM or PDIND1 => a.ival = off; PSIND or PDIND2 => a.offset = off; } } off += IBY2WD; } } }} ## Size of Module Data space taken by run-time relocation information.# RTrelocsize(): int{ i: int; n: int; he: ref RTHash; n = 0; if(nrtclasses > 0) { for(i = 0; i < Hashsize; i++) { for(he = rttbl[i]; he != nil; he = he.next) n += he.rtc.n; } } return n * IBY2WD;} ## Fix type descriptor for run-time relocation information.# RTReloctid: int; RTrelocdesc(map: array of byte, off: int){ i: int; he: ref RTHash; rtr: ref RTReloc; if(nrtclasses == 0) return; RTReloctid = descid(3*IBY2WD, 1, array [1] of { byte 16rc0 }); for(i = 0; i < Hashsize; i++) { for(he = rttbl[i]; he != nil; he = he.next) { setbit(map, off); # @mp cell off += 4; setbit(map, off); # @np cell off += 4; setbit(map, off); # @adt cell off += 8; rtr = he.rtc.rtr.next.next.next.next; while(rtr != nil) { if(rtr.flags & (Rspecialmp | Rstaticmp)) setbit(map, off); off += 4; rtr = rtr.next; } } }} ## Write RTReloc array to .s file.# asmRTReloc(off: int, rtc: ref RTClass){ rtr: ref RTReloc; reloff: int; # relative offset for array elements if(rtc.n <= 4) return; reloff = 0; asmarray(off, RTReloctid, rtc.n - 4, reloff); # skip @mp @np @adt @Class rtr = rtc.rtr.next.next.next.next; while(rtr != nil) { asmstring(reloff, rtr.field); reloff += IBY2WD; if(rtr.sig != nil) asmstring(reloff, rtr.sig); reloff += IBY2WD; asmint(reloff, rtr.flags); reloff += IBY2WD; rtr = rtr.next; } bout.puts("\tapop\n");} ## Write RTClass information to .s file.# asmRTClass(off: int): int{ he: ref RTHash; i: int; ltsize: int; if(nrtclasses > 0) { ltsize = LTrelocsize(); for(i = 0; i < Hashsize; i++) { for(he = rttbl[i]; he != nil; he = he.next) { off += IBY2WD; # @mp cell asmstring(off, he.rtc.classname); off += IBY2WD; asmRTReloc(off, he.rtc); off += IBY2WD; asmint(off, he.rtc.off - ltsize); off += IBY2WD; # account for fields beyond @Class off += (he.rtc.n - 4) * IBY2WD; } } } return off;} ## Write RTReloc array to .dis file.# disRTReloc(off: int, rtc: ref RTClass){ rtr: ref RTReloc; reloff: int; # relative offset for array elements if(rtc.n <= 4) return; reloff = 0; disarray(off, RTReloctid, rtc.n - 4); # skip @mp @np @adt @Class rtr = rtc.rtr.next.next.next.next; while(rtr != nil) { disstring(reloff, rtr.field); reloff += IBY2WD; if(rtr.sig != nil) disstring(reloff, rtr.sig); reloff += IBY2WD; disint(reloff, rtr.flags); reloff += IBY2WD; rtr = rtr.next; } disapop();} ## Write RTClass information to .dis file.# disRTClass(off: int): int{ he: ref RTHash; i: int; ltsize: int; if(nrtclasses > 0) { ltsize = LTrelocsize(); for(i = 0; i < Hashsize; i++) { for(he = rttbl[i]; he != nil; he = he.next) { off += IBY2WD; # @mp cell disstring(off, he.rtc.classname); off += IBY2WD; disRTReloc(off, he.rtc); off += IBY2WD; disint(off, he.rtc.off - ltsize); off += IBY2WD; # account for fields beyond @Class off += (he.rtc.n - 4) * IBY2WD; } } } return off;}
#
# Manage run-time resolution information.
#
LTLOAD: con 6;
ltload := array [LTLOAD] of {
"java/lang/Class",
"java/lang/Object",
"java/lang/String",
"java/lang/StringBuffer",
"inferno/vm/Array",
"java/io/Serializable"
};
dortload(name: string): int
{
i: int;
if(name == nil || name == THISCLASS || name == SUPERCLASS)
return 0;
for(i = 0; i < LTLOAD; i++) {
if(name == ltload[i])
return 0;
}
return 1;
}
RTHash: adt {
rtc: ref RTClass;
next: cyclic ref RTHash;
};
rttbl := array [Hashsize] of ref RTHash; # hash table of ref'd classes
nrtclasses: int; # no. of classes referenced
rtappend(rtc: ref RTClass, rtr: ref RTReloc)
{
if(rtc.rtr == nil)
rtc.rtr = rtr;
else
rtc.tail.next = rtr;
rtc.tail = rtr;
}
rtprepend(rtc: ref RTClass, rtr: ref RTReloc)
{
if(rtc.rtr == nil)
rtc.tail = rtr;
rtr.next = rtc.rtr;
rtc.rtr = rtr;
}
#
# Add RTReloc entry.
#
addRTReloc(rtc: ref RTClass, field: string, sig: string, flags: int): ref RTReloc
{
rtr: ref RTReloc;
rtr = ref RTReloc(field, sig, flags, nil, nil);
rtr.ipatch = ref Ipatch(0, 0, nil, nil);
if(field[0] == '@') # these must go first in the list !
rtprepend(rtc, rtr);
else
rtappend(rtc, rtr);
rtc.n += 1;
return rtr;
}
#
# Allocate a RTClass structure.
#
newRTClass(s: string): ref RTClass
{
rtc: ref RTClass;
rtc = ref RTClass(s, nil, nil, 0, 0);
nrtclasses += 1;
# want the order: @mp, @np, @adt, @Class
addRTReloc(rtc, RCLASS, nil, 0);
addRTReloc(rtc, RADT, nil, 0);
addRTReloc(rtc, RNP, nil, 0);
addRTReloc(rtc, RMP, nil, 0);
return rtc;
}
#
# Add RTClass entry for classname.
#
addRTClass(classname: string): ref RTClass
{
h: int;
he: ref RTHash;
h = hashval(classname);
he = ref RTHash(newRTClass(classname), rttbl[h]);
rttbl[h] = he;
return he.rtc;
}
#
# Get RTClass entry for classname.
#
getRTClass(classname: string): ref RTClass
{
he: ref RTHash;
for(he = rttbl[hashval(classname)]; he != nil; he = he.next) {
if(classname == he.rtc.classname)
return he.rtc;
}
return addRTClass(classname);
}
#
# Get RTReloc entry. Ignore signature if nil.
#
getRTReloc(rtc: ref RTClass, field: string, sig: string, flags: int): ref RTReloc
{
rtr: ref RTReloc;
lowflags: int;
lowflags = 0;
for(rtr = rtc.rtr; rtr != nil; rtr = rtr.next) {
if(rtr.field == field && (sig == nil || rtr.sig == sig)) {
if(rtr.flags >> 16 == 0) {
rtr.flags |= flags;
return rtr;
} else if(rtr.flags >> 16 == flags >> 16)
return rtr;
lowflags = rtr.flags & 16rffff;
}
}
return addRTReloc(rtc, field, sig, flags|lowflags);
}
#
# Add instruction patch information to RTReloc rtr.
#
RTIpatch(rtr: ref RTReloc, i: ref Inst, operand: int, patchkind: int)
{
addDreloc(i, operand, patchkind);
addIpatch(rtr.ipatch, i, operand, patchkind, SAVEINST);
}
#
# Fix RTClass and RTReloc 'off' fields to prepare for instruction patch.
#
RTfixoff(off: int)
{
he: ref RTHash;
i: int;
if(nrtclasses > 0) {
for(i = 0; i < Hashsize; i++) {
for(he = rttbl[i]; he != nil; he = he.next) {
he.rtc.off = off;
off += he.rtc.n * IBY2WD;
}
}
}
}
#
# Patch instructions for run-time relocation.
#
doRTpatch()
{
a: ref Addr;
he: ref RTHash;
ip: ref Ipatch;
rtr: ref RTReloc;
i, j: int;
off, ltsize: int;
if(nrtclasses == 0)
return;
ltsize = LTrelocsize();
for(i = 0; i < Hashsize; i++) {
for(he = rttbl[i]; he != nil; he = he.next) {
off = he.rtc.off - ltsize;
for(rtr = he.rtc.rtr; rtr != nil; rtr = rtr.next) {
ip = rtr.ipatch;
for(j = 0; j < ip.n; j++) {
case(ip.pinfo[j] & (16r3 << 2)) {
PSRC =>
a = ip.i[j].s;
PDST =>
a = ip.i[j].d;
PMID =>
a = ip.i[j].m;
}
case (ip.pinfo[j] & 16r3) {
PIMM or
PDIND1 =>
a.ival = off;
PSIND or
PDIND2 =>
a.offset = off;
}
}
off += IBY2WD;
}
}
}
}
#
# Size of Module Data space taken by run-time relocation information.
#
RTrelocsize(): int
{
i: int;
n: int;
he: ref RTHash;
n = 0;
if(nrtclasses > 0) {
for(i = 0; i < Hashsize; i++) {
for(he = rttbl[i]; he != nil; he = he.next)
n += he.rtc.n;
}
}
return n * IBY2WD;
}
#
# Fix type descriptor for run-time relocation information.
#
RTReloctid: int;
RTrelocdesc(map: array of byte, off: int)
{
i: int;
he: ref RTHash;
rtr: ref RTReloc;
if(nrtclasses == 0)
return;
RTReloctid = descid(3*IBY2WD, 1, array [1] of { byte 16rc0 });
for(i = 0; i < Hashsize; i++) {
for(he = rttbl[i]; he != nil; he = he.next) {
setbit(map, off); # @mp cell
off += 4;
setbit(map, off); # @np cell
off += 4;
setbit(map, off); # @adt cell
off += 8;
rtr = he.rtc.rtr.next.next.next.next;
while(rtr != nil) {
if(rtr.flags & (Rspecialmp | Rstaticmp))
setbit(map, off);
off += 4;
rtr = rtr.next;
}
}
}
}
#
# Write RTReloc array to .s file.
#
asmRTReloc(off: int, rtc: ref RTClass)
{
rtr: ref RTReloc;
reloff: int; # relative offset for array elements
if(rtc.n <= 4)
return;
reloff = 0;
asmarray(off, RTReloctid, rtc.n - 4, reloff);
# skip @mp @np @adt @Class
rtr = rtc.rtr.next.next.next.next;
while(rtr != nil) {
asmstring(reloff, rtr.field);
reloff += IBY2WD;
if(rtr.sig != nil)
asmstring(reloff, rtr.sig);
reloff += IBY2WD;
asmint(reloff, rtr.flags);
reloff += IBY2WD;
rtr = rtr.next;
}
bout.puts("\tapop\n");
}
#
# Write RTClass information to .s file.
#
asmRTClass(off: int): int
{
he: ref RTHash;
i: int;
ltsize: int;
if(nrtclasses > 0) {
ltsize = LTrelocsize();
for(i = 0; i < Hashsize; i++) {
for(he = rttbl[i]; he != nil; he = he.next) {
off += IBY2WD; # @mp cell
asmstring(off, he.rtc.classname);
off += IBY2WD;
asmRTReloc(off, he.rtc);
off += IBY2WD;
asmint(off, he.rtc.off - ltsize);
off += IBY2WD;
# account for fields beyond @Class
off += (he.rtc.n - 4) * IBY2WD;
}
}
}
return off;
}
#
# Write RTReloc array to .dis file.
#
disRTReloc(off: int, rtc: ref RTClass)
{
rtr: ref RTReloc;
reloff: int; # relative offset for array elements
if(rtc.n <= 4)
return;
reloff = 0;
disarray(off, RTReloctid, rtc.n - 4);
# skip @mp @np @adt @Class
rtr = rtc.rtr.next.next.next.next;
while(rtr != nil) {
disstring(reloff, rtr.field);
reloff += IBY2WD;
if(rtr.sig != nil)
disstring(reloff, rtr.sig);
reloff += IBY2WD;
disint(reloff, rtr.flags);
reloff += IBY2WD;
rtr = rtr.next;
}
disapop();
}
#
# Write RTClass information to .dis file.
#
disRTClass(off: int): int
{
he: ref RTHash;
i: int;
ltsize: int;
if(nrtclasses > 0) {
ltsize = LTrelocsize();
for(i = 0; i < Hashsize; i++) {
for(he = rttbl[i]; he != nil; he = he.next) {
off += IBY2WD; # @mp cell
disstring(off, he.rtc.classname);
off += IBY2WD;
disRTReloc(off, he.rtc);
off += IBY2WD;
disint(off, he.rtc.off - ltsize);
off += IBY2WD;
# account for fields beyond @Class
off += (he.rtc.n - 4) * IBY2WD;
}
}
}
return off;
}