## Class loader.# class: ref Class; # class under translationpcode: array of PCode; # pointers to byte code of defined methodsTHISCLASS: string;SUPERCLASS: string; STRING(i: int): string{ pick cp := class.cps[i] { Putf8 => return cp.utf8.utf8; * => badpick("STRING"); } return nil;} CLASSNAME(i: int): string{ pick cp := class.cps[i] { Pci => return STRING(cp.ci.name_index); * => badpick("CLASSNAME"); } return nil;} u8(): big{ b1, b2: big; b1 = big u4() << 32; b2 = big u4() & 16rffffffff; return b1 | b2;} ## Bytecode verification.# verifyutf8index(index: int){ verifycpindex(nil, index, 1 << CON_Utf8); if(STRING(index) == nil) verifyerrormess("nil name or descriptor");} verifyclassindex(index: int){ verifycpindex(nil, index, 1 << CON_Class); pick cp := class.cps[index] { Pci => verifyutf8index(cp.ci.name_index); * => badpick("verifyclassindex"); }} verifyfielddesc(name_index: int, sig_index: int){ sig: string; ftype: int; verifyutf8index(name_index); verifyutf8index(sig_index); sig = STRING(sig_index); ftype = sig[0]; sig = nextjavatype(sig); if(ftype == 'V' || sig != nil) verifyerrormess("field descriptor");} verifymethoddesc(name_index: int, sig_index: int){ name, sig: string; rtype: int; wargs: int; verifyutf8index(name_index); name = STRING(name_index); verifyutf8index(sig_index); sig = STRING(sig_index); # check special <method> names if(name[0] == '<') { if(name == "<init>") ; else if(name == "<clinit>") { if(sig != "()V") verifyerrormess("<clinit> signature"); return; } else verifyerrormess("<method> name"); } # check signature if(sig[0] != '(') verifyerrormess("method descriptor"); sig = sig[1:]; wargs = 0; while(sig[0] != ')') { wargs++; if(sig[0] == 'J' || sig[0] == 'D') wargs++; sig = nextjavatype(sig); } sig = sig[1:]; rtype = sig[0]; sig = nextjavatype(sig); if(wargs > 255 || sig != nil || (name[0] == '<' && rtype != 'V')) verifyerrormess("method descriptor");} verifycpindexes(){ i: int; nameindex, sigindex, natindex: int; for(i = 1; i < class.cp_count; i++) { pick cp := class.cps[i] { Pci => verifyutf8index(cp.ci.name_index); Pfmiref => verifyclassindex(cp.fmiref.class_index); natindex = cp.fmiref.name_type_index; verifycpindex(nil, natindex, 1 << CON_NameAndType); pick cpnat := class.cps[natindex] { Pnat => nameindex = cpnat.nat.name_index; sigindex = cpnat.nat.sig_index; * => badpick("verifycpindexes (inner)"); } if(int class.cts[i] == CON_Fieldref) verifyfielddesc(nameindex, sigindex); else verifymethoddesc(nameindex, sigindex); Pstring_index => verifycpindex(nil, cp.string_index, 1 << CON_Utf8); Ptint => ; Pnat => # CON_NameAndType is verified through # CON_Fieldref, CON_Methodref, CON_InterfaceMref ; Putf8 => ; Ptvlong => i++; Ptdouble => if(int class.cts[i] == CON_Double) # else CON_Float i++; # since 49.0 Pmethodhandle => case cp.mh.ref_kind { # TODO: implement all ref_kinds handling * => verifyerrormess("bad method_handle ref_kind"); } Pmethodtype => verifycpindex(nil, cp.mt.descriptor_index, 1 << CON_Utf8); Pinvokedyn => # TODO: verify bs_method_attr_index field verifycpindex(nil, cp.invokedyn.name_type_index, 1 << CON_NameAndType); * => badpick("verifycpindexes (outer)"); } }} CLASSMUTEX: con ACC_FINAL|ACC_ABSTRACT; verifyclassflags(){ bad: int; if(class.access_flags & ACC_INTERFACE) { if(SUPERCLASS != "java/lang/Object") verifyerrormess("superclass"); # java bug: ACC_ABSTRACT should be set ??? # bad = (class.access_flags & ACC_ABSTRACT) != ACC_ABSTRACT; bad = 0; bad += (class.access_flags & ACC_FINAL) != 0; } else { bad = (class.access_flags & CLASSMUTEX) == CLASSMUTEX; } if(bad) verifyerrormess("access_flags");} multippp(flag: int): int{ ret: int; case flag & (ACC_PUBLIC|ACC_PRIVATE|ACC_PROTECTED) { 0 or ACC_PUBLIC or ACC_PRIVATE or ACC_PROTECTED => ret = 0; * => ret = 1; } return ret;} IFACEFIELD: con ACC_PUBLIC|ACC_STATIC|ACC_FINAL;_IFACEFIELD: con ACC_PRIVATE|ACC_PROTECTED|ACC_VOLATILE|ACC_TRANSIENT;FIELDMUTEX: con ACC_FINAL|ACC_VOLATILE;CVATTRTAGS: con ((1<<CON_Integer)|(1<<CON_Long)|(1<<CON_Float)|(1<<CON_Double)|(1<<CON_String)); verifyfield(fp: ref Field){ bad, n: int; c: int; verifyfielddesc(fp.name_index, fp.sig_index); if(class.access_flags & ACC_INTERFACE) { bad = (fp.access_flags & _IFACEFIELD) != 0; bad += (fp.access_flags & IFACEFIELD) != IFACEFIELD; } else { bad = multippp(fp.access_flags); bad += (fp.access_flags & FIELDMUTEX) == FIELDMUTEX; } if(bad) verifyerrormess("access_flags"); # verify ConstantValue attribute n = CVattrindex(fp); if(n == 0) return; verifycpindex(nil, n, CVATTRTAGS); c = STRING(fp.sig_index)[0]; pick cp := class.cps[n] { Ptdouble => if(int class.cts[n] == CON_Float) bad = (c != 'F'); else bad = (c != 'D'); Ptvlong => bad = (c != 'J'); Ptint => case c { 'Z' or 'B' or 'C' or 'S' or 'I' => bad = 0; * => bad = 1; } Pstring_index => bad = (c != 'L'); * => bad = 1; } if(bad) verifyerrormess("ConstantValue attribute");} IFACEMETHOD: con ACC_PUBLIC|ACC_ABSTRACT;_IFACEMETHOD: con ACC_PRIVATE|ACC_PROTECTED|ACC_STATIC|ACC_FINAL|ACC_SYNCHRONIZED|ACC_NATIVE;_INITFLAGS: con ACC_STATIC|ACC_FINAL|ACC_SYNCHRONIZED|ACC_NATIVE|ACC_ABSTRACT;# java bug: ACC_SYNCHRONIZED wrongly allowed with ACC_ABSTRACT ???#METHODMUTEX: con ACC_PRIVATE|ACC_STATIC|ACC_FINAL|ACC_SYNCHRONIZED|ACC_NATIVE;METHODMUTEX: con ACC_PRIVATE|ACC_STATIC|ACC_FINAL|ACC_NATIVE; verifymethod(mp: ref Method){ bad: int; name: string; verifymethoddesc(mp.name_index, mp.sig_index); name = STRING(mp.name_index); if(name == "<clinit>") return; if(class.access_flags & ACC_INTERFACE) { bad = (mp.access_flags & _IFACEMETHOD) != 0; bad += (mp.access_flags & IFACEMETHOD) != IFACEMETHOD; } else { bad = multippp(mp.access_flags); if(name == "<init>") bad += (mp.access_flags & _INITFLAGS) != 0; if(mp.access_flags & ACC_ABSTRACT) bad += (mp.access_flags & METHODMUTEX) != 0; } if(bad) verifyerrormess("access_flags"); # # Code attribute verified during disassembly # ignore Exceptions attribute for now #} ## Parse a byte stream into a Class stucture.# byte2Class(text: array of byte){ i, j: int; fp: ref Field; mp: ref Method; uSet(text); class = ref Class(0, 0, 0, nil, nil, 0, 0, 0, 0, nil, 0, nil, 0, nil, 0, nil); if(u4() != int 16rCAFEBABE) verifyerrormess("magic"); class.min = u2(); class.maj = u2(); class.cp_count = u2(); class.cps = array [class.cp_count] of ref Const; class.cts = array [class.cp_count] of { * => byte 0 }; for(i = 1; i < class.cp_count; i++) { class.cts[i] = byte u1(); case int class.cts[i] { CON_Class => cp := ref Const.Pci; cp.ci = ref Const_ci; cp.ci.name_index = u2(); class.cps[i] = cp; CON_Fieldref or CON_Methodref or CON_InterfaceMref => cp := ref Const.Pfmiref; cp.fmiref = ref Const_fmiref; cp.fmiref.class_index = u2(); cp.fmiref.name_type_index = u2(); class.cps[i] = cp; CON_String => cp := ref Const.Pstring_index; cp.string_index = u2(); class.cps[i] = cp; CON_Integer => cp := ref Const.Ptint; cp.tint = u4(); class.cps[i] = cp; CON_Float => cp := ref Const.Ptdouble; cp.tdouble = math->bits32real(u4()); class.cps[i] = cp; CON_Long => cp := ref Const.Ptvlong; cp.tvlong = u8(); class.cps[i] = cp; i++; CON_Double => cp := ref Const.Ptdouble; cp.tdouble = math->bits64real(u8()); class.cps[i] = cp; i++; CON_NameAndType => cp := ref Const.Pnat; cp.nat = ref Const_nat; cp.nat.name_index = u2(); cp.nat.sig_index = u2(); class.cps[i] = cp; CON_Utf8 => cp := ref Const.Putf8; cp.utf8 = ref Const_utf8; cp.utf8.ln = u2(); # null char represented as 16rC080 in String literals a := uPtr(cp.utf8.ln); (src, dst) := (0, 0); while(src < cp.utf8.ln) { if(src+1 < cp.utf8.ln && a[src] == byte 16rC0 && a[src+1] == byte 16r80) { a[dst] = byte 0; src++; } else a[dst] = a[src]; src++; dst++; } cp.utf8.utf8 = string a[0:dst]; uN(cp.utf8.ln); class.cps[i] = cp; # since 49.0 CON_MethodHandle => verifyerrormess("MethodHandles are not implemented"); cp := ref Const.Pmethodhandle; cp.mh = ref Const_methodhandle; cp.mh.ref_kind = int u1(); cp.mh.ref_index = u2(); class.cps[i] = cp; CON_MethodType => verifyerrormess("MethodTypes are not implemented"); cp := ref Const.Pmethodtype; cp.mt = ref Const_methodtype; cp.mt.descriptor_index = u2(); class.cps[i] = cp; CON_InvokeDynamic => verifyerrormess("InvokeDynamics are not implemented"); cp := ref Const.Pinvokedyn; cp.invokedyn = ref Const_invokedyn; cp.invokedyn.bs_method_attr_index = u2(); cp.invokedyn.name_type_index = u2(); class.cps[i] = cp; * => verifyerrormess("constant pool tag"); } } verifycpindexes(); # verify after all are established class.access_flags = u2(); # verify after [THIS|SUPER]CLASS set class.this_class = u2(); verifyclassindex(class.this_class); THISCLASS = CLASSNAME(class.this_class); class.super_class = u2(); if(class.super_class) { verifyclassindex(class.super_class); SUPERCLASS = CLASSNAME(class.super_class); } else if(THISCLASS != "java/lang/Object") verifyerrormess("superclass"); verifyclassflags(); # for compatibility with JavaSoft VM if(len THISCLASS > len "inferno/vm/" && THISCLASS[0:len "inferno/vm/"] == "inferno/vm/") { # # ACC_ABSTRACT & ACC_FINAL are both set in JVM, # but a class can't be declared that way # class.access_flags |= ACC_ABSTRACT; # # ACC_SUPER not set in JVM, but javac sets it # for inferno/vm/Array # class.access_flags &= ~ACC_SUPER; } else if(class.access_flags & ACC_INTERFACE) { # interfaces are implicitly abstract class.access_flags |= ACC_ABSTRACT; } class.interfaces_count = u2(); if(class.interfaces_count > 0) class.interfaces = array [class.interfaces_count] of int; for(i = 0; i < class.interfaces_count; i++) { class.interfaces[i] = u2(); verifyclassindex(class.interfaces[i]); } class.fields_count = u2(); if(class.fields_count > 0) class.fields = array [class.fields_count] of ref Field; for(i = 0; i < class.fields_count; i++) { class.fields[i] = ref Field(0, 0, 0, 0, nil); fp = class.fields[i]; fp.access_flags = u2(); fp.name_index = u2(); fp.sig_index = u2(); fp.attr_count = u2(); if(fp.attr_count > 0) fp.attr_info = array [fp.attr_count] of ref Attr; for(j = 0; j < fp.attr_count; j++) fp.attr_info[j] = getattr(); verifyfield(fp); } class.methods_count = u2(); if(class.methods_count > 0) { class.methods = array [class.methods_count] of ref Method; pcode = array [class.methods_count] of PCode; } for(i = 0; i < class.methods_count; i++) { class.methods[i] = ref Method(0, 0, 0, 0, nil); mp = class.methods[i]; mp.access_flags = u2(); mp.name_index = u2(); mp.sig_index = u2(); mp.attr_count = u2(); if(mp.attr_count > 0) mp.attr_info = array [mp.attr_count] of ref Attr; for(j = 0; j < mp.attr_count; j++) mp.attr_info[j] = getattr(); verifymethod(mp); } # get SourceFile attribute i = u2(); for(j = 0; j < i; j++) { a := getattr(); if(STRING(a.name) == "SourceFile") { class.source_file = (int a.info[0] << 8) | int a.info[1]; verifyutf8index(class.source_file); break; }Lines 1–500 of 691. Load more
# # Class loader. # class: ref Class; # class under translation pcode: array of PCode; # pointers to byte code of defined methods THISCLASS: string; SUPERCLASS: string; STRING(i: int): string { pick cp := class.cps[i] { Putf8 => return cp.utf8.utf8; * => badpick("STRING"); } return nil; } CLASSNAME(i: int): string { pick cp := class.cps[i] { Pci => return STRING(cp.ci.name_index); * => badpick("CLASSNAME"); } return nil; } u8(): big { b1, b2: big; b1 = big u4() << 32; b2 = big u4() & 16rffffffff; return b1 | b2; } # # Bytecode verification. # verifyutf8index(index: int) { verifycpindex(nil, index, 1 << CON_Utf8); if(STRING(index) == nil) verifyerrormess("nil name or descriptor"); } verifyclassindex(index: int) { verifycpindex(nil, index, 1 << CON_Class); pick cp := class.cps[index] { Pci => verifyutf8index(cp.ci.name_index); * => badpick("verifyclassindex"); } } verifyfielddesc(name_index: int, sig_index: int) { sig: string; ftype: int; verifyutf8index(name_index); verifyutf8index(sig_index); sig = STRING(sig_index); ftype = sig[0]; sig = nextjavatype(sig); if(ftype == 'V' || sig != nil) verifyerrormess("field descriptor"); } verifymethoddesc(name_index: int, sig_index: int) { name, sig: string; rtype: int; wargs: int; verifyutf8index(name_index); name = STRING(name_index); verifyutf8index(sig_index); sig = STRING(sig_index); # check special <method> names if(name[0] == '<') { if(name == "<init>") ; else if(name == "<clinit>") { if(sig != "()V") verifyerrormess("<clinit> signature"); return; } else verifyerrormess("<method> name"); } # check signature if(sig[0] != '(') verifyerrormess("method descriptor"); sig = sig[1:]; wargs = 0; while(sig[0] != ')') { wargs++; if(sig[0] == 'J' || sig[0] == 'D') wargs++; sig = nextjavatype(sig); } sig = sig[1:]; rtype = sig[0]; sig = nextjavatype(sig); if(wargs > 255 || sig != nil || (name[0] == '<' && rtype != 'V')) verifyerrormess("method descriptor"); } verifycpindexes() { i: int; nameindex, sigindex, natindex: int; for(i = 1; i < class.cp_count; i++) { pick cp := class.cps[i] { Pci => verifyutf8index(cp.ci.name_index); Pfmiref => verifyclassindex(cp.fmiref.class_index); natindex = cp.fmiref.name_type_index; verifycpindex(nil, natindex, 1 << CON_NameAndType); pick cpnat := class.cps[natindex] { Pnat => nameindex = cpnat.nat.name_index; sigindex = cpnat.nat.sig_index; * => badpick("verifycpindexes (inner)"); } if(int class.cts[i] == CON_Fieldref) verifyfielddesc(nameindex, sigindex); else verifymethoddesc(nameindex, sigindex); Pstring_index => verifycpindex(nil, cp.string_index, 1 << CON_Utf8); Ptint => ; Pnat => # CON_NameAndType is verified through # CON_Fieldref, CON_Methodref, CON_InterfaceMref ; Putf8 => ; Ptvlong => i++; Ptdouble => if(int class.cts[i] == CON_Double) # else CON_Float i++; # since 49.0 Pmethodhandle => case cp.mh.ref_kind { # TODO: implement all ref_kinds handling * => verifyerrormess("bad method_handle ref_kind"); } Pmethodtype => verifycpindex(nil, cp.mt.descriptor_index, 1 << CON_Utf8); Pinvokedyn => # TODO: verify bs_method_attr_index field verifycpindex(nil, cp.invokedyn.name_type_index, 1 << CON_NameAndType); * => badpick("verifycpindexes (outer)"); } } } CLASSMUTEX: con ACC_FINAL|ACC_ABSTRACT; verifyclassflags() { bad: int; if(class.access_flags & ACC_INTERFACE) { if(SUPERCLASS != "java/lang/Object") verifyerrormess("superclass"); # java bug: ACC_ABSTRACT should be set ??? # bad = (class.access_flags & ACC_ABSTRACT) != ACC_ABSTRACT; bad = 0; bad += (class.access_flags & ACC_FINAL) != 0; } else { bad = (class.access_flags & CLASSMUTEX) == CLASSMUTEX; } if(bad) verifyerrormess("access_flags"); } multippp(flag: int): int { ret: int; case flag & (ACC_PUBLIC|ACC_PRIVATE|ACC_PROTECTED) { 0 or ACC_PUBLIC or ACC_PRIVATE or ACC_PROTECTED => ret = 0; * => ret = 1; } return ret; } IFACEFIELD: con ACC_PUBLIC|ACC_STATIC|ACC_FINAL; _IFACEFIELD: con ACC_PRIVATE|ACC_PROTECTED|ACC_VOLATILE|ACC_TRANSIENT; FIELDMUTEX: con ACC_FINAL|ACC_VOLATILE; CVATTRTAGS: con ((1<<CON_Integer)|(1<<CON_Long)|(1<<CON_Float)|(1<<CON_Double)|(1<<CON_String)); verifyfield(fp: ref Field) { bad, n: int; c: int; verifyfielddesc(fp.name_index, fp.sig_index); if(class.access_flags & ACC_INTERFACE) { bad = (fp.access_flags & _IFACEFIELD) != 0; bad += (fp.access_flags & IFACEFIELD) != IFACEFIELD; } else { bad = multippp(fp.access_flags); bad += (fp.access_flags & FIELDMUTEX) == FIELDMUTEX; } if(bad) verifyerrormess("access_flags"); # verify ConstantValue attribute n = CVattrindex(fp); if(n == 0) return; verifycpindex(nil, n, CVATTRTAGS); c = STRING(fp.sig_index)[0]; pick cp := class.cps[n] { Ptdouble => if(int class.cts[n] == CON_Float) bad = (c != 'F'); else bad = (c != 'D'); Ptvlong => bad = (c != 'J'); Ptint => case c { 'Z' or 'B' or 'C' or 'S' or 'I' => bad = 0; * => bad = 1; } Pstring_index => bad = (c != 'L'); * => bad = 1; } if(bad) verifyerrormess("ConstantValue attribute"); } IFACEMETHOD: con ACC_PUBLIC|ACC_ABSTRACT; _IFACEMETHOD: con ACC_PRIVATE|ACC_PROTECTED|ACC_STATIC|ACC_FINAL|ACC_SYNCHRONIZED|ACC_NATIVE; _INITFLAGS: con ACC_STATIC|ACC_FINAL|ACC_SYNCHRONIZED|ACC_NATIVE|ACC_ABSTRACT; # java bug: ACC_SYNCHRONIZED wrongly allowed with ACC_ABSTRACT ??? #METHODMUTEX: con ACC_PRIVATE|ACC_STATIC|ACC_FINAL|ACC_SYNCHRONIZED|ACC_NATIVE; METHODMUTEX: con ACC_PRIVATE|ACC_STATIC|ACC_FINAL|ACC_NATIVE; verifymethod(mp: ref Method) { bad: int; name: string; verifymethoddesc(mp.name_index, mp.sig_index); name = STRING(mp.name_index); if(name == "<clinit>") return; if(class.access_flags & ACC_INTERFACE) { bad = (mp.access_flags & _IFACEMETHOD) != 0; bad += (mp.access_flags & IFACEMETHOD) != IFACEMETHOD; } else { bad = multippp(mp.access_flags); if(name == "<init>") bad += (mp.access_flags & _INITFLAGS) != 0; if(mp.access_flags & ACC_ABSTRACT) bad += (mp.access_flags & METHODMUTEX) != 0; } if(bad) verifyerrormess("access_flags"); # # Code attribute verified during disassembly # ignore Exceptions attribute for now # } # # Parse a byte stream into a Class stucture. # byte2Class(text: array of byte) { i, j: int; fp: ref Field; mp: ref Method; uSet(text); class = ref Class(0, 0, 0, nil, nil, 0, 0, 0, 0, nil, 0, nil, 0, nil, 0, nil); if(u4() != int 16rCAFEBABE) verifyerrormess("magic"); class.min = u2(); class.maj = u2(); class.cp_count = u2(); class.cps = array [class.cp_count] of ref Const; class.cts = array [class.cp_count] of { * => byte 0 }; for(i = 1; i < class.cp_count; i++) { class.cts[i] = byte u1(); case int class.cts[i] { CON_Class => cp := ref Const.Pci; cp.ci = ref Const_ci; cp.ci.name_index = u2(); class.cps[i] = cp; CON_Fieldref or CON_Methodref or CON_InterfaceMref => cp := ref Const.Pfmiref; cp.fmiref = ref Const_fmiref; cp.fmiref.class_index = u2(); cp.fmiref.name_type_index = u2(); class.cps[i] = cp; CON_String => cp := ref Const.Pstring_index; cp.string_index = u2(); class.cps[i] = cp; CON_Integer => cp := ref Const.Ptint; cp.tint = u4(); class.cps[i] = cp; CON_Float => cp := ref Const.Ptdouble; cp.tdouble = math->bits32real(u4()); class.cps[i] = cp; CON_Long => cp := ref Const.Ptvlong; cp.tvlong = u8(); class.cps[i] = cp; i++; CON_Double => cp := ref Const.Ptdouble; cp.tdouble = math->bits64real(u8()); class.cps[i] = cp; i++; CON_NameAndType => cp := ref Const.Pnat; cp.nat = ref Const_nat; cp.nat.name_index = u2(); cp.nat.sig_index = u2(); class.cps[i] = cp; CON_Utf8 => cp := ref Const.Putf8; cp.utf8 = ref Const_utf8; cp.utf8.ln = u2(); # null char represented as 16rC080 in String literals a := uPtr(cp.utf8.ln); (src, dst) := (0, 0); while(src < cp.utf8.ln) { if(src+1 < cp.utf8.ln && a[src] == byte 16rC0 && a[src+1] == byte 16r80) { a[dst] = byte 0; src++; } else a[dst] = a[src]; src++; dst++; } cp.utf8.utf8 = string a[0:dst]; uN(cp.utf8.ln); class.cps[i] = cp; # since 49.0 CON_MethodHandle => verifyerrormess("MethodHandles are not implemented"); cp := ref Const.Pmethodhandle; cp.mh = ref Const_methodhandle; cp.mh.ref_kind = int u1(); cp.mh.ref_index = u2(); class.cps[i] = cp; CON_MethodType => verifyerrormess("MethodTypes are not implemented"); cp := ref Const.Pmethodtype; cp.mt = ref Const_methodtype; cp.mt.descriptor_index = u2(); class.cps[i] = cp; CON_InvokeDynamic => verifyerrormess("InvokeDynamics are not implemented"); cp := ref Const.Pinvokedyn; cp.invokedyn = ref Const_invokedyn; cp.invokedyn.bs_method_attr_index = u2(); cp.invokedyn.name_type_index = u2(); class.cps[i] = cp; * => verifyerrormess("constant pool tag"); } } verifycpindexes(); # verify after all are established class.access_flags = u2(); # verify after [THIS|SUPER]CLASS set class.this_class = u2(); verifyclassindex(class.this_class); THISCLASS = CLASSNAME(class.this_class); class.super_class = u2(); if(class.super_class) { verifyclassindex(class.super_class); SUPERCLASS = CLASSNAME(class.super_class); } else if(THISCLASS != "java/lang/Object") verifyerrormess("superclass"); verifyclassflags(); # for compatibility with JavaSoft VM if(len THISCLASS > len "inferno/vm/" && THISCLASS[0:len "inferno/vm/"] == "inferno/vm/") { # # ACC_ABSTRACT & ACC_FINAL are both set in JVM, # but a class can't be declared that way # class.access_flags |= ACC_ABSTRACT; # # ACC_SUPER not set in JVM, but javac sets it # for inferno/vm/Array # class.access_flags &= ~ACC_SUPER; } else if(class.access_flags & ACC_INTERFACE) { # interfaces are implicitly abstract class.access_flags |= ACC_ABSTRACT; } class.interfaces_count = u2(); if(class.interfaces_count > 0) class.interfaces = array [class.interfaces_count] of int; for(i = 0; i < class.interfaces_count; i++) { class.interfaces[i] = u2(); verifyclassindex(class.interfaces[i]); } class.fields_count = u2(); if(class.fields_count > 0) class.fields = array [class.fields_count] of ref Field; for(i = 0; i < class.fields_count; i++) { class.fields[i] = ref Field(0, 0, 0, 0, nil); fp = class.fields[i]; fp.access_flags = u2(); fp.name_index = u2(); fp.sig_index = u2(); fp.attr_count = u2(); if(fp.attr_count > 0) fp.attr_info = array [fp.attr_count] of ref Attr; for(j = 0; j < fp.attr_count; j++) fp.attr_info[j] = getattr(); verifyfield(fp); } class.methods_count = u2(); if(class.methods_count > 0) { class.methods = array [class.methods_count] of ref Method; pcode = array [class.methods_count] of PCode; } for(i = 0; i < class.methods_count; i++) { class.methods[i] = ref Method(0, 0, 0, 0, nil); mp = class.methods[i]; mp.access_flags = u2(); mp.name_index = u2(); mp.sig_index = u2(); mp.attr_count = u2(); if(mp.attr_count > 0) mp.attr_info = array [mp.attr_count] of ref Attr; for(j = 0; j < mp.attr_count; j++) mp.attr_info[j] = getattr(); verifymethod(mp); } # get SourceFile attribute i = u2(); for(j = 0; j < i; j++) { a := getattr(); if(STRING(a.name) == "SourceFile") { class.source_file = (int a.info[0] << 8) | int a.info[1]; verifyutf8index(class.source_file); break; }