? bytecomp/alpha_eq.ml
Index: bytecomp/lambda.ml
===================================================================
RCS file: /net/yquem/devel/caml/repository/csl/bytecomp/lambda.ml,v
retrieving revision 1.44
diff -u -r1.44 lambda.ml
--- bytecomp/lambda.ml	25 Aug 2005 15:35:16 -0000	1.44
+++ bytecomp/lambda.ml	2 Feb 2006 05:08:56 -0000
@@ -287,9 +287,10 @@
     let compare = compare
   end)
 
-let free_ids get l =
+let free_ids get used l =
   let fv = ref IdentSet.empty in
   let rec free l =
+    let old = !fv in
     iter free l;
     fv := List.fold_right IdentSet.add (get l) !fv;
     match l with
@@ -307,17 +308,20 @@
         fv := IdentSet.remove v !fv
     | Lassign(id, e) ->
         fv := IdentSet.add id !fv
+    | Lifused(id, e) ->
+        if used && not (IdentSet.mem id old) then fv := IdentSet.remove id !fv
     | Lvar _ | Lconst _ | Lapply _
     | Lprim _ | Lswitch _ | Lstaticraise _
     | Lifthenelse _ | Lsequence _ | Lwhile _
-    | Lsend _ | Levent _ | Lifused _ -> ()
+    | Lsend _ | Levent _ -> ()
   in free l; !fv
 
-let free_variables l =
-  free_ids (function Lvar id -> [id] | _ -> []) l
+let free_variables ?(ifused=false) l =
+  free_ids (function Lvar id -> [id] | _ -> []) ifused l
 
 let free_methods l =
-  free_ids (function Lsend(Self, Lvar meth, obj, _) -> [meth] | _ -> []) l
+  free_ids (function Lsend(Self, Lvar meth, obj, _) -> [meth] | _ -> [])
+    false l
 
 (* Check if an action has a "when" guard *)
 let raise_count = ref 0
Index: bytecomp/lambda.mli
===================================================================
RCS file: /net/yquem/devel/caml/repository/csl/bytecomp/lambda.mli,v
retrieving revision 1.42
diff -u -r1.42 lambda.mli
--- bytecomp/lambda.mli	25 Aug 2005 15:35:16 -0000	1.42
+++ bytecomp/lambda.mli	2 Feb 2006 05:08:56 -0000
@@ -177,7 +177,7 @@
 
 val iter: (lambda -> unit) -> lambda -> unit
 module IdentSet: Set.S with type elt = Ident.t
-val free_variables: lambda -> IdentSet.t
+val free_variables: ?ifused:bool -> lambda -> IdentSet.t
 val free_methods: lambda -> IdentSet.t
 
 val transl_path: Path.t -> lambda
Index: bytecomp/translclass.ml
===================================================================
RCS file: /net/yquem/devel/caml/repository/csl/bytecomp/translclass.ml,v
retrieving revision 1.38
diff -u -r1.38 translclass.ml
--- bytecomp/translclass.ml	13 Aug 2005 20:59:37 -0000	1.38
+++ bytecomp/translclass.ml	2 Feb 2006 05:08:56 -0000
@@ -46,6 +46,10 @@
 
 let lfield v i = Lprim(Pfield i, [Lvar v])
 
+let ltuple l = Lprim(Pmakeblock(0,Immutable), l)
+
+let lprim name args = Lapply(oo_prim name, args)
+
 let transl_label l = share (Const_immstring l)
 
 let rec transl_meth_list lst =
@@ -68,8 +72,8 @@
                                                     Lvar offset])])]))
 
 let transl_val tbl create name =
-  Lapply (oo_prim (if create then "new_variable" else "get_variable"),
-          [Lvar tbl; transl_label name])
+  lprim (if create then "new_variable" else "get_variable")
+    [Lvar tbl; transl_label name]
 
 let transl_vals tbl create vals rem =
   List.fold_right
@@ -82,7 +86,7 @@
     (fun (nm, id) rem ->
        try
          (nm, id,
-          Lapply(oo_prim "get_method", [Lvar tbl; Lvar (Meths.find nm meths)]))
+          lprim "get_method" [Lvar tbl; Lvar (Meths.find nm meths)])
          :: rem
        with Not_found -> rem)
     inh_meths []
@@ -97,17 +101,15 @@
   let (inh_init, obj_init, has_init) = init obj' in
   if obj_init = lambda_unit then
     (inh_init,
-     Lapply (oo_prim (if has_init then "create_object_and_run_initializers"
-                      else"create_object_opt"),
-             [obj; Lvar cl]))
+     lprim (if has_init then "create_object_and_run_initializers"
+            else"create_object_opt")
+       [obj; Lvar cl])
   else begin
    (inh_init,
-    Llet(Strict, obj',
-            Lapply (oo_prim "create_object_opt", [obj; Lvar cl]),
+    Llet(Strict, obj', lprim "create_object_opt" [obj; Lvar cl],
          Lsequence(obj_init,
                    if not has_init then Lvar obj' else
-                   Lapply (oo_prim "run_initializers_opt",
-			   [obj; Lvar obj'; Lvar cl]))))
+                   lprim "run_initializers_opt" [obj; Lvar obj'; Lvar cl])))
   end
 
 let rec build_object_init cl_table obj params inh_init obj_init cl =
@@ -203,14 +205,13 @@
 
 
 let bind_method tbl lab id cl_init =
-  Llet(StrictOpt, id, Lapply (oo_prim "get_method_label",
-                              [Lvar tbl; transl_label lab]),
+  Llet(StrictOpt, id, lprim "get_method_label" [Lvar tbl; transl_label lab],
        cl_init)
 
-let bind_methods tbl meths vals cl_init =
-  let methl = Meths.fold (fun lab id tl -> (lab,id) :: tl) meths [] in
+let bind_methods tbl methl vals cl_init =
   let len = List.length methl and nvals = List.length vals in
-  if len < 2 && nvals = 0 then Meths.fold (bind_method tbl) meths cl_init else
+  if len < 2 && nvals = 0 then
+    List.fold_right (fun (n,i) -> bind_method tbl n i) methl cl_init else
   if len = 0 && nvals < 2 then transl_vals tbl true vals cl_init else
   let ids = Ident.create "ids" in
   let i = ref len in
@@ -229,21 +230,19 @@
 	       vals' cl_init)
   in
   Llet(StrictOpt, ids,
-       Lapply (oo_prim getter,
-               [Lvar tbl; transl_meth_list (List.map fst methl)] @ names),
+       lprim getter
+         ([Lvar tbl; transl_meth_list (List.map fst methl)] @ names),
        List.fold_right
-         (fun (lab,id) lam -> decr i; Llet(StrictOpt, id, lfield ids !i, lam))
+         (fun (lab,id) lam -> decr i; Llet(Alias, id, lfield ids !i, lam))
          methl cl_init)
 
 let output_methods tbl methods lam =
   match methods with
     [] -> lam
   | [lab; code] ->
-      lsequence (Lapply(oo_prim "set_method", [Lvar tbl; lab; code])) lam
+      lsequence (lprim "set_method" [Lvar tbl; lab; code]) lam
   | _ ->
-      lsequence (Lapply(oo_prim "set_methods",
-                        [Lvar tbl; Lprim(Pmakeblock(0,Immutable), methods)]))
-        lam
+      lsequence (lprim "set_methods" [Lvar tbl; ltuple methods]) lam
 
 let rec ignore_cstrs cl =
   match cl.cl_desc with
@@ -266,7 +265,8 @@
            Llet (Strict, obj_init, 
                  Lapply(Lprim(Pfield 1, [lpath]), Lvar cla ::
 			if top then [Lprim(Pfield 3, [lpath])] else []),
-                 bind_super cla super cl_init))
+                 bind_super cla super cl_init),
+           [], [])
       | _ ->
           assert false
       end
@@ -278,10 +278,11 @@
             match field with
               Cf_inher (cl, vals, meths) ->
                 let cl_init = output_methods cla methods cl_init in
-                let inh_init, cl_init =
+                let (inh_init, cl_init, meths', vals') =
                   build_class_init cla false
                     (vals, meths_super cla str.cl_meths meths)
                     inh_init cl_init msubst top cl in
+                let cl_init = bind_methods cla meths' vals' cl_init in
                 (inh_init, cl_init, [], values)
             | Cf_val (name, id, exp) ->
                 (inh_init, cl_init, methods, (name, id)::values)
@@ -304,29 +305,37 @@
                 (inh_init, cl_init, methods, vals @ values)
             | Cf_init exp ->
                 (inh_init,
-                 Lsequence(Lapply (oo_prim "add_initializer",
-                                   Lvar cla :: msubst false (transl_exp exp)),
+                 Lsequence(lprim "add_initializer"
+                             (Lvar cla :: msubst false (transl_exp exp)),
                            cl_init),
                  methods, values))
           str.cl_field
           (inh_init, cl_init, [], [])
       in
       let cl_init = output_methods cla methods cl_init in
-      (inh_init, bind_methods cla str.cl_meths values cl_init)
+      (* inh_init, bind_methods cla str.cl_meths values cl_init *)
+      let methods =  Meths.fold (fun n i l -> (n,i)::l) str.cl_meths [] in
+      (inh_init, cl_init, methods, values)
   | Tclass_fun (pat, vals, cl, _) ->
-      let (inh_init, cl_init) =
+      let (inh_init, cl_init, methods, values) =
         build_class_init cla cstr super inh_init cl_init msubst top cl
       in
+      let fv = free_variables ~ifused:true cl_init in
+      let vals = List.filter (fun (id,_) -> IdentSet.mem id fv) vals in
       let vals = List.map (function (id, _) -> (Ident.name id, id)) vals in
-      (inh_init, transl_vals cla true vals cl_init)
+      (* inh_init, transl_vals cla true vals cl_init *)
+      (inh_init, cl_init, methods, vals @ values)
   | Tclass_apply (cl, exprs) ->
       build_class_init cla cstr super inh_init cl_init msubst top cl
   | Tclass_let (rec_flag, defs, vals, cl) ->
-      let (inh_init, cl_init) =
+      let (inh_init, cl_init, methods, values) =
         build_class_init cla cstr super inh_init cl_init msubst top cl
       in
+      let fv = free_variables ~ifused:true cl_init in
+      let vals = List.filter (fun (id,_) -> IdentSet.mem id fv) vals in
       let vals = List.map (function (id, _) -> (Ident.name id, id)) vals in
-      (inh_init, transl_vals cla true vals cl_init)
+      (* inh_init, transl_vals cla true vals cl_init *)
+      (inh_init, cl_init, methods, vals @ values)
   | Tclass_constraint (cl, vals, meths, concr_meths) ->
       let virt_meths =
         List.filter (fun lab -> not (Concr.mem lab concr_meths)) meths in
@@ -358,23 +367,34 @@
               cl_init valids in
           (inh_init,
            Llet (Strict, inh, 
-		 Lapply(oo_prim "inherits", narrow_args @
-			[lpath; Lconst(Const_pointer(if top then 1 else 0))]),
+		 lprim "inherits"
+                   (narrow_args @
+                    [lpath; Lconst(Const_pointer(if top then 1 else 0))]),
                  Llet(StrictOpt, obj_init, lfield inh 0,
                  Llet(Alias, inh_vals, lfield inh 1,
-                 Llet(Alias, inh_meths, lfield inh 2, cl_init)))))
+                 Llet(Alias, inh_meths, lfield inh 2, cl_init)))),
+          [], [])
       | _ ->
 	  let core cl_init =
             build_class_init cla true super inh_init cl_init msubst top cl
 	  in
 	  if cstr then core cl_init else
-          let (inh_init, cl_init) =
-            core (Lsequence (Lapply (oo_prim "widen", [Lvar cla]), cl_init))
+          let (inh_init, cl_init, methods, values) =
+            core (Lsequence (lprim "widen" [Lvar cla], cl_init))
           in
-          (inh_init,
-           Lsequence(Lapply (oo_prim "narrow", narrow_args), cl_init))
+          let cl_init = bind_methods cla methods values cl_init in
+          (inh_init, Lsequence(lprim "narrow" narrow_args, cl_init), [], [])
       end
 
+let build_class_init cla env inh_init obj_init msubst top cl =
+  let inh_init = List.rev inh_init in
+  let (inh_init, cl_init, methods, values) =
+    build_class_init cla true ([],[]) inh_init obj_init msubst top cl in
+  assert (inh_init = []);
+  if IdentSet.mem env (free_variables ~ifused:true cl_init)
+  then bind_methods cla methods (("", env) :: values) cl_init
+  else Llet(Alias, env, lambda_unit, bind_methods cla methods values cl_init)
+
 let rec build_class_lets cl =
   match cl.cl_desc with
     Tclass_let (rec_flag, defs, vals, cl) ->
@@ -459,16 +479,16 @@
     Strict, new_init, lfunction [obj_init] obj_init',
     Llet(
     Alias, cla, transl_path path,
-    Lprim(Pmakeblock(0, Immutable),
-          [Lapply(Lvar new_init, [lfield cla 0]);
-           lfunction [table]
-             (Llet(Strict, env_init,
-                   Lapply(lfield cla 1, [Lvar table]),
-                   lfunction [envs]
-                     (Lapply(Lvar new_init,
-                             [Lapply(Lvar env_init, [Lvar envs])]))));
-           lfield cla 2;
-           lfield cla 3])))
+    ltuple
+      [Lapply(Lvar new_init, [lfield cla 0]);
+       lfunction [table]
+         (Llet(Strict, env_init,
+               Lapply(lfield cla 1, [Lvar table]),
+               lfunction [envs]
+                 (Lapply(Lvar new_init,
+                         [Lapply(Lvar env_init, [Lvar envs])]))));
+       lfield cla 2;
+       lfield cla 3]))
   with Exit ->
     lambda_unit
 
@@ -541,7 +561,7 @@
   open CamlinternalOO
   let builtin_meths arr self env env2 body =
     let builtin, args = builtin_meths self env env2 body in
-    if not arr then [Lapply(oo_prim builtin, args)] else
+    if not arr then [lprim builtin args] else
     let tag = match builtin with
       "get_const" -> GetConst
     | "get_var"   -> GetVar
@@ -599,7 +619,8 @@
 
   (* Prepare for heavy environment handling *)
   let tables = Ident.create (Ident.name cl_id ^ "_tables") in
-  let (top_env, req) = oo_add_class tables in
+  let table_init = ref None in
+  let (top_env, req) = oo_add_class tables table_init in
   let top = not req in
   let cl_env, llets = build_class_lets cl in
   let new_ids = if top then [] else Env.diff top_env cl_env in
@@ -633,6 +654,7 @@
         begin try
           (* Doesn't seem to improve size for bytecode *)
           (* if not !Clflags.native_code then raise Not_found; *)
+          if !Clflags.debug then raise Not_found;
           builtin_meths arr [self] env env2 (lfunction args body')
         with Not_found ->
           [lfunction (self :: args)
@@ -665,15 +687,8 @@
     build_object_init_0 cla [] cl copy_env subst_env top ids in
   if not (Translcore.check_recursive_lambda ids obj_init) then
     raise(Error(cl.cl_loc, Illegal_class_expr));
-  let inh_init' = List.rev inh_init in
-  let (inh_init', cl_init) =
-    build_class_init cla true ([],[]) inh_init' obj_init msubst top cl
-  in
-  assert (inh_init' = []);
-  let table = Ident.create "table"
-  and class_init = Ident.create (Ident.name cl_id ^ "_init")
-  and env_init = Ident.create "env_init"
-  and obj_init = Ident.create "obj_init" in
+  let cl_init = build_class_init cla env2 inh_init obj_init msubst top cl in
+  let obj_init = Ident.create "obj_init" in
   let pub_meths =
     List.sort
       (fun s s' -> compare (Btype.hash_variant s) (Btype.hash_variant s'))
@@ -685,42 +700,44 @@
       let name' = List.assoc tag rev_map in
       if name' <> name then raise(Error(cl.cl_loc, Tags(name, name'))))
     tags pub_meths;
+  let pos = cl.cl_loc.Location.loc_end in
+  let filepos = [transl_label pos.Lexing.pos_fname;
+                 Lconst(Const_base(Const_int pos.Lexing.pos_cnum))] in
   let ltable table lam =
-    Llet(Strict, table,
-         Lapply (oo_prim "create_table", [transl_meth_list pub_meths]), lam)
+    Llet(Strict, table, lprim "create_table" [transl_meth_list pub_meths], lam)
   and ldirect obj_init =
     Llet(Strict, obj_init, cl_init,
-         Lsequence(Lapply (oo_prim "init_class", [Lvar cla]),
+         Lsequence(lprim "init_class_shared" (Lvar cla :: filepos),
                    Lapply(Lvar obj_init, [lambda_unit])))
   in
   (* Simplest case: an object defined at toplevel (ids=[]) *)
   if top && ids = [] then llets (ltable cla (ldirect obj_init)) else
 
+  let table = Ident.create "table"
+  and class_init = Ident.create (Ident.name cl_id ^ "_init")
+  and env_init = Ident.create (Ident.name cl_id ^ "_env_init") in
+  let cl_init_fun = Lfunction(Curried, [cla], cl_init) in
   let concrete =
     ids = [] ||
     Typeclass.virtual_methods (Ctype.signature_of_class_type cl.cl_type) = []
-  and lclass lam =
-    let cl_init = llets (Lfunction(Curried, [cla], cl_init)) in
+  and lclass cl_init lam =
     Llet(Strict, class_init, cl_init, lam (free_variables cl_init))
   and lbody fv =
     if List.for_all (fun id -> not (IdentSet.mem id fv)) ids then
-      Lapply (oo_prim "make_class",[transl_meth_list pub_meths;
-				    Lvar class_init])
+      lprim "make_class"
+        (transl_meth_list pub_meths :: Lvar class_init :: filepos)
     else
       ltable table (
       Llet(
       Strict, env_init, Lapply(Lvar class_init, [Lvar table]),
-      Lsequence(
-      Lapply (oo_prim "init_class", [Lvar table]),
-      Lprim(Pmakeblock(0, Immutable),
-	    [Lapply(Lvar env_init, [lambda_unit]);
-	     Lvar class_init; Lvar env_init; lambda_unit]))))
+      Lsequence(lprim "init_class_shared" (Lvar table :: filepos),
+                ltuple [Lapply(Lvar env_init, [lambda_unit]);
+	                Lvar class_init; Lvar env_init; lambda_unit])))
   and lbody_virt lenvs =
-    Lprim(Pmakeblock(0, Immutable),
-          [lambda_unit; Lfunction(Curried,[cla], cl_init); lambda_unit; lenvs])
+    ltuple [lambda_unit; cl_init_fun; lambda_unit; lenvs]
   in
   (* Still easy: a class defined at toplevel *)
-  if top && concrete then lclass lbody else
+  if top && concrete then lclass (llets cl_init_fun) lbody else
   if top then llets (lbody_virt lambda_unit) else
 
   (* Now for the hard stuff: prepare for table cacheing *)
@@ -733,23 +750,16 @@
   let lenv =
     let menv =
       if !new_ids_meths = [] then lambda_unit else
-      Lprim(Pmakeblock(0, Immutable),
-            List.map (fun id -> Lvar id) !new_ids_meths) in
+      ltuple (List.map (fun id -> Lvar id) !new_ids_meths) in
     if !new_ids_init = [] then menv else
-    Lprim(Pmakeblock(0, Immutable),
-          menv :: List.map (fun id -> Lvar id) !new_ids_init)
+    ltuple (menv :: List.map (fun id -> Lvar id) !new_ids_init)
   and linh_envs =
     List.map (fun (_, p) -> Lprim(Pfield 3, [transl_path p]))
       (List.rev inh_init)
   in
   let make_envs lam =
     Llet(StrictOpt, envs,
-         (if linh_envs = [] then lenv else
-         Lprim(Pmakeblock(0, Immutable), lenv :: linh_envs)),
-         lam)
-  and def_ids cla lam =
-    Llet(StrictOpt, env2,
-         Lapply (oo_prim "new_variable", [Lvar cla; transl_label ""]),
+         (if linh_envs = [] then lenv else ltuple (lenv :: linh_envs)),
          lam)
   in
   let inh_paths =
@@ -757,46 +767,53 @@
       (fun (_,path) -> List.mem (Path.head path) new_ids) inh_init in
   let inh_keys =
     List.map (fun (_,p) -> Lprim(Pfield 1, [transl_path p])) inh_paths in
-  let lclass lam =
-    Llet(Strict, class_init,
-         Lfunction(Curried, [cla], def_ids cla cl_init), lam)
+  let lclass_init lam =
+    Llet(Strict, class_init, cl_init_fun, lam)
   and lcache lam =
     if inh_keys = [] then Llet(Alias, cached, Lvar tables, lam) else
-    Llet(Strict, cached,
-         Lapply(oo_prim "lookup_tables",
-                [Lvar tables; Lprim(Pmakeblock(0, Immutable), inh_keys)]),
+    Llet(Strict, cached, lprim "lookup_tables" [Lvar tables; ltuple inh_keys],
          lam)
   and lset cached i lam =
     Lprim(Psetfield(i, true), [Lvar cached; lam])
   in
-  let ldirect () =
-    ltable cla
-      (Llet(Strict, env_init, def_ids cla cl_init,
-            Lsequence(Lapply (oo_prim "init_class", [Lvar cla]),
-                      lset cached 0 (Lvar env_init))))
-  and lclass_virt () =
-    lset cached 0 (Lfunction(Curried, [cla], def_ids cla cl_init))
+  let ldirect prim pos =
+    ltable cla (
+    Llet(Strict, env_init, cl_init,
+         Lsequence(lprim prim (Lvar cla :: pos), Lvar env_init)))
+  and lclass_concrete cached =
+    ltuple [Lapply (lfield cached 0, [lenvs]);
+            lfield cached 1; lfield cached 0; lenvs]
   in
+
   llets (
-  lcache (
-  Lsequence(
-  Lifthenelse(lfield cached 0, lambda_unit,
-              if ids = [] then ldirect () else
-              if not concrete then lclass_virt () else
-              lclass (
-              Lapply (oo_prim "make_class_store",
-                      [transl_meth_list pub_meths;
-                       Lvar class_init; Lvar cached]))),
   make_envs (
-  if ids = [] then Lapply(lfield cached 0, [lenvs]) else
-  Lprim(Pmakeblock(0, Immutable),
-        if concrete then
-          [Lapply(lfield cached 0, [lenvs]);
-           lfield cached 1;
-           lfield cached 0;
-           lenvs]
-        else [lambda_unit; lfield cached 0; lambda_unit; lenvs]
-       )))))
+  if inh_paths = [] && concrete then
+    if ids = [] then begin
+      table_init := Some (ldirect "init_class_shared" filepos);
+      Lapply (Lvar tables, [lenvs])
+    end else begin
+      let init =
+        lclass cl_init_fun (fun _ ->
+          lprim "make_class_env"
+            (transl_meth_list pub_meths :: Lvar class_init :: filepos))
+      in table_init := Some init;
+      lclass_concrete tables
+    end
+  else begin
+    lcache (
+    Lsequence(
+    Lifthenelse(lfield cached 0, lambda_unit,
+                if ids = [] then lset cached 0 (ldirect "init_class" []) else
+                if not concrete then lset cached 0 cl_init_fun else
+                lclass_init (
+                lprim "make_class_store"
+                  [transl_meth_list pub_meths; Lvar class_init; Lvar cached])),
+    llets (
+    make_envs (
+    if ids = [] then Lapply(lfield cached 0, [lenvs]) else
+    if concrete then lclass_concrete cached else
+    ltuple [lambda_unit; lfield cached 0; lambda_unit; lenvs]))))
+  end))
 
 (* Wrapper for class compilation *)
 
Index: bytecomp/translobj.ml
===================================================================
RCS file: /net/yquem/devel/caml/repository/csl/bytecomp/translobj.ml,v
retrieving revision 1.9
diff -u -r1.9 translobj.ml
--- bytecomp/translobj.ml	26 May 2004 11:10:51 -0000	1.9
+++ bytecomp/translobj.ml	2 Feb 2006 05:08:56 -0000
@@ -88,7 +88,6 @@
 
 (* Insert labels *)
 
-let string s = Lconst (Const_base (Const_string s))
 let int n = Lconst (Const_base (Const_int n))
 
 let prim_makearray =
@@ -124,8 +123,8 @@
 let top_env = ref Env.empty
 let classes = ref []
 
-let oo_add_class id =
-  classes := id :: !classes;
+let oo_add_class id init =
+  classes := (id, init) :: !classes;
   (!top_env, !cache_required)
 
 let oo_wrap env req f x =
@@ -141,10 +140,12 @@
     let lambda = f x in
     let lambda =
       List.fold_left
-        (fun lambda id ->
+        (fun lambda (id, init) ->
           Llet(StrictOpt, id,
-               Lprim(Pmakeblock(0, Mutable),
-                     [lambda_unit; lambda_unit; lambda_unit]),
+               (match !init with
+                 Some lam -> lam
+               | None -> Lprim(Pmakeblock(0, Mutable),
+                               [lambda_unit; lambda_unit; lambda_unit])),
                lambda))
         lambda !classes
     in
Index: bytecomp/translobj.mli
===================================================================
RCS file: /net/yquem/devel/caml/repository/csl/bytecomp/translobj.mli,v
retrieving revision 1.6
diff -u -r1.6 translobj.mli
--- bytecomp/translobj.mli	26 May 2004 11:10:51 -0000	1.6
+++ bytecomp/translobj.mli	2 Feb 2006 05:08:56 -0000
@@ -25,4 +25,4 @@
     Ident.t -> int -> ('a -> lambda) -> 'a -> int * lambda
 
 val oo_wrap: Env.t -> bool -> ('a -> lambda) -> 'a -> lambda
-val oo_add_class: Ident.t -> Env.t * bool
+val oo_add_class: Ident.t -> Lambda.lambda option ref -> Env.t * bool
Index: byterun/compare.h
===================================================================
RCS file: /net/yquem/devel/caml/repository/csl/byterun/compare.h,v
retrieving revision 1.2
diff -u -r1.2 compare.h
--- byterun/compare.h	31 Dec 2003 14:20:35 -0000	1.2
+++ byterun/compare.h	2 Feb 2006 05:08:56 -0000
@@ -17,5 +17,6 @@
 #define CAML_COMPARE_H
 
 CAMLextern int caml_compare_unordered;
+CAMLextern value caml_compare(value, value);
 
 #endif /* CAML_COMPARE_H */
Index: byterun/extern.c
===================================================================
RCS file: /net/yquem/devel/caml/repository/csl/byterun/extern.c,v
retrieving revision 1.59
diff -u -r1.59 extern.c
--- byterun/extern.c	4 Jan 2006 16:55:49 -0000	1.59
+++ byterun/extern.c	2 Feb 2006 05:08:56 -0000
@@ -411,6 +411,22 @@
       extern_record_location(v);
       break;
     }
+    case Object_tag: {
+      value field0;
+      mlsize_t i;
+      i = Wosize_val(Field(v, 0)) - 1;
+      field0 = Field(Field(v, 0),i);
+      if (Wosize_val(field0) > 0) {
+        writecode32(CODE_OBJECT, Wosize_hd (hd));
+        extern_record_location(v);
+        extern_rec(field0);
+        for (i = 1; i < sz - 1; i++) extern_rec(Field(v, i));
+        v = Field(v, i);
+        goto tailcall;
+      }
+      if (!extern_closures)
+        extern_invalid_argument("output_value: dynamic class");
+    } /* may fall through */
     default: {
       value field0;
       mlsize_t i;
Index: byterun/intern.c
===================================================================
RCS file: /net/yquem/devel/caml/repository/csl/byterun/intern.c,v
retrieving revision 1.60
diff -u -r1.60 intern.c
--- byterun/intern.c	22 Sep 2005 14:21:50 -0000	1.60
+++ byterun/intern.c	2 Feb 2006 05:08:56 -0000
@@ -28,6 +28,8 @@
 #include "mlvalues.h"
 #include "misc.h"
 #include "reverse.h"
+#include "callback.h"
+#include "compare.h"
 
 static unsigned char * intern_src;
 /* Reading pointer in block holding input data. */
@@ -98,6 +100,25 @@
 #define readblock(dest,len) \
   (memmove((dest), intern_src, (len)), intern_src += (len))
 
+static value get_method_table (value key)
+{
+  static value *classes = NULL;
+  value current;
+  if (classes == NULL) {
+    classes = caml_named_value("caml_oo_classes");
+    if (classes == NULL) return 0;
+    caml_register_global_root(classes);
+  }
+  for (current = Field(*classes, 0); Is_block(current);
+       current = Field(current, 1))
+  {
+    value head = Field(current, 0);
+    if (caml_compare(key, Field(head, 0)) == Val_int(0))
+      return Field(head, 1);
+  }
+  return 0;
+}
+
 static void intern_cleanup(void)
 {
   if (intern_input_malloced) caml_stat_free(intern_input);
@@ -315,6 +336,24 @@
         Custom_ops_val(v) = ops;
         intern_dest += 1 + size;
         break;
+      case CODE_OBJECT:
+        size = read32u();
+        v = Val_hp(intern_dest);
+        *dest = v;
+        if (intern_obj_table != NULL) intern_obj_table[obj_counter++] = v;
+        dest = (value *) (intern_dest + 1);
+        *intern_dest = Make_header(size, Object_tag, intern_color);
+        intern_dest += 1 + size;
+        intern_rec(dest);
+        *dest = get_method_table(*dest);
+        if (*dest == 0) {
+          intern_cleanup();
+          caml_failwith("input_value: unknown class");
+        }
+        for(size--, dest++; size > 1; size--, dest++)
+          intern_rec(dest);
+        goto tailcall;
+        
       default:
         intern_cleanup();
         caml_failwith("input_value: ill-formed message");
Index: byterun/intext.h
===================================================================
RCS file: /net/yquem/devel/caml/repository/csl/byterun/intext.h,v
retrieving revision 1.32
diff -u -r1.32 intext.h
--- byterun/intext.h	22 Sep 2005 14:21:50 -0000	1.32
+++ byterun/intext.h	2 Feb 2006 05:08:56 -0000
@@ -56,6 +56,7 @@
 #define CODE_CODEPOINTER 0x10
 #define CODE_INFIXPOINTER 0x11
 #define CODE_CUSTOM 0x12
+#define CODE_OBJECT 0x14
 
 #if ARCH_FLOAT_ENDIANNESS == 0x76543210
 #define CODE_DOUBLE_NATIVE CODE_DOUBLE_BIG
Index: stdlib/camlinternalOO.ml
===================================================================
RCS file: /net/yquem/devel/caml/repository/csl/stdlib/camlinternalOO.ml,v
retrieving revision 1.14
diff -u -r1.14 camlinternalOO.ml
--- stdlib/camlinternalOO.ml	25 Oct 2005 18:34:07 -0000	1.14
+++ stdlib/camlinternalOO.ml	2 Feb 2006 05:08:56 -0000
@@ -305,10 +305,38 @@
     public_methods;
   table
 
+(*
+let create_table_variables pub_meths priv_meths vars =
+  let tbl = create_table pub_meths in
+  let pub_meths = to_array pub_meths
+  and priv_meths = to_array priv_meths
+  and vars = to_array vars in
+  let len = 2 + Array.length pub_meths + Array.length priv_meths in
+  let res = Array.create len tbl in
+  let mv = new_methods_variables tbl pub_meths vars in
+  Array.blit mv 0 res 1;
+  res
+*)
+
 let init_class table =
   inst_var_count := !inst_var_count + table.size - 1;
   table.initializers <- List.rev table.initializers;
-  resize table (3 + magic table.methods.(1) * 16 / Sys.word_size)
+  let len = 3 + magic table.methods.(1) * 16 / Sys.word_size in
+  (* keep 1 more for extra info *)
+  let len = if len > Array.length table.methods then len else len+1 in
+  resize table len
+
+let classes = ref []
+let () = Callback.register "caml_oo_classes" classes
+
+let init_class_shared table (file : string) (pos : int) =
+  init_class table;
+  let rec unique_pos pos =
+    if List.mem_assoc (file, pos) !classes then unique_pos (pos + 0x100000)
+    else pos in
+  let pos = unique_pos pos in
+  table.methods.(Array.length table.methods - 1) <- Obj.magic (file, pos);
+  classes := ((file, pos), table.methods) :: !classes
 
 let inherits cla vals virt_meths concr_meths (_, super, _, env) top =
   narrow cla vals virt_meths concr_meths;
@@ -319,12 +347,18 @@
    Array.map (fun nm -> get_method cla (get_method_label cla nm))
      (to_array concr_meths))
 
-let make_class pub_meths class_init =
+let make_class pub_meths class_init file pos =
   let table = create_table pub_meths in
   let env_init = class_init table in
-  init_class table;
+  init_class_shared table file pos;
   (env_init (Obj.repr 0), class_init, env_init, Obj.repr 0)
 
+let make_class_env pub_meths class_init file pos =
+  let table = create_table pub_meths in
+  let env_init = class_init table in
+  init_class_shared table file pos;
+  (env_init, class_init)
+
 type init_table = { mutable env_init: t; mutable class_init: table -> t }
 
 let make_class_store pub_meths class_init init_table =
Index: stdlib/camlinternalOO.mli
===================================================================
RCS file: /net/yquem/devel/caml/repository/csl/stdlib/camlinternalOO.mli,v
retrieving revision 1.9
diff -u -r1.9 camlinternalOO.mli
--- stdlib/camlinternalOO.mli	25 Oct 2005 18:34:07 -0000	1.9
+++ stdlib/camlinternalOO.mli	2 Feb 2006 05:08:56 -0000
@@ -43,14 +43,20 @@
 val add_initializer : table -> (obj -> unit) -> unit
 val dummy_table : table
 val create_table : string array -> table
+(* val create_table_variables :
+    string array -> string array -> string array -> table *)
 val init_class : table -> unit
+val init_class_shared : table -> string -> int -> unit
 val inherits :
     table -> string array -> string array -> string array ->
     (t * (table -> obj -> Obj.t) * t * obj) -> bool ->
     (Obj.t * int array * closure array)
 val make_class :
-    string array -> (table -> Obj.t -> t) ->
+    string array -> (table -> Obj.t -> t) -> string -> int ->
     (t * (table -> Obj.t -> t) * (Obj.t -> t) * Obj.t)
+val make_class_env :
+    string array -> (table -> Obj.t -> t) -> string -> int ->
+    (Obj.t -> t) * (table -> Obj.t -> t)
 type init_table
 val make_class_store :
     string array -> (table -> t) -> init_table -> unit
