Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file camlinternalOO.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613(**************************************************************************)(* *)(* OCaml *)(* *)(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *)(* *)(* Copyright 2002 Institut National de Recherche en Informatique et *)(* en Automatique. *)(* *)(* All rights reserved. This file is distributed under the terms of *)(* the GNU Lesser General Public License version 2.1, with the *)(* special exception on linking described in the file LICENSE. *)(* *)(**************************************************************************)openObj(**** Object representation ****)externalset_id:'a->'a="caml_set_oo_id"[@@noalloc](**** Object copy ****)letcopyo=leto=(Obj.obj(Obj.dup(Obj.repro)))inset_ido(**** Compression options ****)(* Parameters *)typeparams={mutablecompact_table:bool;mutablecopy_parent:bool;mutableclean_when_copying:bool;mutableretry_count:int;mutablebucket_small_size:int}letparams={compact_table=true;copy_parent=true;clean_when_copying=true;retry_count=3;bucket_small_size=16}(**** Parameters ****)letinitial_object_size=2(**** Items ****)typeitem=DummyA|DummyB|DummyCofintlet_=[DummyA;DummyB;DummyC0](* to avoid warnings *)letdummy_item=(magic():item)(**** Types ****)typetagtypelabel=inttypeclosure=itemtypet=DummyA|DummyB|DummyCofintlet_=[DummyA;DummyB;DummyC0](* to avoid warnings *)typeobj=tarrayexternalret:(obj->'a)->closure="%identity"(**** Labels ****)letpublic_method_labels:tag=letaccu=ref0infori=0toString.lengths-1doaccu:=223*!accu+Char.codes.[i]done;(* reduce to 31 bits *)accu:=!acculand(1lsl31-1);(* make it signed for 64 bits architectures *)lettag=if!accu>0x3FFFFFFFthen!accu-(1lsl31)else!accuin(* Printf.eprintf "%s = %d\n" s tag; flush stderr; *)magictag(**** Sparse array ****)moduleVars=Map.Make(structtypet=stringletcompare(x:t)y=comparexyend)typevars=intVars.tmoduleMeths=Map.Make(structtypet=stringletcompare(x:t)y=comparexyend)typemeths=labelMeths.tmoduleLabs=Map.Make(structtypet=labelletcompare(x:t)y=comparexyend)typelabs=boolLabs.t(* The compiler assumes that the first field of this structure is [size]. *)typetable={mutablesize:int;mutablemethods:closurearray;mutablemethods_by_name:meths;mutablemethods_by_label:labs;mutableprevious_states:(meths*labs*(label*item)list*vars*labellist*stringlist)list;mutablehidden_meths:(label*item)list;mutablevars:vars;mutableinitializers:(obj->unit)list}letdummy_table={methods=[|dummy_item|];methods_by_name=Meths.empty;methods_by_label=Labs.empty;previous_states=[];hidden_meths=[];vars=Vars.empty;initializers=[];size=0}lettable_count=ref0(* dummy_met should be a pointer, so use an atom *)letdummy_met:item=obj(Obj.new_block00)(* if debugging is needed, this could be a good idea: *)(* let dummy_met () = failwith "Undefined method" *)letrecfit_sizen=ifn<=2thennelsefit_size((n+1)/2)*2letnew_tablepub_labels=incrtable_count;letlen=Array.lengthpub_labelsinletmethods=Array.make(len*2+2)dummy_metinmethods.(0)<-magiclen;methods.(1)<-magic(fit_sizelen*Sys.word_size/8-1);fori=0tolen-1domethods.(i*2+3)<-magicpub_labels.(i)done;{methods=methods;methods_by_name=Meths.empty;methods_by_label=Labs.empty;previous_states=[];hidden_meths=[];vars=Vars.empty;initializers=[];size=initial_object_size}letresizearraynew_size=letold_size=Array.lengtharray.methodsinifnew_size>old_sizethenbeginletnew_buck=Array.makenew_sizedummy_metinArray.blitarray.methods0new_buck0old_size;array.methods<-new_buckendletputarraylabelelement=resizearray(label+1);array.methods.(label)<-element(**** Classes ****)letmethod_count=ref0letinst_var_count=ref0(* type t *)typemeth=itemletnew_methodtable=letindex=Array.lengthtable.methodsinresizetable(index+1);indexletget_method_labeltablename=tryMeths.findnametable.methods_by_namewithNot_found->letlabel=new_methodtableintable.methods_by_name<-Meths.addnamelabeltable.methods_by_name;table.methods_by_label<-Labs.addlabeltruetable.methods_by_label;labelletget_method_labelstablenames=Array.map(get_method_labeltable)namesletset_methodtablelabelelement=incrmethod_count;ifLabs.findlabeltable.methods_by_labelthenputtablelabelelementelsetable.hidden_meths<-(label,element)::table.hidden_methsletget_methodtablelabel=tryList.assoclabeltable.hidden_methswithNot_found->table.methods.(label)letto_listarr=ifarr==magic0then[]elseArray.to_listarrletnarrowtablevarsvirt_methsconcr_meths=letvars=to_listvarsandvirt_meths=to_listvirt_methsandconcr_meths=to_listconcr_methsinletvirt_meth_labs=List.map(get_method_labeltable)virt_methsinletconcr_meth_labs=List.map(get_method_labeltable)concr_methsintable.previous_states<-(table.methods_by_name,table.methods_by_label,table.hidden_meths,table.vars,virt_meth_labs,vars)::table.previous_states;table.vars<-Vars.fold(funlabinfotvars->ifList.memlabvarsthenVars.addlabinfotvarselsetvars)table.varsVars.empty;letby_name=refMeths.emptyinletby_label=refLabs.emptyinList.iter2(funmetlabel->by_name:=Meths.addmetlabel!by_name;by_label:=Labs.addlabel(tryLabs.findlabeltable.methods_by_labelwithNot_found->true)!by_label)concr_methsconcr_meth_labs;List.iter2(funmetlabel->by_name:=Meths.addmetlabel!by_name;by_label:=Labs.addlabelfalse!by_label)virt_methsvirt_meth_labs;table.methods_by_name<-!by_name;table.methods_by_label<-!by_label;table.hidden_meths<-List.fold_right(fun((lab,_)asmet)hm->ifList.memlabvirt_meth_labsthenhmelsemet::hm)table.hidden_meths[]letwidentable=let(by_name,by_label,saved_hidden_meths,saved_vars,virt_meths,vars)=List.hdtable.previous_statesintable.previous_states<-List.tltable.previous_states;table.vars<-List.fold_left(funsv->Vars.addv(Vars.findvtable.vars)s)saved_varsvars;table.methods_by_name<-by_name;table.methods_by_label<-by_label;table.hidden_meths<-List.fold_right(fun((lab,_)asmet)hm->ifList.memlabvirt_methsthenhmelsemet::hm)table.hidden_methssaved_hidden_methsletnew_slottable=letindex=table.sizeintable.size<-index+1;indexletnew_variabletablename=tryVars.findnametable.varswithNot_found->letindex=new_slottableinifname<>""thentable.vars<-Vars.addnameindextable.vars;indexletto_arrayarr=ifarr=Obj.magic0then[||]elsearrletnew_methods_variablestablemethsvals=letmeths=to_arraymethsinletnmeths=Array.lengthmethsandnvals=Array.lengthvalsinletres=Array.make(nmeths+nvals)0infori=0tonmeths-1dores.(i)<-get_method_labeltablemeths.(i)done;fori=0tonvals-1dores.(i+nmeths)<-new_variabletablevals.(i)done;resletget_variabletablename=tryVars.findnametable.varswithNot_found->assertfalseletget_variablestablenames=Array.map(get_variabletable)namesletadd_initializertablef=table.initializers<-f::table.initializers(*
module Keys =
Map.Make(struct type t = tag array let compare (x:t) y = compare x y end)
let key_map = ref Keys.empty
let get_key tags : item =
try magic (Keys.find tags !key_map : tag array)
with Not_found ->
key_map := Keys.add tags tags !key_map;
magic tags
*)letcreate_tablepublic_methods=ifpublic_methods==magic0thennew_table[||]else(* [public_methods] must be in ascending order for bytecode *)lettags=Array.mappublic_method_labelpublic_methodsinlettable=new_tabletagsinArray.iteri(funimet->letlab=i*2+2intable.methods_by_name<-Meths.addmetlabtable.methods_by_name;table.methods_by_label<-Labs.addlabtruetable.methods_by_label)public_methods;tableletinit_classtable=inst_var_count:=!inst_var_count+table.size-1;table.initializers<-List.revtable.initializers;resizetable(3+magictable.methods.(1)*16/Sys.word_size)letinheritsclavalsvirt_methsconcr_meths(_,super,_,env)top=narrowclavalsvirt_methsconcr_meths;letinit=iftopthensuperclaenvelseObj.repr(supercla)inwidencla;Array.concat[[|reprinit|];magic(Array.map(get_variablecla)(to_arrayvals):intarray);Array.map(funnm->repr(get_methodcla(get_method_labelclanm):closure))(to_arrayconcr_meths)]letmake_classpub_methsclass_init=lettable=create_tablepub_methsinletenv_init=class_inittableininit_classtable;(env_init(Obj.repr0),class_init,env_init,Obj.repr0)typeinit_table={mutableenv_init:t;mutableclass_init:table->t}letmake_class_storepub_methsclass_initinit_table=lettable=create_tablepub_methsinletenv_init=class_inittableininit_classtable;init_table.class_init<-class_init;init_table.env_init<-env_initletdummy_classloc=letundef=fun_->raise(Undefined_recursive_moduleloc)in(Obj.magicundef,undef,undef,Obj.repr0)(**** Objects ****)letcreate_objecttable=(* XXX Appel de [obj_block] | Call to [obj_block] *)letobj=Obj.new_blockObj.object_tagtable.sizein(* XXX Appel de [caml_modify] | Call to [caml_modify] *)Obj.set_fieldobj0(Obj.reprtable.methods);Obj.obj(set_idobj)letcreate_object_optobj_0table=if(Obj.magicobj_0:bool)thenobj_0elsebegin(* XXX Appel de [obj_block] | Call to [obj_block] *)letobj=Obj.new_blockObj.object_tagtable.sizein(* XXX Appel de [caml_modify] | Call to [caml_modify] *)Obj.set_fieldobj0(Obj.reprtable.methods);Obj.obj(set_idobj)endletreciter_fobj=function[]->()|f::l->fobj;iter_fobjlletrun_initializersobjtable=letinits=table.initializersinifinits<>[]theniter_fobjinitsletrun_initializers_optobj_0objtable=if(Obj.magicobj_0:bool)thenobjelsebeginletinits=table.initializersinifinits<>[]theniter_fobjinits;objendletcreate_object_and_run_initializersobj_0table=if(Obj.magicobj_0:bool)thenobj_0elsebeginletobj=create_objecttableinrun_initializersobjtable;objend(* Equivalent primitive below
let sendself obj lab =
(magic obj : (obj -> t) array array).(0).(lab) obj
*)externalsend:obj->tag->'a="%send"externalsendcache:obj->tag->t->int->'a="%sendcache"externalsendself:obj->label->'a="%sendself"externalget_public_method:obj->tag->closure="caml_get_public_method"[@@noalloc](**** table collection access ****)typetables=|Empty|Consof{key:closure;mutabledata:tables;mutablenext:tables}letset_datatablesv=matchtableswith|Empty->assertfalse|Constables->tables.data<-vletset_nexttablesv=matchtableswith|Empty->assertfalse|Constables->tables.next<-vletget_key=function|Empty->assertfalse|Constables->tables.keyletget_data=function|Empty->assertfalse|Constables->tables.dataletget_next=function|Empty->assertfalse|Constables->tables.nextletbuild_pathnkeystables=letres=Cons{key=Obj.magic0;data=Empty;next=Empty}inletr=refresinfori=0tondor:=Cons{key=keys.(i);data=!r;next=Empty}done;set_datatables!r;resletreclookup_keysikeystables=ifi<0thentableselseletkey=keys.(i)inletreclookup_key(tables:tables)=ifget_keytables==keythenmatchget_datatableswith|Empty->assertfalse|Cons_astables_data->lookup_keys(i-1)keystables_dataelsematchget_nexttableswith|Cons_asnext->lookup_keynext|Empty->letnext:tables=Cons{key;data=Empty;next=Empty}inset_nexttablesnext;build_path(i-1)keysnextinlookup_keytablesletlookup_tablesrootkeys=matchget_datarootwith|Cons_asroot_data->lookup_keys(Array.lengthkeys-1)keysroot_data|Empty->build_path(Array.lengthkeys-1)keysroot(**** builtin methods ****)letget_constx=ret(fun_obj->x)letget_varn=ret(funobj->Array.unsafe_getobjn)letget_enven=ret(funobj->Array.unsafe_get(Obj.magic(Array.unsafe_getobje):obj)n)letget_methn=ret(funobj->sendselfobjn)letset_varn=ret(funobjx->Array.unsafe_setobjnx)letapp_constfx=ret(fun_obj->fx)letapp_varfn=ret(funobj->f(Array.unsafe_getobjn))letapp_envfen=ret(funobj->f(Array.unsafe_get(Obj.magic(Array.unsafe_getobje):obj)n))letapp_methfn=ret(funobj->f(sendselfobjn))letapp_const_constfxy=ret(fun_obj->fxy)letapp_const_varfxn=ret(funobj->fx(Array.unsafe_getobjn))letapp_const_methfxn=ret(funobj->fx(sendselfobjn))letapp_var_constfnx=ret(funobj->f(Array.unsafe_getobjn)x)letapp_meth_constfnx=ret(funobj->f(sendselfobjn)x)letapp_const_envfxen=ret(funobj->fx(Array.unsafe_get(Obj.magic(Array.unsafe_getobje):obj)n))letapp_env_constfenx=ret(funobj->f(Array.unsafe_get(Obj.magic(Array.unsafe_getobje):obj)n)x)letmeth_app_constnx=ret(funobj->(sendselfobjn:_->_)x)letmeth_app_varnm=ret(funobj->(sendselfobjn:_->_)(Array.unsafe_getobjm))letmeth_app_envnem=ret(funobj->(sendselfobjn:_->_)(Array.unsafe_get(Obj.magic(Array.unsafe_getobje):obj)m))letmeth_app_methnm=ret(funobj->(sendselfobjn:_->_)(sendselfobjm))letsend_constmxc=ret(funobj->sendcachexm(Array.unsafe_getobj0)c)letsend_varmnc=ret(funobj->sendcache(Obj.magic(Array.unsafe_getobjn):obj)m(Array.unsafe_getobj0)c)letsend_envmenc=ret(funobj->sendcache(Obj.magic(Array.unsafe_get(Obj.magic(Array.unsafe_getobje):obj)n):obj)m(Array.unsafe_getobj0)c)letsend_methmnc=ret(funobj->sendcache(sendselfobjn)m(Array.unsafe_getobj0)c)letnew_cachetable=letn=new_methodtableinletn=ifnmod2=0||n>2+magictable.methods.(1)*16/Sys.word_sizethennelsenew_methodtableintable.methods.(n)<-Obj.magic0;ntypeimpl=GetConst|GetVar|GetEnv|GetMeth|SetVar|AppConst|AppVar|AppEnv|AppMeth|AppConstConst|AppConstVar|AppConstEnv|AppConstMeth|AppVarConst|AppEnvConst|AppMethConst|MethAppConst|MethAppVar|MethAppEnv|MethAppMeth|SendConst|SendVar|SendEnv|SendMeth|Closureofclosureletmethod_impltableiarr=letnext()=incri;magicarr.(!i)inmatchnext()withGetConst->letx:t=next()inget_constx|GetVar->letn=next()inget_varn|GetEnv->lete=next()inletn=next()inget_enven|GetMeth->letn=next()inget_methn|SetVar->letn=next()inset_varn|AppConst->letf=next()inletx=next()inapp_constfx|AppVar->letf=next()inletn=next()inapp_varfn|AppEnv->letf=next()inlete=next()inletn=next()inapp_envfen|AppMeth->letf=next()inletn=next()inapp_methfn|AppConstConst->letf=next()inletx=next()inlety=next()inapp_const_constfxy|AppConstVar->letf=next()inletx=next()inletn=next()inapp_const_varfxn|AppConstEnv->letf=next()inletx=next()inlete=next()inletn=next()inapp_const_envfxen|AppConstMeth->letf=next()inletx=next()inletn=next()inapp_const_methfxn|AppVarConst->letf=next()inletn=next()inletx=next()inapp_var_constfnx|AppEnvConst->letf=next()inlete=next()inletn=next()inletx=next()inapp_env_constfenx|AppMethConst->letf=next()inletn=next()inletx=next()inapp_meth_constfnx|MethAppConst->letn=next()inletx=next()inmeth_app_constnx|MethAppVar->letn=next()inletm=next()inmeth_app_varnm|MethAppEnv->letn=next()inlete=next()inletm=next()inmeth_app_envnem|MethAppMeth->letn=next()inletm=next()inmeth_app_methnm|SendConst->letm=next()inletx=next()insend_constmx(new_cachetable)|SendVar->letm=next()inletn=next()insend_varmn(new_cachetable)|SendEnv->letm=next()inlete=next()inletn=next()insend_envmen(new_cachetable)|SendMeth->letm=next()inletn=next()insend_methmn(new_cachetable)|Closure_asclo->magiccloletset_methodstablemethods=letlen=Array.lengthmethodsinleti=ref0inwhile!i<lendoletlabel=methods.(!i)inletclo=method_impltableimethodsinset_methodtablelabelclo;incridone(**** Statistics ****)typestats={classes:int;methods:int;inst_vars:int;}letstats()={classes=!table_count;methods=!method_count;inst_vars=!inst_var_count;}