Merge with trunk; remake dependencies

master
Mark Shinwell 2015-12-22 16:28:35 +00:00
commit 852efd270e
109 changed files with 5379 additions and 2904 deletions

187
.depend
View File

@ -122,10 +122,10 @@ typing/cmt_format.cmi : typing/types.cmi typing/typedtree.cmi \
typing/ctype.cmi : typing/types.cmi typing/path.cmi parsing/longident.cmi \
typing/ident.cmi typing/env.cmi parsing/asttypes.cmi
typing/datarepr.cmi : typing/types.cmi typing/path.cmi typing/ident.cmi
typing/envaux.cmi : typing/subst.cmi typing/path.cmi typing/env.cmi
typing/env.cmi : utils/warnings.cmi typing/types.cmi typing/subst.cmi \
typing/path.cmi parsing/longident.cmi parsing/location.cmi \
typing/ident.cmi utils/consistbl.cmi parsing/asttypes.cmi
typing/envaux.cmi : typing/subst.cmi typing/path.cmi typing/env.cmi
typing/ident.cmi :
typing/includeclass.cmi : typing/types.cmi typing/env.cmi typing/ctype.cmi
typing/includecore.cmi : typing/types.cmi typing/typedtree.cmi \
@ -144,10 +144,10 @@ typing/path.cmi : typing/ident.cmi
typing/predef.cmi : typing/types.cmi typing/path.cmi typing/ident.cmi
typing/primitive.cmi : parsing/parsetree.cmi typing/outcometree.cmi \
parsing/location.cmi
typing/printtyped.cmi : typing/typedtree.cmi
typing/printtyp.cmi : typing/types.cmi typing/path.cmi \
typing/outcometree.cmi parsing/longident.cmi typing/ident.cmi \
typing/env.cmi parsing/asttypes.cmi
typing/printtyped.cmi : typing/typedtree.cmi
typing/stypes.cmi : typing/typedtree.cmi parsing/location.cmi \
typing/annot.cmi
typing/subst.cmi : typing/types.cmi typing/path.cmi typing/ident.cmi
@ -163,11 +163,11 @@ typing/typedecl.cmi : typing/types.cmi typing/typedtree.cmi typing/path.cmi \
parsing/parsetree.cmi parsing/longident.cmi parsing/location.cmi \
typing/includecore.cmi typing/ident.cmi typing/env.cmi \
parsing/asttypes.cmi
typing/typedtreeIter.cmi : typing/typedtree.cmi parsing/asttypes.cmi
typing/typedtreeMap.cmi : typing/typedtree.cmi
typing/typedtree.cmi : typing/types.cmi typing/primitive.cmi typing/path.cmi \
parsing/parsetree.cmi parsing/longident.cmi parsing/location.cmi \
typing/ident.cmi typing/env.cmi parsing/asttypes.cmi
typing/typedtreeIter.cmi : typing/typedtree.cmi parsing/asttypes.cmi
typing/typedtreeMap.cmi : typing/typedtree.cmi
typing/typemod.cmi : typing/types.cmi typing/typedtree.cmi typing/path.cmi \
parsing/parsetree.cmi parsing/longident.cmi parsing/location.cmi \
typing/includemod.cmi typing/ident.cmi typing/env.cmi \
@ -211,6 +211,12 @@ typing/datarepr.cmo : typing/types.cmi typing/path.cmi parsing/location.cmi \
typing/datarepr.cmx : typing/types.cmx typing/path.cmx parsing/location.cmx \
typing/ident.cmx typing/btype.cmx parsing/asttypes.cmi \
typing/datarepr.cmi
typing/envaux.cmo : typing/types.cmi typing/subst.cmi typing/printtyp.cmi \
typing/path.cmi utils/misc.cmi typing/ident.cmi typing/env.cmi \
parsing/asttypes.cmi typing/envaux.cmi
typing/envaux.cmx : typing/types.cmx typing/subst.cmx typing/printtyp.cmx \
typing/path.cmx utils/misc.cmx typing/ident.cmx typing/env.cmx \
parsing/asttypes.cmi typing/envaux.cmi
typing/env.cmo : utils/warnings.cmi typing/types.cmi utils/tbl.cmi \
typing/subst.cmi typing/predef.cmi typing/path.cmi utils/misc.cmi \
parsing/longident.cmi parsing/location.cmi typing/ident.cmi \
@ -223,12 +229,6 @@ typing/env.cmx : utils/warnings.cmx typing/types.cmx utils/tbl.cmx \
typing/datarepr.cmx utils/consistbl.cmx utils/config.cmx \
typing/cmi_format.cmx utils/clflags.cmx parsing/builtin_attributes.cmx \
typing/btype.cmx parsing/asttypes.cmi typing/env.cmi
typing/envaux.cmo : typing/types.cmi typing/subst.cmi typing/printtyp.cmi \
typing/path.cmi utils/misc.cmi typing/ident.cmi typing/env.cmi \
parsing/asttypes.cmi typing/envaux.cmi
typing/envaux.cmx : typing/types.cmx typing/subst.cmx typing/printtyp.cmx \
typing/path.cmx utils/misc.cmx typing/ident.cmx typing/env.cmx \
parsing/asttypes.cmi typing/envaux.cmi
typing/ident.cmo : typing/ident.cmi
typing/ident.cmx : typing/ident.cmi
typing/includeclass.cmo : typing/types.cmi typing/printtyp.cmi \
@ -293,6 +293,12 @@ typing/primitive.cmo : utils/warnings.cmi parsing/parsetree.cmi \
typing/primitive.cmx : utils/warnings.cmx parsing/parsetree.cmi \
typing/outcometree.cmi utils/misc.cmx parsing/location.cmx \
parsing/attr_helper.cmx typing/primitive.cmi
typing/printtyped.cmo : typing/typedtree.cmi parsing/printast.cmi \
typing/path.cmi utils/misc.cmi parsing/longident.cmi parsing/location.cmi \
typing/ident.cmi parsing/asttypes.cmi typing/printtyped.cmi
typing/printtyped.cmx : typing/typedtree.cmx parsing/printast.cmx \
typing/path.cmx utils/misc.cmx parsing/longident.cmx parsing/location.cmx \
typing/ident.cmx parsing/asttypes.cmi typing/printtyped.cmi
typing/printtyp.cmo : typing/types.cmi typing/primitive.cmi \
typing/predef.cmi typing/path.cmi parsing/parsetree.cmi \
typing/outcometree.cmi typing/oprint.cmi utils/misc.cmi \
@ -305,12 +311,6 @@ typing/printtyp.cmx : typing/types.cmx typing/primitive.cmx \
parsing/longident.cmx parsing/location.cmx typing/ident.cmx \
typing/env.cmx typing/ctype.cmx utils/clflags.cmx typing/btype.cmx \
parsing/asttypes.cmi typing/printtyp.cmi
typing/printtyped.cmo : typing/typedtree.cmi parsing/printast.cmi \
typing/path.cmi utils/misc.cmi parsing/longident.cmi parsing/location.cmi \
typing/ident.cmi parsing/asttypes.cmi typing/printtyped.cmi
typing/printtyped.cmx : typing/typedtree.cmx parsing/printast.cmx \
typing/path.cmx utils/misc.cmx parsing/longident.cmx parsing/location.cmx \
typing/ident.cmx parsing/asttypes.cmi typing/printtyped.cmi
typing/stypes.cmo : typing/typedtree.cmi typing/printtyp.cmi \
parsing/location.cmi utils/clflags.cmi typing/annot.cmi typing/stypes.cmi
typing/stypes.cmx : typing/typedtree.cmx typing/printtyp.cmx \
@ -379,14 +379,6 @@ typing/typedecl.cmx : utils/warnings.cmx typing/typetexp.cmx \
typing/ident.cmx typing/env.cmx typing/ctype.cmx utils/config.cmx \
utils/clflags.cmx typing/btype.cmx parsing/attr_helper.cmx \
parsing/asttypes.cmi parsing/ast_helper.cmx typing/typedecl.cmi
typing/typedtree.cmo : typing/types.cmi typing/primitive.cmi typing/path.cmi \
parsing/parsetree.cmi utils/misc.cmi parsing/longident.cmi \
parsing/location.cmi typing/ident.cmi typing/env.cmi parsing/asttypes.cmi \
typing/typedtree.cmi
typing/typedtree.cmx : typing/types.cmx typing/primitive.cmx typing/path.cmx \
parsing/parsetree.cmi utils/misc.cmx parsing/longident.cmx \
parsing/location.cmx typing/ident.cmx typing/env.cmx parsing/asttypes.cmi \
typing/typedtree.cmi
typing/typedtreeIter.cmo : typing/typedtree.cmi utils/misc.cmi \
parsing/asttypes.cmi typing/typedtreeIter.cmi
typing/typedtreeIter.cmx : typing/typedtree.cmx utils/misc.cmx \
@ -395,6 +387,14 @@ typing/typedtreeMap.cmo : typing/typedtree.cmi utils/misc.cmi \
typing/typedtreeMap.cmi
typing/typedtreeMap.cmx : typing/typedtree.cmx utils/misc.cmx \
typing/typedtreeMap.cmi
typing/typedtree.cmo : typing/types.cmi typing/primitive.cmi typing/path.cmi \
parsing/parsetree.cmi utils/misc.cmi parsing/longident.cmi \
parsing/location.cmi typing/ident.cmi typing/env.cmi parsing/asttypes.cmi \
typing/typedtree.cmi
typing/typedtree.cmx : typing/types.cmx typing/primitive.cmx typing/path.cmx \
parsing/parsetree.cmi utils/misc.cmx parsing/longident.cmx \
parsing/location.cmx typing/ident.cmx typing/env.cmx parsing/asttypes.cmi \
typing/typedtree.cmi
typing/typemod.cmo : utils/warnings.cmi typing/typetexp.cmi typing/types.cmi \
typing/typedtree.cmi typing/typedecl.cmi typing/typecore.cmi \
typing/typeclass.cmi typing/subst.cmi typing/stypes.cmi \
@ -449,6 +449,7 @@ bytecomp/bytelink.cmi : bytecomp/symtable.cmi bytecomp/cmo_format.cmi
bytecomp/bytepackager.cmi : typing/ident.cmi typing/env.cmi
bytecomp/bytesections.cmi :
bytecomp/cmo_format.cmi : bytecomp/lambda.cmi typing/ident.cmi
bytecomp/debuginfo.cmi : parsing/location.cmi bytecomp/lambda.cmi
bytecomp/dll.cmi :
bytecomp/emitcode.cmi : bytecomp/instruct.cmi bytecomp/cmo_format.cmi
bytecomp/instruct.cmi : typing/types.cmi typing/subst.cmi \
@ -517,6 +518,10 @@ bytecomp/bytepackager.cmx : typing/typemod.cmx bytecomp/translmod.cmx \
bytecomp/bytegen.cmx bytecomp/bytepackager.cmi
bytecomp/bytesections.cmo : utils/config.cmi bytecomp/bytesections.cmi
bytecomp/bytesections.cmx : utils/config.cmx bytecomp/bytesections.cmi
bytecomp/debuginfo.cmo : parsing/location.cmi bytecomp/lambda.cmi \
bytecomp/debuginfo.cmi
bytecomp/debuginfo.cmx : parsing/location.cmx bytecomp/lambda.cmx \
bytecomp/debuginfo.cmi
bytecomp/dll.cmo : utils/misc.cmi utils/config.cmi bytecomp/dll.cmi
bytecomp/dll.cmx : utils/misc.cmx utils/config.cmx bytecomp/dll.cmi
bytecomp/emitcode.cmo : bytecomp/translmod.cmi typing/primitive.cmi \
@ -625,18 +630,18 @@ bytecomp/translcore.cmx : typing/types.cmx bytecomp/typeopt.cmx \
typing/btype.cmx parsing/asttypes.cmi bytecomp/translcore.cmi
bytecomp/translmod.cmo : typing/types.cmi typing/typedtree.cmi \
bytecomp/translobj.cmi bytecomp/translcore.cmi bytecomp/translclass.cmi \
typing/printtyp.cmi typing/primitive.cmi typing/predef.cmi \
typing/path.cmi typing/mtype.cmi utils/misc.cmi parsing/longident.cmi \
parsing/location.cmi bytecomp/lambda.cmi typing/ident.cmi typing/env.cmi \
typing/ctype.cmi utils/clflags.cmi parsing/asttypes.cmi \
bytecomp/translmod.cmi
bytecomp/translattribute.cmi typing/printtyp.cmi typing/primitive.cmi \
typing/predef.cmi typing/path.cmi typing/mtype.cmi utils/misc.cmi \
parsing/longident.cmi parsing/location.cmi bytecomp/lambda.cmi \
typing/ident.cmi typing/env.cmi typing/ctype.cmi utils/clflags.cmi \
parsing/asttypes.cmi bytecomp/translmod.cmi
bytecomp/translmod.cmx : typing/types.cmx typing/typedtree.cmx \
bytecomp/translobj.cmx bytecomp/translcore.cmx bytecomp/translclass.cmx \
typing/printtyp.cmx typing/primitive.cmx typing/predef.cmx \
typing/path.cmx typing/mtype.cmx utils/misc.cmx parsing/longident.cmx \
parsing/location.cmx bytecomp/lambda.cmx typing/ident.cmx typing/env.cmx \
typing/ctype.cmx utils/clflags.cmx parsing/asttypes.cmi \
bytecomp/translmod.cmi
bytecomp/translattribute.cmx typing/printtyp.cmx typing/primitive.cmx \
typing/predef.cmx typing/path.cmx typing/mtype.cmx utils/misc.cmx \
parsing/longident.cmx parsing/location.cmx bytecomp/lambda.cmx \
typing/ident.cmx typing/env.cmx typing/ctype.cmx utils/clflags.cmx \
parsing/asttypes.cmi bytecomp/translmod.cmi
bytecomp/translobj.cmo : typing/primitive.cmi utils/misc.cmi \
parsing/longident.cmi bytecomp/lambda.cmi typing/ident.cmi typing/env.cmi \
utils/clflags.cmi typing/btype.cmi parsing/asttypes.cmi \
@ -651,7 +656,6 @@ bytecomp/typeopt.cmo : typing/types.cmi typing/typedtree.cmi \
bytecomp/typeopt.cmx : typing/types.cmx typing/typedtree.cmx \
typing/predef.cmx typing/path.cmx bytecomp/lambda.cmx typing/ident.cmx \
typing/env.cmx typing/ctype.cmx typing/btype.cmx bytecomp/typeopt.cmi
asmcomp/CSEgen.cmi : asmcomp/mach.cmi
asmcomp/asmgen.cmi : bytecomp/lambda.cmi asmcomp/cmm.cmi
asmcomp/asmlibrarian.cmi :
asmcomp/asmlink.cmi : asmcomp/cmx_format.cmi
@ -659,38 +663,39 @@ asmcomp/asmpackager.cmi : typing/env.cmi
asmcomp/branch_relaxation.cmi : asmcomp/linearize.cmi \
asmcomp/branch_relaxation_intf.cmo
asmcomp/clambda.cmi : bytecomp/lambda.cmi typing/ident.cmi \
asmcomp/debuginfo.cmi parsing/asttypes.cmi
bytecomp/debuginfo.cmi parsing/asttypes.cmi
asmcomp/closure.cmi : bytecomp/lambda.cmi asmcomp/clambda.cmi
asmcomp/cmm.cmi : bytecomp/lambda.cmi typing/ident.cmi asmcomp/debuginfo.cmi
asmcomp/cmmgen.cmi : asmcomp/cmx_format.cmi asmcomp/cmm.cmi \
asmcomp/clambda.cmi
asmcomp/cmm.cmi : bytecomp/lambda.cmi typing/ident.cmi \
bytecomp/debuginfo.cmi
asmcomp/cmx_format.cmi : asmcomp/clambda.cmi
asmcomp/coloring.cmi :
asmcomp/comballoc.cmi : asmcomp/mach.cmi
asmcomp/compilenv.cmi : utils/timings.cmi typing/ident.cmi \
asmcomp/cmx_format.cmi asmcomp/clambda.cmi
asmcomp/CSEgen.cmi : asmcomp/mach.cmi
asmcomp/deadcode.cmi : asmcomp/mach.cmi
asmcomp/debuginfo.cmi : parsing/location.cmi bytecomp/lambda.cmi
asmcomp/emitaux.cmi : bytecomp/debuginfo.cmi
asmcomp/emit.cmi : asmcomp/linearize.cmi asmcomp/cmm.cmi
asmcomp/emitaux.cmi : asmcomp/debuginfo.cmi
asmcomp/interf.cmi : asmcomp/mach.cmi
asmcomp/linearize.cmi : asmcomp/reg.cmi asmcomp/mach.cmi bytecomp/lambda.cmi \
asmcomp/debuginfo.cmi
bytecomp/debuginfo.cmi
asmcomp/liveness.cmi : asmcomp/mach.cmi
asmcomp/mach.cmi : asmcomp/reg.cmi bytecomp/lambda.cmi asmcomp/debuginfo.cmi \
asmcomp/cmm.cmi asmcomp/arch.cmo
asmcomp/mach.cmi : asmcomp/reg.cmi bytecomp/lambda.cmi \
bytecomp/debuginfo.cmi asmcomp/cmm.cmi asmcomp/arch.cmo
asmcomp/printclambda.cmi : asmcomp/clambda.cmi
asmcomp/printcmm.cmi : asmcomp/cmm.cmi
asmcomp/printlinear.cmi : asmcomp/linearize.cmi
asmcomp/printmach.cmi : asmcomp/reg.cmi asmcomp/mach.cmi
asmcomp/proc.cmi : asmcomp/reg.cmi asmcomp/mach.cmi
asmcomp/reg.cmi : typing/ident.cmi asmcomp/cmm.cmi
asmcomp/reload.cmi : asmcomp/mach.cmi
asmcomp/reloadgen.cmi : asmcomp/reg.cmi asmcomp/mach.cmi
asmcomp/reload.cmi : asmcomp/mach.cmi
asmcomp/schedgen.cmi : asmcomp/mach.cmi asmcomp/linearize.cmi
asmcomp/scheduling.cmi : asmcomp/linearize.cmi
asmcomp/selectgen.cmi : utils/tbl.cmi asmcomp/reg.cmi asmcomp/mach.cmi \
typing/ident.cmi asmcomp/debuginfo.cmi asmcomp/cmm.cmi asmcomp/arch.cmo
typing/ident.cmi bytecomp/debuginfo.cmi asmcomp/cmm.cmi asmcomp/arch.cmo
asmcomp/selection.cmi : asmcomp/mach.cmi asmcomp/cmm.cmi
asmcomp/spill.cmi : asmcomp/mach.cmi
asmcomp/split.cmi : asmcomp/mach.cmi
@ -700,12 +705,6 @@ asmcomp/x86_dsl.cmi : asmcomp/x86_ast.cmi
asmcomp/x86_gas.cmi : asmcomp/x86_ast.cmi
asmcomp/x86_masm.cmi : asmcomp/x86_ast.cmi
asmcomp/x86_proc.cmi : asmcomp/x86_ast.cmi
asmcomp/CSE.cmo : asmcomp/mach.cmi asmcomp/CSEgen.cmi asmcomp/arch.cmo
asmcomp/CSE.cmx : asmcomp/mach.cmx asmcomp/CSEgen.cmx asmcomp/arch.cmx
asmcomp/CSEgen.cmo : asmcomp/reg.cmi asmcomp/proc.cmi asmcomp/mach.cmi \
asmcomp/cmm.cmi asmcomp/CSEgen.cmi
asmcomp/CSEgen.cmx : asmcomp/reg.cmx asmcomp/proc.cmx asmcomp/mach.cmx \
asmcomp/cmm.cmx asmcomp/CSEgen.cmi
asmcomp/arch.cmo : utils/clflags.cmi
asmcomp/arch.cmx : utils/clflags.cmx
asmcomp/asmgen.cmo : bytecomp/translmod.cmi utils/timings.cmi \
@ -758,44 +757,44 @@ asmcomp/asmpackager.cmx : typing/typemod.cmx bytecomp/translmod.cmx \
typing/env.cmx utils/config.cmx asmcomp/compilenv.cmx \
asmcomp/cmx_format.cmi utils/clflags.cmx utils/ccomp.cmx \
asmcomp/asmlink.cmx asmcomp/asmgen.cmx asmcomp/asmpackager.cmi
asmcomp/branch_relaxation_intf.cmo : asmcomp/linearize.cmi asmcomp/arch.cmo
asmcomp/branch_relaxation_intf.cmx : asmcomp/linearize.cmx asmcomp/arch.cmx
asmcomp/branch_relaxation.cmo : utils/misc.cmi asmcomp/mach.cmi \
asmcomp/linearize.cmi asmcomp/cmm.cmi asmcomp/branch_relaxation_intf.cmo \
asmcomp/branch_relaxation.cmi
asmcomp/branch_relaxation.cmx : utils/misc.cmx asmcomp/mach.cmx \
asmcomp/linearize.cmx asmcomp/cmm.cmx asmcomp/branch_relaxation_intf.cmx \
asmcomp/branch_relaxation.cmi
asmcomp/branch_relaxation_intf.cmo : asmcomp/linearize.cmi asmcomp/arch.cmo
asmcomp/branch_relaxation_intf.cmx : asmcomp/linearize.cmx asmcomp/arch.cmx
asmcomp/clambda.cmo : bytecomp/lambda.cmi typing/ident.cmi \
asmcomp/debuginfo.cmi parsing/asttypes.cmi asmcomp/clambda.cmi
bytecomp/debuginfo.cmi parsing/asttypes.cmi asmcomp/clambda.cmi
asmcomp/clambda.cmx : bytecomp/lambda.cmx typing/ident.cmx \
asmcomp/debuginfo.cmx parsing/asttypes.cmi asmcomp/clambda.cmi
bytecomp/debuginfo.cmx parsing/asttypes.cmi asmcomp/clambda.cmi
asmcomp/closure.cmo : utils/warnings.cmi utils/tbl.cmi bytecomp/switch.cmi \
typing/primitive.cmi utils/misc.cmi parsing/location.cmi \
bytecomp/lambda.cmi typing/ident.cmi asmcomp/debuginfo.cmi \
bytecomp/lambda.cmi typing/ident.cmi bytecomp/debuginfo.cmi \
asmcomp/compilenv.cmi utils/clflags.cmi asmcomp/clambda.cmi \
parsing/asttypes.cmi asmcomp/arch.cmo asmcomp/closure.cmi
asmcomp/closure.cmx : utils/warnings.cmx utils/tbl.cmx bytecomp/switch.cmx \
typing/primitive.cmx utils/misc.cmx parsing/location.cmx \
bytecomp/lambda.cmx typing/ident.cmx asmcomp/debuginfo.cmx \
bytecomp/lambda.cmx typing/ident.cmx bytecomp/debuginfo.cmx \
asmcomp/compilenv.cmx utils/clflags.cmx asmcomp/clambda.cmx \
parsing/asttypes.cmi asmcomp/arch.cmx asmcomp/closure.cmi
asmcomp/cmm.cmo : bytecomp/lambda.cmi typing/ident.cmi asmcomp/debuginfo.cmi \
asmcomp/arch.cmo asmcomp/cmm.cmi
asmcomp/cmm.cmx : bytecomp/lambda.cmx typing/ident.cmx asmcomp/debuginfo.cmx \
asmcomp/arch.cmx asmcomp/cmm.cmi
asmcomp/cmmgen.cmo : typing/types.cmi bytecomp/switch.cmi \
asmcomp/strmatch.cmi asmcomp/proc.cmi typing/primitive.cmi utils/misc.cmi \
bytecomp/lambda.cmi typing/ident.cmi asmcomp/debuginfo.cmi \
bytecomp/lambda.cmi typing/ident.cmi bytecomp/debuginfo.cmi \
utils/config.cmi asmcomp/compilenv.cmi asmcomp/cmx_format.cmi \
asmcomp/cmm.cmi utils/clflags.cmi asmcomp/clambda.cmi \
parsing/asttypes.cmi asmcomp/arch.cmo asmcomp/cmmgen.cmi
asmcomp/cmmgen.cmx : typing/types.cmx bytecomp/switch.cmx \
asmcomp/strmatch.cmx asmcomp/proc.cmx typing/primitive.cmx utils/misc.cmx \
bytecomp/lambda.cmx typing/ident.cmx asmcomp/debuginfo.cmx \
bytecomp/lambda.cmx typing/ident.cmx bytecomp/debuginfo.cmx \
utils/config.cmx asmcomp/compilenv.cmx asmcomp/cmx_format.cmi \
asmcomp/cmm.cmx utils/clflags.cmx asmcomp/clambda.cmx \
parsing/asttypes.cmi asmcomp/arch.cmx asmcomp/cmmgen.cmi
asmcomp/cmm.cmo : bytecomp/lambda.cmi typing/ident.cmi \
bytecomp/debuginfo.cmi asmcomp/arch.cmo asmcomp/cmm.cmi
asmcomp/cmm.cmx : bytecomp/lambda.cmx typing/ident.cmx \
bytecomp/debuginfo.cmx asmcomp/arch.cmx asmcomp/cmm.cmi
asmcomp/coloring.cmo : asmcomp/reg.cmi asmcomp/proc.cmi asmcomp/coloring.cmi
asmcomp/coloring.cmx : asmcomp/reg.cmx asmcomp/proc.cmx asmcomp/coloring.cmi
asmcomp/comballoc.cmo : asmcomp/reg.cmi asmcomp/mach.cmi utils/config.cmi \
@ -808,41 +807,43 @@ asmcomp/compilenv.cmo : utils/misc.cmi parsing/location.cmi typing/ident.cmi \
asmcomp/compilenv.cmx : utils/misc.cmx parsing/location.cmx typing/ident.cmx \
typing/env.cmx utils/config.cmx asmcomp/cmx_format.cmi \
asmcomp/clambda.cmx asmcomp/compilenv.cmi
asmcomp/CSEgen.cmo : asmcomp/reg.cmi asmcomp/proc.cmi asmcomp/mach.cmi \
asmcomp/cmm.cmi asmcomp/CSEgen.cmi
asmcomp/CSEgen.cmx : asmcomp/reg.cmx asmcomp/proc.cmx asmcomp/mach.cmx \
asmcomp/cmm.cmx asmcomp/CSEgen.cmi
asmcomp/CSE.cmo : asmcomp/mach.cmi asmcomp/CSEgen.cmi asmcomp/arch.cmo
asmcomp/CSE.cmx : asmcomp/mach.cmx asmcomp/CSEgen.cmx asmcomp/arch.cmx
asmcomp/deadcode.cmo : asmcomp/reg.cmi asmcomp/proc.cmi asmcomp/mach.cmi \
asmcomp/deadcode.cmi
asmcomp/deadcode.cmx : asmcomp/reg.cmx asmcomp/proc.cmx asmcomp/mach.cmx \
asmcomp/deadcode.cmi
asmcomp/debuginfo.cmo : parsing/location.cmi bytecomp/lambda.cmi \
asmcomp/debuginfo.cmi
asmcomp/debuginfo.cmx : parsing/location.cmx bytecomp/lambda.cmx \
asmcomp/debuginfo.cmi
asmcomp/emitaux.cmo : asmcomp/linearize.cmi bytecomp/debuginfo.cmi \
utils/config.cmi utils/clflags.cmi asmcomp/arch.cmo asmcomp/emitaux.cmi
asmcomp/emitaux.cmx : asmcomp/linearize.cmx bytecomp/debuginfo.cmx \
utils/config.cmx utils/clflags.cmx asmcomp/arch.cmx asmcomp/emitaux.cmi
asmcomp/emit.cmo : asmcomp/x86_proc.cmi asmcomp/x86_masm.cmi \
asmcomp/x86_gas.cmi asmcomp/x86_dsl.cmi asmcomp/x86_ast.cmi \
asmcomp/reg.cmi asmcomp/proc.cmi utils/misc.cmi asmcomp/mach.cmi \
asmcomp/linearize.cmi bytecomp/lambda.cmi asmcomp/emitaux.cmi \
asmcomp/debuginfo.cmi utils/config.cmi asmcomp/compilenv.cmi \
bytecomp/debuginfo.cmi utils/config.cmi asmcomp/compilenv.cmi \
asmcomp/cmm.cmi utils/clflags.cmi asmcomp/branch_relaxation.cmi \
asmcomp/arch.cmo asmcomp/emit.cmi
asmcomp/emit.cmx : asmcomp/x86_proc.cmx asmcomp/x86_masm.cmx \
asmcomp/x86_gas.cmx asmcomp/x86_dsl.cmx asmcomp/x86_ast.cmi \
asmcomp/reg.cmx asmcomp/proc.cmx utils/misc.cmx asmcomp/mach.cmx \
asmcomp/linearize.cmx bytecomp/lambda.cmx asmcomp/emitaux.cmx \
asmcomp/debuginfo.cmx utils/config.cmx asmcomp/compilenv.cmx \
bytecomp/debuginfo.cmx utils/config.cmx asmcomp/compilenv.cmx \
asmcomp/cmm.cmx utils/clflags.cmx asmcomp/branch_relaxation.cmx \
asmcomp/arch.cmx asmcomp/emit.cmi
asmcomp/emitaux.cmo : asmcomp/linearize.cmi asmcomp/debuginfo.cmi \
utils/config.cmi utils/clflags.cmi asmcomp/arch.cmo asmcomp/emitaux.cmi
asmcomp/emitaux.cmx : asmcomp/linearize.cmx asmcomp/debuginfo.cmx \
utils/config.cmx utils/clflags.cmx asmcomp/arch.cmx asmcomp/emitaux.cmi
asmcomp/interf.cmo : asmcomp/reg.cmi asmcomp/proc.cmi asmcomp/mach.cmi \
asmcomp/interf.cmi
asmcomp/interf.cmx : asmcomp/reg.cmx asmcomp/proc.cmx asmcomp/mach.cmx \
asmcomp/interf.cmi
asmcomp/linearize.cmo : asmcomp/reg.cmi asmcomp/proc.cmi utils/misc.cmi \
asmcomp/mach.cmi bytecomp/lambda.cmi asmcomp/debuginfo.cmi \
asmcomp/mach.cmi bytecomp/lambda.cmi bytecomp/debuginfo.cmi \
asmcomp/cmm.cmi asmcomp/linearize.cmi
asmcomp/linearize.cmx : asmcomp/reg.cmx asmcomp/proc.cmx utils/misc.cmx \
asmcomp/mach.cmx bytecomp/lambda.cmx asmcomp/debuginfo.cmx \
asmcomp/mach.cmx bytecomp/lambda.cmx bytecomp/debuginfo.cmx \
asmcomp/cmm.cmx asmcomp/linearize.cmi
asmcomp/liveness.cmo : asmcomp/reg.cmi asmcomp/proc.cmi \
asmcomp/printmach.cmi utils/misc.cmi asmcomp/mach.cmi \
@ -850,10 +851,10 @@ asmcomp/liveness.cmo : asmcomp/reg.cmi asmcomp/proc.cmi \
asmcomp/liveness.cmx : asmcomp/reg.cmx asmcomp/proc.cmx \
asmcomp/printmach.cmx utils/misc.cmx asmcomp/mach.cmx \
asmcomp/liveness.cmi
asmcomp/mach.cmo : asmcomp/reg.cmi bytecomp/lambda.cmi asmcomp/debuginfo.cmi \
asmcomp/cmm.cmi asmcomp/arch.cmo asmcomp/mach.cmi
asmcomp/mach.cmx : asmcomp/reg.cmx bytecomp/lambda.cmx asmcomp/debuginfo.cmx \
asmcomp/cmm.cmx asmcomp/arch.cmx asmcomp/mach.cmi
asmcomp/mach.cmo : asmcomp/reg.cmi bytecomp/lambda.cmi \
bytecomp/debuginfo.cmi asmcomp/cmm.cmi asmcomp/arch.cmo asmcomp/mach.cmi
asmcomp/mach.cmx : asmcomp/reg.cmx bytecomp/lambda.cmx \
bytecomp/debuginfo.cmx asmcomp/cmm.cmx asmcomp/arch.cmx asmcomp/mach.cmi
asmcomp/printclambda.cmo : bytecomp/printlambda.cmi bytecomp/lambda.cmi \
typing/ident.cmi asmcomp/clambda.cmi parsing/asttypes.cmi \
asmcomp/printclambda.cmi
@ -861,22 +862,22 @@ asmcomp/printclambda.cmx : bytecomp/printlambda.cmx bytecomp/lambda.cmx \
typing/ident.cmx asmcomp/clambda.cmx parsing/asttypes.cmi \
asmcomp/printclambda.cmi
asmcomp/printcmm.cmo : bytecomp/lambda.cmi typing/ident.cmi \
asmcomp/debuginfo.cmi asmcomp/cmm.cmi asmcomp/printcmm.cmi
bytecomp/debuginfo.cmi asmcomp/cmm.cmi asmcomp/printcmm.cmi
asmcomp/printcmm.cmx : bytecomp/lambda.cmx typing/ident.cmx \
asmcomp/debuginfo.cmx asmcomp/cmm.cmx asmcomp/printcmm.cmi
bytecomp/debuginfo.cmx asmcomp/cmm.cmx asmcomp/printcmm.cmi
asmcomp/printlinear.cmo : asmcomp/printmach.cmi asmcomp/mach.cmi \
asmcomp/linearize.cmi bytecomp/lambda.cmi asmcomp/debuginfo.cmi \
asmcomp/linearize.cmi bytecomp/lambda.cmi bytecomp/debuginfo.cmi \
asmcomp/printlinear.cmi
asmcomp/printlinear.cmx : asmcomp/printmach.cmx asmcomp/mach.cmx \
asmcomp/linearize.cmx bytecomp/lambda.cmx asmcomp/debuginfo.cmx \
asmcomp/linearize.cmx bytecomp/lambda.cmx bytecomp/debuginfo.cmx \
asmcomp/printlinear.cmi
asmcomp/printmach.cmo : asmcomp/reg.cmi asmcomp/proc.cmi \
asmcomp/printcmm.cmi asmcomp/mach.cmi bytecomp/lambda.cmi \
asmcomp/debuginfo.cmi asmcomp/cmm.cmi asmcomp/arch.cmo \
bytecomp/debuginfo.cmi asmcomp/cmm.cmi asmcomp/arch.cmo \
asmcomp/printmach.cmi
asmcomp/printmach.cmx : asmcomp/reg.cmx asmcomp/proc.cmx \
asmcomp/printcmm.cmx asmcomp/mach.cmx bytecomp/lambda.cmx \
asmcomp/debuginfo.cmx asmcomp/cmm.cmx asmcomp/arch.cmx \
bytecomp/debuginfo.cmx asmcomp/cmm.cmx asmcomp/arch.cmx \
asmcomp/printmach.cmi
asmcomp/proc.cmo : asmcomp/x86_proc.cmi asmcomp/reg.cmi utils/misc.cmi \
asmcomp/mach.cmi utils/config.cmi asmcomp/cmm.cmi asmcomp/arch.cmo \
@ -886,14 +887,14 @@ asmcomp/proc.cmx : asmcomp/x86_proc.cmx asmcomp/reg.cmx utils/misc.cmx \
asmcomp/proc.cmi
asmcomp/reg.cmo : typing/ident.cmi asmcomp/cmm.cmi asmcomp/reg.cmi
asmcomp/reg.cmx : typing/ident.cmx asmcomp/cmm.cmx asmcomp/reg.cmi
asmcomp/reload.cmo : asmcomp/reloadgen.cmi asmcomp/reg.cmi asmcomp/mach.cmi \
asmcomp/cmm.cmi utils/clflags.cmi asmcomp/reload.cmi
asmcomp/reload.cmx : asmcomp/reloadgen.cmx asmcomp/reg.cmx asmcomp/mach.cmx \
asmcomp/cmm.cmx utils/clflags.cmx asmcomp/reload.cmi
asmcomp/reloadgen.cmo : asmcomp/reg.cmi utils/misc.cmi asmcomp/mach.cmi \
asmcomp/reloadgen.cmi
asmcomp/reloadgen.cmx : asmcomp/reg.cmx utils/misc.cmx asmcomp/mach.cmx \
asmcomp/reloadgen.cmi
asmcomp/reload.cmo : asmcomp/reloadgen.cmi asmcomp/reg.cmi asmcomp/mach.cmi \
asmcomp/cmm.cmi utils/clflags.cmi asmcomp/reload.cmi
asmcomp/reload.cmx : asmcomp/reloadgen.cmx asmcomp/reg.cmx asmcomp/mach.cmx \
asmcomp/cmm.cmx utils/clflags.cmx asmcomp/reload.cmi
asmcomp/schedgen.cmo : asmcomp/reg.cmi asmcomp/proc.cmi asmcomp/mach.cmi \
asmcomp/linearize.cmi asmcomp/cmm.cmi asmcomp/arch.cmo \
asmcomp/schedgen.cmi
@ -904,11 +905,11 @@ asmcomp/scheduling.cmo : asmcomp/schedgen.cmi asmcomp/scheduling.cmi
asmcomp/scheduling.cmx : asmcomp/schedgen.cmx asmcomp/scheduling.cmi
asmcomp/selectgen.cmo : utils/tbl.cmi bytecomp/simplif.cmi asmcomp/reg.cmi \
asmcomp/proc.cmi utils/misc.cmi asmcomp/mach.cmi bytecomp/lambda.cmi \
typing/ident.cmi asmcomp/debuginfo.cmi asmcomp/cmm.cmi utils/clflags.cmi \
typing/ident.cmi bytecomp/debuginfo.cmi asmcomp/cmm.cmi utils/clflags.cmi \
asmcomp/arch.cmo asmcomp/selectgen.cmi
asmcomp/selectgen.cmx : utils/tbl.cmx bytecomp/simplif.cmx asmcomp/reg.cmx \
asmcomp/proc.cmx utils/misc.cmx asmcomp/mach.cmx bytecomp/lambda.cmx \
typing/ident.cmx asmcomp/debuginfo.cmx asmcomp/cmm.cmx utils/clflags.cmx \
typing/ident.cmx bytecomp/debuginfo.cmx asmcomp/cmm.cmx utils/clflags.cmx \
asmcomp/arch.cmx asmcomp/selectgen.cmi
asmcomp/selection.cmo : asmcomp/selectgen.cmi asmcomp/proc.cmi \
asmcomp/mach.cmi asmcomp/cmm.cmi utils/clflags.cmi asmcomp/arch.cmo \
@ -948,8 +949,8 @@ driver/compenv.cmi :
driver/compile.cmi :
driver/compmisc.cmi : typing/env.cmi
driver/errors.cmi :
driver/main.cmi :
driver/main_args.cmi :
driver/main.cmi :
driver/optcompile.cmi :
driver/opterrors.cmi :
driver/optmain.cmi :
@ -986,6 +987,8 @@ driver/compmisc.cmx : typing/typemod.cmx utils/misc.cmx \
parsing/asttypes.cmi driver/compmisc.cmi
driver/errors.cmo : parsing/location.cmi driver/errors.cmi
driver/errors.cmx : parsing/location.cmx driver/errors.cmi
driver/main_args.cmo : utils/warnings.cmi driver/main_args.cmi
driver/main_args.cmx : utils/warnings.cmx driver/main_args.cmi
driver/main.cmo : utils/warnings.cmi utils/timings.cmi utils/misc.cmi \
driver/main_args.cmi parsing/location.cmi utils/config.cmi \
driver/compmisc.cmi driver/compile.cmi driver/compenv.cmi \
@ -996,8 +999,6 @@ driver/main.cmx : utils/warnings.cmx utils/timings.cmx utils/misc.cmx \
driver/compmisc.cmx driver/compile.cmx driver/compenv.cmx \
utils/clflags.cmx bytecomp/bytepackager.cmx bytecomp/bytelink.cmx \
bytecomp/bytelibrarian.cmx driver/main.cmi
driver/main_args.cmo : utils/warnings.cmi driver/main_args.cmi
driver/main_args.cmx : utils/warnings.cmx driver/main_args.cmi
driver/optcompile.cmo : utils/warnings.cmi typing/typemod.cmi \
typing/typedtree.cmi typing/typecore.cmi bytecomp/translmod.cmi \
utils/timings.cmi typing/stypes.cmi bytecomp/simplif.cmi \

6
.gitignore vendored
View File

@ -197,8 +197,8 @@
/stdlib/camlheader
/stdlib/target_camlheader
/stdlib/camlheaderd
/stdlib/target_camlheaderd
/stdlib/camlheader[di]
/stdlib/target_camlheader[di]
/stdlib/camlheader_ur
/stdlib/labelled-*
/stdlib/caml
@ -282,6 +282,8 @@
/tools/objinfo_helper
/tools/read_cmt
/tools/read_cmt.opt
/tools/cmpbyt
/tools/stripdebug
/utils/config.ml

View File

@ -63,6 +63,7 @@ Compilers:
- PR#4080, PR#6537, PR#5333: fix stack overflow in the compiler when -pack'ing
a module
that includes a module of the same name (Alain Frisch)
- PR#4231, PR#5461: (interim solution) warning 31 is now fatal by default
- PR#4800: better compilation of tuple assignment (Gabriel Scherer and
Alain Frisch)
- PR#5995: keep -for-pack into account to name exceptions; document -for-pack
@ -154,6 +155,8 @@ Runtime system:
Shinwell, review by Damien Doligez)
- GPR#325: Add v=0x400 flag to OCAMLRUNPARAM to display GC stats on exit (Louis
Gesbert, review by Alain Frisch)
- GPR#297: Several changes to improve the worst-case GC pause time.
(Damien Doligez, with help from Leo White and Francois Bobot)
Standard library:
- PR#5197, GPR#63: Arg: allow flags such as --flag=arg as well as --flag arg
@ -242,6 +245,8 @@ Toplevel and debugger:
(Valentin Gatien-Baron, review by Jérémie Dimino)
- PR#7098: Loss of ppx context in toplevel after an exception
(Alain Frisch, report by whitequark)
- PR#7101: The toplevel does not close in_channel for libraries specified on its command line
(Alain Frisch)
Other libraries:
* Unix library: channels created by Unix.in_channel_of_descr or
@ -485,6 +490,8 @@ Features wishes:
(Hugo Heuzard)
- GPR#308: add experimental support for NetBSD/arm (verified on RaspberryPi)
(Rich Neswold)
- GPR#365: prevent printing just a single type variable on one side
of a type error clash. (Hugo Heuzard)
OCaml 4.02.3 (27 Jul 2015):
---------------------------

View File

@ -106,6 +106,10 @@ The `configure` script accepts the following options:
Compile and install the debug version of the runtimes, useful
for debugging C stubs and other low-level code.
-with-instrumented-runtime::
Compile and install the instrumented version of the runtimes,
useful mainly for fine-tuning the GC. Works only on Linux.
-verbose::
Verbose output of the configuration tests. Use it if the outcome
of configure is not what you were expecting.

View File

@ -71,6 +71,7 @@ COMP=bytecomp/lambda.cmo bytecomp/printlambda.cmo \
bytecomp/translcore.cmo \
bytecomp/translclass.cmo bytecomp/translmod.cmo \
bytecomp/simplif.cmo bytecomp/runtimedef.cmo \
bytecomp/debuginfo.cmo \
driver/pparse.cmo driver/main_args.cmo \
driver/compenv.cmo driver/compmisc.cmo
@ -98,7 +99,7 @@ endif
ASMCOMP=\
$(ARCH_SPECIFIC_ASMCOMP) \
asmcomp/arch.cmo asmcomp/debuginfo.cmo \
asmcomp/arch.cmo \
asmcomp/cmm.cmo asmcomp/printcmm.cmo \
asmcomp/reg.cmo asmcomp/mach.cmo asmcomp/proc.cmo \
asmcomp/clambda.cmo asmcomp/printclambda.cmo asmcomp/compilenv.cmo \

View File

@ -1,4 +1,4 @@
4.03.0+dev11-2015-10-19
4.03.0+dev12-2015-11-20
# The version string is the first line of this file.
# It must be in the format described in stdlib/sys.mli

22
asmcomp/amd64/NOTES.md Normal file
View File

@ -0,0 +1,22 @@
# Supported platforms
Intel and AMD x86 processors in 64-bit mode, a.k.a `x86_64`.
Floating-point architecture: SSE2, supported by all x86_64 processors.
Operating systems: Linux, BSD, MacOS X, MS Windows.
Debian architecture name: `amd64`
# Reference documents
* Instruction set architecture:
any Intel or AMD manual less than 10 years old.
* ELF application binary interface:
_System V Application Binary Interface,
AMD64 Architecture Processor Supplement_
* MacOS X application binary interface:
_OS X ABI Function Call Guide: x86-64 Function Calling Conventions_
* Windows 64 application binary interface:
_x64 Software Conventions_ from MSDN

21
asmcomp/arm/NOTES.md Normal file
View File

@ -0,0 +1,21 @@
# Supported platforms
A great many variants of the ARM 32-bit architecture:
* Architecture versions: v4, v5, v5te, v6, v6t2, v7.
ARMv7 is the standard nowadays.
* Instruction encoding: classic ARM or Thumb or Thumb-2.
* Floating-point: software emulation, VFPv2, VFPv3-d16, VFP-v3.
* ABI: the standard EABI (with floats passed in integer registers)
or the EABI-HF variant (with floats passed in VFP registers).
Debian architecture names: `armel` and `armhf`.
# Reference documents
* Instruction set architecture:
_ARM Architecture Reference Manual, ARMv7-A and ARMv7-R edition_.
Alternatively:
_ARM Architecture Reference Manual, ARMv8_, restricted to the AArch32 subset.
* Application binary interface:
_Procedure Call Standard for the ARM Architecture_

12
asmcomp/arm64/NOTES.md Normal file
View File

@ -0,0 +1,12 @@
# Supported platforms
ARMv8 in 64-bit mode (AArch64).
Debian architecture name: `arm64`.
# Reference documents
* Instruction set architecture:
_ARM Architecture Reference Manual, ARMv8_, restricted to the AArch64 subset.
* Application binary interface:
_Procedure Call Standard for the ARM 64-bit Architecture (AArch64)_

27
asmcomp/i386/NOTES.md Normal file
View File

@ -0,0 +1,27 @@
# Supported platforms
Intel and AMD x86 processors in 32-bit mode.
The baseline is the 80486, also known as `i486`.
(Debian's baseline is now the Pentium 1.)
Floating-point architecture: x87.
(SSE2 not available in Debian's baseline.)
Operating systems: Linux, BSD, MacOS X, MS Windows.
Debian architecture name: `i386`
# Reference documents
* Instruction set architecture:
any Intel or AMD manual of the last 20 years.
* ELF application binary interface:
_System V Application Binary Interface,
Intel386 Architecture Processor Supplement_
* MacOS X application binary interface:
_OS X ABI Function Call Guide: IA-32 Function Calling Conventions_

27
asmcomp/power/NOTES.md Normal file
View File

@ -0,0 +1,27 @@
# Supported platforms
IBM POWER and Freescale (nee Motorola) PowerPC processors, in three flavors:
* 32 bits, ELF ABI: Debian's `powerpc`
* 64 bits big-endian, ELF ABI v1: Debian's `powerpc`
* 64 bits little-endian, ELF ABI v2: Debian's `ppc64el`
No longer supported: AIX and MacOS X.
# Reference documents
* Instruction set architecture:
_PowerPC User Instruction Set Architecture_,
book 1 of _PowerPC Architecture Book_
(http://www.ibm.com/developerworks/systems/library/es-archguide-v2.html).
* ELF ABI 32 bits:
_System V Application Binary Interface, PowerPC Processor Supplement_
* ELF ABI 64 bits version 1:
_64-bit PowerPC ELF Application Binary Interface Supplement_
(http://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi.html)
* ELF ABI 64 bits version 2:
_Power Architecture 64-bit ELF V2 ABI Specification,
OpenPOWER ABI for Linux Supplement_
(http://openpowerfoundation.org/technical/technical-resources/technical-specifications/)
* _The PowerPC Compiler Writer's Guide_, Warthman Associates, 1996.
(PDF available from various sources on the Web.)

19
asmcomp/s390x/NOTES.md Normal file
View File

@ -0,0 +1,19 @@
# Supported platforms
IBM z Systems version 10 and up, in 64-bit flat addressing mode,
running Linux (Debian architecture: `s390x`).
# Reference documents
* Instruction set architecture:
_z/Architecture Principles of Operation_,
SA22-7832-07, eight edition (Feb 2009).
This is the version that corresponds to z10.
Newer versions of this manual include additional instructions
that are not in z10.
* ELF ABI:
_zSeries ELF Application Binary Interface Supplement_
(http://refspecs.linuxfoundation.org/ELF/zSeries/index.html)

21
asmcomp/sparc/NOTES.md Normal file
View File

@ -0,0 +1,21 @@
# Supported platforms
SPARC v8 and up, in 32-bit mode.
Operating systems: Solaris, Linux
(abandoned since major Linux distributions no longer support SPARC).
Status of this port: nearly abandoned
(no hardware or virtual machine available for testing).
# Reference documents
* Instruction set architecture:
_The SPARC Architecture Manual_ version 8.
* ELF application binary interface:
_System V Application Binary Interface,
SPARC Processor Supplement_

File diff suppressed because it is too large Load Diff

View File

@ -18,12 +18,13 @@ FLAGS=-I../byterun -DCAML_NAME_SPACE -DNATIVE_CODE \
-DTARGET_$(ARCH) -DMODEL_$(MODEL) -DSYS_$(SYSTEM) $(IFLEXDIR)
CFLAGS=$(FLAGS) $(NATIVECCCOMPOPTS)
DFLAGS=$(FLAGS) -g -DDEBUG $(NATIVECCCOMPOPTS)
IFLAGS=$(FLAGS) -DCAML_INSTR
PFLAGS=$(FLAGS) -pg -DPROFILING $(NATIVECCPROFOPTS) $(NATIVECCCOMPOPTS)
PICFLAGS=$(FLAGS) $(SHAREDCCCOMPOPTS) $(NATIVECCCOMPOPTS)
COBJS=startup_aux.o startup.o \
main.o fail.o roots.o globroots.o signals.o signals_asm.o \
misc.o freelist.o major_gc.o minor_gc.o memory.o alloc.o compare.o ints.o \
freelist.o misc.o major_gc.o minor_gc.o memory.o alloc.o compare.o ints.o \
floats.o str.o array.o io.o extern.o intern.o hash.o sys.o parsing.o \
gc_ctrl.o terminfo.o md5.o obj.o lexing.o printexc.o callback.o weak.o \
compact.o finalise.o custom.o $(UNIX_OR_WIN32).o backtrace_prim.o \
@ -34,11 +35,16 @@ ASMOBJS=$(ARCH).o
OBJS=$(COBJS) $(ASMOBJS)
DOBJS=$(COBJS:.o=.d.o) $(ASMOBJS)
IOBJS=$(COBJS:.o=.i.o) $(ASMOBJS)
POBJS=$(COBJS:.o=.p.o) $(ASMOBJS:.o=.p.o)
PICOBJS=$(COBJS:.o=.pic.o) $(ASMOBJS:.o=.pic.o)
all: libasmrun.a all-$(RUNTIMED) all-$(PROFILING) all-$(SHARED)
ifeq "$(RUNTIMEI)" "true"
all: libasmruni.a
endif
libasmrun.a: $(OBJS)
rm -f libasmrun.a
$(ARCMD) rc libasmrun.a $(OBJS)
@ -55,6 +61,11 @@ libasmrund.a: $(DOBJS)
$(ARCMD) rc libasmrund.a $(DOBJS)
$(RANLIB) libasmrund.a
libasmruni.a: $(IOBJS)
rm -f $@
$(ARCMD) rc $@ $^
$(RANLIB) $@
all-noprof:
all-prof: libasmrunp.a
@ -78,40 +89,39 @@ libasmrun_shared.so: $(PICOBJS)
INSTALL_LIBDIR=$(DESTDIR)$(LIBDIR)
install: install-default install-$(RUNTIMED) install-$(PROFILING) \
install-$(SHARED)
install-default:
install::
cp libasmrun.a $(INSTALL_LIBDIR)/libasmrun.a
cd $(INSTALL_LIBDIR); $(RANLIB) libasmrun.a
.PHONY: install-default
install-noruntimed:
.PHONY: install-noruntimed
install-runtimed:
ifeq "$(RUNTIMED)" "runtimed"
install::
cp libasmrund.a $(INSTALL_LIBDIR)/libasmrund.a
cd $(INSTALL_LIBDIR); $(RANLIB) libasmrund.a
.PHONY: install-runtimed
endif
install-noprof:
rm -f $(INSTALL_LIBDIR)/libasmrunp.a
ln -s libasmrun.a $(INSTALL_LIBDIR)/libasmrunp.a
.PHONY: install-noprof
ifeq "$(RUNTIMEI)" "true"
install::
cp libasmruni.a $(INSTALL_LIBDIR)/libasmruni.a
cd $(INSTALL_LIBDIR); $(RANLIB) libasmruni.a
endif
install-prof:
ifeq "$(PROFILING)" "prof"
install::
cp libasmrunp.a $(INSTALL_LIBDIR)/libasmrunp.a
cd $(INSTALL_LIBDIR); $(RANLIB) libasmrunp.a
.PHONY: install-prof
else
install::
rm -f $(INSTALL_LIBDIR)/libasmrunp.a
ln -s libasmrun.a $(INSTALL_LIBDIR)/libasmrunp.a
endif
install-noshared:
.PHONY: install-noshared
install-shared:
ifeq "$(SHARED)" "shared"
install::
cp libasmrun_pic.a $(INSTALL_LIBDIR)/libasmrun_pic.a
cd $(INSTALL_LIBDIR); $(RANLIB) libasmrunp.a
cp libasmrun_shared.so $(INSTALL_LIBDIR)/libasmrun_shared.so
.PHONY: install-prof
endif
main.c: ../byterun/main.c
ln -s ../byterun/main.c main.c
@ -197,6 +207,18 @@ LINKEDFILES=misc.c freelist.c major_gc.c minor_gc.c memory.c alloc.c array.c \
clean::
rm -f $(LINKEDFILES)
%.d.o: %.c
$(CC) -c $(DFLAGS) -o $@ $<
%.i.o : %.c
$(CC) -c $(IFLAGS) -o $@ $<
%.p.o: %.c
$(CC) -c $(PFLAGS) -o $@ $<
%.pic.o: %.c
$(CC) -c $(PICFLAGS) -o $@ $<
%.o: %.S
$(ASPP) -DSYS_$(SYSTEM) -DMODEL_$(MODEL) -o $@ $< || \
{ echo "If your assembler produced syntax errors, it is probably";\
@ -210,15 +232,6 @@ clean::
%.pic.o: %.S
$(ASPP) -DSYS_$(SYSTEM) -DMODEL_$(MODEL) $(SHAREDCCCOMPOPTS) -o $@ $<
%.d.o: %.c
$(CC) -c $(DFLAGS) -o $@ $<
%.p.o: %.c
$(CC) -c $(PFLAGS) -o $@ $<
%.pic.o: %.c
$(CC) -c $(PICFLAGS) -o $@ $<
%.o: %.s
$(ASPP) -DSYS_$(SYSTEM) -o $@ $<
@ -233,7 +246,8 @@ clean::
depend: $(COBJS:.o=.c) ${LINKEDFILES}
$(CC) -MM $(FLAGS) *.c > .depend
$(CC) -MM $(FLAGS) -DPROFILING *.c | sed -e 's/\.o/.p.o/' >> .depend
$(CC) -MM $(FLAGS) -DDEBUG *.c | sed -e 's/\.o/.d.o/' >> .depend
$(CC) -MM $(FLAGS) *.c | sed -e 's/\.o/.p.o/' >> .depend
$(CC) -MM $(FLAGS) -DCAML_INSTR *.c | sed -e 's/\.o/.i.o/' >> .depend
include .depend

View File

@ -518,3 +518,6 @@ caml_system__frametable:
.align 2
.type caml_system__frametable, %object
.size caml_system__frametable, .-caml_system__frametable
/* Mark stack as non-executable */
.section .note.GNU-stack,"",%progbits

View File

@ -553,3 +553,6 @@ caml_system__frametable:
.align 3
.type caml_system__frametable, %object
.size caml_system__frametable, .-caml_system__frametable
/* Mark stack as non-executable */
.section .note.GNU-stack,"",%progbits

View File

@ -690,3 +690,6 @@ TOCENTRY(caml_young_limit)
TOCENTRY(caml_young_ptr)
#endif
/* Mark stack as non-executable */
.section .note.GNU-stack,"",%progbits

View File

@ -335,27 +335,78 @@ void caml_oldify_local_roots (void)
if (caml_scan_roots_hook != NULL) (*caml_scan_roots_hook)(&caml_oldify_one);
}
/* Call [darken] on all roots */
uintnat caml_incremental_roots_count = 0;
void caml_darken_all_roots (void)
/* Call [caml_darken] on all roots, incrementally:
[caml_darken_all_roots_start] does the non-incremental part and
sets things up for [caml_darken_all_roots_slice].
*/
void caml_darken_all_roots_start (void)
{
caml_do_roots (caml_darken);
caml_do_roots (caml_darken, 0);
}
void caml_do_roots (scanning_action f)
/* Call [caml_darken] on at most [work] global roots. Return the
amount of work not done, if any. If this is strictly positive,
the darkening is done.
*/
intnat caml_darken_all_roots_slice (intnat work)
{
static int i, j;
static value *glob;
static int do_resume = 0;
static mlsize_t roots_count = 0;
intnat remaining_work = work;
CAML_INSTR_SETUP (tmr, "");
/* If the loop was started in a previous call, resume it. */
if (do_resume) goto resume;
/* This is the same loop as in [caml_do_roots], but we make it
suspend itself when [work] reaches 0. */
for (i = 0; caml_globals[i] != 0; i++) {
for(glob = caml_globals[i]; *glob != 0; glob++) {
for (j = 0; j < Wosize_val(*glob); j++){
caml_darken (Field (*glob, j), &Field (*glob, j));
-- remaining_work;
if (remaining_work == 0){
roots_count += work;
do_resume = 1;
goto suspend;
}
resume: ;
}
}
}
/* The loop finished normally, so all roots are now darkened. */
caml_incremental_roots_count = roots_count + work - remaining_work;
/* Prepare for the next run. */
do_resume = 0;
roots_count = 0;
suspend:
/* Do this in both cases. */
CAML_INSTR_TIME (tmr, "major/mark/global_roots_slice");
return remaining_work;
}
void caml_do_roots (scanning_action f, int do_globals)
{
int i, j;
value * glob;
link *lnk;
CAML_INSTR_SETUP (tmr, "major_roots");
/* The global roots */
for (i = 0; caml_globals[i] != 0; i++) {
for(glob = caml_globals[i]; *glob != 0; glob++) {
for (j = 0; j < Wosize_val(*glob); j++)
f (Field (*glob, j), &Field (*glob, j));
if (do_globals){
/* The global roots */
for (i = 0; caml_globals[i] != 0; i++) {
for(glob = caml_globals[i]; *glob != 0; glob++) {
for (j = 0; j < Wosize_val(*glob); j++)
f (Field (*glob, j), &Field (*glob, j));
}
}
}
/* Dynamic global roots */
iter_list(caml_dyn_globals, lnk) {
for(glob = (value *) lnk->data; *glob != 0; glob++) {
@ -364,16 +415,20 @@ void caml_do_roots (scanning_action f)
}
}
}
CAML_INSTR_TIME (tmr, "major_roots/dynamic_global");
/* The stack and local roots */
caml_do_local_roots(f, caml_bottom_of_stack, caml_last_return_address,
caml_gc_regs, caml_local_roots);
CAML_INSTR_TIME (tmr, "major_roots/local");
/* Global C roots */
caml_scan_global_roots(f);
CAML_INSTR_TIME (tmr, "major_roots/C");
/* Finalised values */
caml_final_do_strong_roots (f);
CAML_INSTR_TIME (tmr, "major_roots/finalised");
/* Hook */
if (caml_scan_roots_hook != NULL) (*caml_scan_roots_hook)(f);
CAML_INSTR_TIME (tmr, "major_roots/hook");
}
void caml_do_local_roots(scanning_action f, char * bottom_of_stack,

View File

@ -351,3 +351,6 @@ caml_system__frametable:
.short -1 /* negative size count => use callback link */
.short 0 /* no roots here */
.align 8
/* Mark stack as non-executable */
.section .note.GNU-stack,"",%progbits

View File

@ -67,9 +67,11 @@ extern char caml_system__code_begin, caml_system__code_end;
void caml_garbage_collection(void)
{
caml_young_limit = caml_young_start;
if (caml_young_ptr < caml_young_start || caml_force_major_slice) {
caml_minor_collection();
CAMLassert (caml_young_ptr >= caml_young_alloc_start);
caml_young_limit = caml_young_trigger;
if (caml_requested_major_slice || caml_requested_minor_gc ||
caml_young_ptr - caml_young_trigger < Max_young_whsize){
caml_gc_dispatch ();
}
caml_process_pending_signals();
}

View File

@ -107,14 +107,17 @@ void caml_main(char **argv)
caml_install_invalid_parameter_handler();
#endif
caml_init_custom_operations();
#ifdef DEBUG
caml_verb_gc = 63;
#endif
caml_top_of_stack = &tos;
#ifdef DEBUG
caml_verb_gc = 0x3F;
#endif
caml_parse_ocamlrunparam();
#ifdef DEBUG
caml_gc_message (-1, "### OCaml runtime: debug mode ###\n", 0);
#endif
caml_init_gc (caml_init_minor_heap_wsz, caml_init_heap_wsz,
caml_init_heap_chunk_sz, caml_init_percent_free,
caml_init_max_percent_free);
caml_init_max_percent_free, caml_init_major_window);
init_static();
caml_init_signals();
caml_init_backtrace();

1
asmrun/startup_aux.c Symbolic link
View File

@ -0,0 +1 @@
../byterun/startup_aux.c

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -176,6 +176,7 @@ type shared_code = (int * int) list
type function_attribute = {
inline : inline_attribute;
is_a_functor: bool;
}
type lambda =
@ -237,6 +238,7 @@ let lambda_unit = Lconst const_unit
let default_function_attribute = {
inline = Default_inline;
is_a_functor = false;
}
(* Build sharing keys *)

View File

@ -185,6 +185,7 @@ type shared_code = (int * int) list (* stack size -> code label *)
type function_attribute = {
inline : inline_attribute;
is_a_functor: bool;
}
type lambda =

View File

@ -246,7 +246,9 @@ let primitive ppf = function
| Pbbswap(bi) -> print_boxed_integer "bswap" ppf bi
| Pint_as_pointer -> fprintf ppf "int_as_pointer"
let function_attribute ppf { inline } =
let function_attribute ppf { inline; is_a_functor } =
if is_a_functor then
fprintf ppf "is_a_functor@ ";
match inline with
| Default_inline -> ()
| Always_inline -> fprintf ppf "always_inline@ "

View File

@ -73,7 +73,7 @@ let add_inline_attribute expr loc attributes =
Location.prerr_warning loc
(Warnings.Duplicated_attribute "inline")
end;
Lfunction { funct with attr = { inline = inline_attribute } }
Lfunction { funct with attr = { attr with inline = inline_attribute } }
| expr, (Always_inline | Never_inline) ->
Location.prerr_warning loc
(Warnings.Misplaced_attribute "inline");
@ -84,12 +84,18 @@ let add_inline_attribute expr loc attributes =
used to ensure that this expression is not misplaced: If it
appears on any expression, it is an error, otherwise it would
have been removed by this function *)
let get_inlined_attribute e =
let get_and_remove_inlined_attribute e =
let attribute_value, exp_attributes =
make_get_inline_attribute is_inlined_attribute e.exp_attributes
in
attribute_value, { e with exp_attributes }
let get_and_remove_inlined_attribute_on_module e =
let attribute_value, mod_attributes =
make_get_inline_attribute is_inlined_attribute e.mod_attributes
in
attribute_value, { e with mod_attributes }
(* It also remove the attribute from the expression, like
get_inlined_attribute *)
let get_tailcall_attribute e =
@ -125,3 +131,18 @@ let check_attribute e ({ txt; loc }, _) =
Location.prerr_warning loc
(Warnings.Misplaced_attribute txt)
| _ -> ()
let check_attribute_on_module e ({ txt; loc }, _) =
match txt with
| "inline" | "ocaml.inline" -> begin
match e.mod_desc with
| Tmod_functor _ -> ()
| _ ->
Location.prerr_warning loc
(Warnings.Misplaced_attribute txt)
end
| "inlined" | "ocaml.inlined" ->
(* Removed by the Texp_apply cases *)
Location.prerr_warning loc
(Warnings.Misplaced_attribute txt)
| _ -> ()

View File

@ -15,20 +15,29 @@ val check_attribute
-> string Location.loc * _
-> unit
val check_attribute_on_module
: Typedtree.module_expr
-> string Location.loc * _
-> unit
val add_inline_attribute
: Lambda.lambda
-> Location.t
-> Parsetree.attribute list
-> Parsetree.attributes
-> Lambda.lambda
val get_inline_attribute
: (string Location.loc * Parsetree.payload) list
: Parsetree.attributes
-> Lambda.inline_attribute
val get_inlined_attribute
val get_and_remove_inlined_attribute
: Typedtree.expression
-> Lambda.inline_attribute * Typedtree.expression
val get_and_remove_inlined_attribute_on_module
: Typedtree.module_expr
-> Lambda.inline_attribute * Typedtree.module_expr
val get_tailcall_attribute
: Typedtree.expression
-> bool * Typedtree.expression

View File

@ -691,6 +691,7 @@ and transl_exp0 e =
transl_function e.exp_loc !Clflags.native_code repr partial pl)
in
let attr = {
default_function_attribute with
inline = Translattribute.get_inline_attribute e.exp_attributes;
}
in
@ -708,7 +709,7 @@ and transl_exp0 e =
Translattribute.get_tailcall_attribute funct
in
let inlined, funct =
Translattribute.get_inlined_attribute funct
Translattribute.get_and_remove_inlined_attribute funct
in
let e = { e with exp_desc = Texp_apply(funct, oargs) } in
event_after e (transl_apply ~should_be_tailcall ~inlined
@ -764,7 +765,7 @@ and transl_exp0 e =
Translattribute.get_tailcall_attribute funct
in
let inlined, funct =
Translattribute.get_inlined_attribute funct
Translattribute.get_and_remove_inlined_attribute funct
in
let e = { e with exp_desc = Texp_apply(funct, oargs) } in
event_after e (transl_apply ~should_be_tailcall ~inlined

View File

@ -91,7 +91,8 @@ let rec apply_coercion strict restr arg =
let param = Ident.create "funarg" in
name_lambda strict arg (fun id ->
Lfunction{kind = Curried; params = [param];
attr = default_function_attribute;
attr = { default_function_attribute with
is_a_functor = true };
body = apply_coercion
Strict cc_res
(Lapply{ap_should_be_tailcall=false;
@ -348,6 +349,8 @@ let transl_class_bindings cl_list =
(* Compile a module expression *)
let rec transl_module cc rootpath mexp =
List.iter (Translattribute.check_attribute_on_module mexp)
mexp.mod_attributes;
match mexp.mod_type with
Mty_alias _ -> apply_coercion Alias cc lambda_unit
| _ ->
@ -359,16 +362,21 @@ let rec transl_module cc rootpath mexp =
transl_struct [] cc rootpath str
| Tmod_functor( param, _, mty, body) ->
let bodypath = functor_path rootpath param in
let inline_attribute =
Translattribute.get_inline_attribute mexp.mod_attributes
in
oo_wrap mexp.mod_env true
(function
| Tcoerce_none ->
Lfunction{kind = Curried; params = [param];
attr = default_function_attribute;
attr = { inline = inline_attribute;
is_a_functor = true };
body = transl_module Tcoerce_none bodypath body}
| Tcoerce_functor(ccarg, ccres) ->
let param' = Ident.create "funarg" in
Lfunction{kind = Curried; params = [param'];
attr = default_function_attribute;
attr = { inline = inline_attribute;
is_a_functor = true };
body = Llet(Alias, param,
apply_coercion Alias ccarg (Lvar param'),
transl_module ccres bodypath body)}
@ -376,13 +384,16 @@ let rec transl_module cc rootpath mexp =
fatal_error "Translmod.transl_module")
cc
| Tmod_apply(funct, arg, ccarg) ->
let inlined_attribute, funct =
Translattribute.get_and_remove_inlined_attribute_on_module funct
in
oo_wrap mexp.mod_env true
(apply_coercion Strict cc)
(Lapply{ap_should_be_tailcall=false;
ap_loc=mexp.mod_loc;
ap_func=transl_module Tcoerce_none None funct;
ap_args=[transl_module ccarg None arg];
ap_inlined=Default_inline})
ap_inlined=inlined_attribute})
| Tmod_constraint(arg, mty, _, ccarg) ->
transl_module (compose_coercions cc ccarg) rootpath arg
| Tmod_unpack(arg, _) ->
@ -448,7 +459,9 @@ and transl_structure fields cc rootpath = function
| Tstr_module mb ->
let id = mb.mb_id in
Llet(pure_module mb.mb_expr, id,
transl_module Tcoerce_none (field_path rootpath id) mb.mb_expr,
Translattribute.add_inline_attribute
(transl_module Tcoerce_none (field_path rootpath id) mb.mb_expr)
mb.mb_loc mb.mb_attributes,
transl_structure (id :: fields) cc rootpath rem)
| Tstr_recmodule bindings ->
let ext_fields =
@ -671,7 +684,11 @@ let transl_store_structure glob map prims str =
let lam = transl_extension_constructor item.str_env path ext in
Lsequence(Llet(Strict, id, subst_lambda subst lam, store_ident id),
transl_store rootpath (add_ident false id subst) rem)
| Tstr_module{mb_id=id; mb_expr={mod_desc = Tmod_structure str}} ->
| Tstr_module{mb_id=id;
mb_expr={mod_desc = Tmod_structure str} as mexp;
mb_attributes} ->
List.iter (Translattribute.check_attribute_on_module mexp)
mb_attributes;
let lam = transl_store (field_path rootpath id) subst str.str_items in
(* Careful: see next case *)
let subst = !transl_store_subst in
@ -684,8 +701,17 @@ let transl_store_structure glob map prims str =
Lsequence(store_ident id,
transl_store rootpath (add_ident true id subst)
rem)))
| Tstr_module{mb_id=id; mb_expr={mod_desc = Tmod_constraint ({mod_desc = Tmod_structure str}, _, _, (Tcoerce_structure (map, _) as _cc))}} ->
| Tstr_module{
mb_id=id;
mb_expr= {
mod_desc = Tmod_constraint (
{mod_desc = Tmod_structure str} as mexp, _, _,
(Tcoerce_structure (map, _) as _cc))};
mb_attributes
} ->
(* Format.printf "coerc id %s: %a@." (Ident.unique_name id) Includemod.print_coercion cc; *)
List.iter (Translattribute.check_attribute_on_module mexp)
mb_attributes;
let lam = transl_store (field_path rootpath id) subst str.str_items in
(* Careful: see next case *)
let subst = !transl_store_subst in
@ -704,8 +730,12 @@ let transl_store_structure glob map prims str =
Lsequence(store_ident id,
transl_store rootpath (add_ident true id subst)
rem)))
| Tstr_module{mb_id=id; mb_expr=modl} ->
let lam = transl_module Tcoerce_none (field_path rootpath id) modl in
| Tstr_module{mb_id=id; mb_expr=modl; mb_loc; mb_attributes} ->
let lam =
Translattribute.add_inline_attribute
(transl_module Tcoerce_none (field_path rootpath id) modl)
mb_loc mb_attributes
in
(* Careful: the module value stored in the global may be different
from the local module value, in case a coercion is applied.
If so, keep using the local module value (id) in the remainder of

File diff suppressed because it is too large Load Diff

View File

@ -15,9 +15,11 @@ include Makefile.common
CFLAGS=-DCAML_NAME_SPACE $(BYTECCCOMPOPTS) $(IFLEXDIR)
DFLAGS=-DCAML_NAME_SPACE -g -DDEBUG $(BYTECCCOMPOPTS) $(IFLEXDIR)
IFLAGS=$(CFLAGS) -DCAML_INSTR
OBJS=$(COMMONOBJS) $(UNIX_OR_WIN32).o main.o
DOBJS=$(OBJS:.o=.d.o) instrtrace.d.o
IOBJS=$(OBJS:.o=.i.o)
PICOBJS=$(OBJS:.o=.pic.o)
all:: all-$(SHARED)
@ -30,6 +32,9 @@ ocamlrund$(EXE): libcamlrund.a prims.o
$(MKEXE) $(MKEXEDEBUGFLAG) $(BYTECCLINKOPTS) -o ocamlrund$(EXE) \
prims.o libcamlrund.a $(BYTECCLIBS)
ocamlruni$(EXE): prims.o libcamlruni.a
$(MKEXE) $(BYTECCLINKOPTS) -o $@ $^ $(BYTECCLIBS)
libcamlrun.a: $(OBJS)
$(ARCMD) rc libcamlrun.a $(OBJS)
$(RANLIB) libcamlrun.a
@ -38,6 +43,10 @@ libcamlrund.a: $(DOBJS)
$(ARCMD) rc libcamlrund.a $(DOBJS)
$(RANLIB) libcamlrund.a
libcamlruni.a: $(IOBJS)
$(ARCMD) rc $@ $^
$(RANLIB) $@
all-noshared:
.PHONY: all-noshared
@ -68,12 +77,18 @@ clean::
%.d.o: %.c
$(CC) -c $(DFLAGS) $< -o $@
%.i.o: %.c
$(CC) -c $(IFLAGS) -o $@ $<
%.pic.o: %.c
$(CC) -c $(CFLAGS) $(SHAREDCCCOMPOPTS) $< -o $@
depend : prims.c caml/opnames.h caml/jumptbl.h caml/version.h
-$(CC) -MM $(BYTECCCOMPOPTS) *.c > .depend
-$(CC) -MM $(BYTECCCOMPOPTS) -DDEBUG *.c | sed -e 's/\.o/.d.o/' >> .depend
-$(CC) -MM $(BYTECCCOMPOPTS) -DDEBUG *.c | sed -e 's/\.o/.d.o/' \
>> .depend
-$(CC) -MM $(BYTECCCOMPOPTS) -DCAML_INSTR *.c | sed -e 's/\.o/.i.o/' \
>> .depend
-$(CC) -MM $(BYTECCCOMPOPTS) *.c | sed -e 's/\.o/.pic.o/' >> .depend
.PHONY: depend

View File

@ -48,6 +48,10 @@ all-noruntimed:
all-runtimed: ocamlrund$(EXE) libcamlrund.$(A)
.PHONY: all-runtimed
ifeq "$(RUNTIMEI)" "true"
all:: ocamlruni$(EXE) libcamlruni.$(A)
endif
ld.conf: ../config/Makefile
echo "$(STUBLIBDIR)" > ld.conf
echo "$(LIBDIR)" >> ld.conf
@ -84,6 +88,12 @@ install-runtimed:
cp libcamlrund.$(A) $(INSTALL_LIBDIR)/libcamlrund.$(A)
.PHONY: install-runtimed
ifeq "$(RUNTIMEI)" "true"
install::
cp ocamlruni$(EXE) $(INSTALL_BINDIR)/ocamlruni$(EXE)
cp libcamlruni.$(A) $(INSTALL_LIBDIR)/libcamlruni.$(A)
endif
# If primitives contain duplicated lines (e.g. because the code is defined
# like
# #ifdef X

View File

@ -18,6 +18,7 @@
#include "caml/memory.h"
#include "caml/misc.h"
#include "caml/mlvalues.h"
#include "caml/signals.h"
/* returns number of elements (either fields or floats) */
CAMLexport mlsize_t caml_array_length(value array)
@ -181,12 +182,16 @@ CAMLprim value caml_make_vect(value len, value init)
}
} else {
if (size > Max_wosize) caml_invalid_argument("Array.make");
if (size < Max_young_wosize) {
if (size <= Max_young_wosize) {
res = caml_alloc_small(size, 0);
for (i = 0; i < size; i++) Field(res, i) = init;
}
else if (Is_block(init) && Is_young(init)) {
caml_minor_collection();
/* We don't want to create so many major-to-minor references,
so [init] is moved to the major heap by doing a minor GC. */
CAML_INSTR_INT ("force_minor/make_vect@", 1);
caml_request_minor_gc ();
caml_gc_dispatch ();
res = caml_alloc_shr(size, 0);
for (i = 0; i < size; i++) Field(res, i) = init;
res = caml_check_urgent_gc (res);
@ -324,7 +329,7 @@ static value caml_array_gather(intnat num_arrays,
/* Array of values, too big. */
caml_invalid_argument("Array.concat");
}
else if (size < Max_young_wosize) {
else if (size <= Max_young_wosize) {
/* Array of values, small enough to fit in young generation.
We can use memcpy directly. */
res = caml_alloc_small(size, 0);

View File

@ -16,6 +16,7 @@
#ifndef CAML_ADDRESS_CLASS_H
#define CAML_ADDRESS_CLASS_H
#include "config.h"
#include "misc.h"
#include "mlvalues.h"

View File

@ -112,6 +112,15 @@ typedef uint64_t uintnat;
#define ARCH_FLOAT_ENDIANNESS 0x01234567
#endif
/* We use static inline functions in some cases instead of duplicating
code but the MSVC compiler has a slightly different syntax. */
#ifdef _MSC_VER
#define inline _inline
#endif
/* We use threaded code interpretation if the compiler provides labels
as first-class values (GCC 2.x). */
@ -143,10 +152,11 @@ typedef uint64_t uintnat;
/* Maximum size of a block allocated in the young generation (words). */
/* Must be > 4 */
#define Max_young_wosize 256
#define Max_young_whsize (Whsize_wosize (Max_young_wosize))
/* Minimum size of the minor zone (words).
This must be at least [Max_young_wosize + 1]. */
This must be at least [2 * Max_young_whsize]. */
#define Minor_heap_min 4096
/* Maximum size of the minor zone (words).
@ -185,5 +195,12 @@ typedef uint64_t uintnat;
*/
#define Max_percent_free_def 500
/* Default setting for the major GC slice smoothing window: 1
(i.e. no smoothing)
*/
#define Major_window_def 1
/* Maximum size of the major GC slice smoothing window. */
#define Max_major_window 50
#endif /* CAML_CONFIG_H */

View File

@ -31,8 +31,16 @@ extern intnat
uintnat caml_normalize_heap_increment (uintnat);
void caml_init_gc (uintnat, uintnat, uintnat,
uintnat, uintnat);
/*
minor_size: cf. minor_heap_size in gc.mli
major_size: Size in words of the initial major heap
major_incr: cf. major_heap_increment in gc.mli
percent_fr: cf. space_overhead in gc.mli
percent_m : cf. max_overhead in gc.mli
window : cf. window_size in gc.mli
*/
void caml_init_gc (uintnat minor_size, uintnat major_size, uintnat major_incr,
uintnat percent_fr, uintnat percent_m, uintnat window);
#ifdef DEBUG

View File

@ -20,7 +20,6 @@
#include "mlvalues.h"
#include "misc.h"
extern int caml_trace_flag;
extern intnat caml_icount;
void caml_stop_here (void);
void caml_disasm_instr (code_t pc);

View File

@ -40,21 +40,29 @@ extern uintnat caml_fl_wsz_at_phase_change;
#define Phase_mark 0
#define Phase_sweep 1
#define Phase_idle 2
#define Subphase_main 10
#define Subphase_weak1 11
#define Subphase_weak2 12
#define Subphase_final 13
#define Subphase_roots 10
#define Subphase_main 11
#define Subphase_weak1 12
#define Subphase_weak2 13
#define Subphase_final 14
CAMLextern char *caml_heap_start;
extern uintnat total_heap_size;
extern char *caml_gc_sweep_hp;
extern int caml_major_window;
double caml_major_ring[Max_major_window];
int caml_major_ring_index;
double caml_major_work_credit;
extern double caml_gc_clock;
void caml_init_major_heap (asize_t); /* size in bytes */
asize_t caml_round_heap_chunk_wsz (asize_t);
asize_t caml_clip_heap_chunk_wsz (asize_t wsz);
void caml_darken (value, value *);
intnat caml_major_collection_slice (intnat);
void caml_major_collection_slice (intnat);
void major_collection (void);
void caml_finish_major_cycle (void);
void caml_set_major_window (int);
#endif /* CAML_MAJOR_GC_H */

View File

@ -44,15 +44,32 @@ CAMLextern value caml_check_urgent_gc (value);
CAMLextern void * caml_stat_alloc (asize_t); /* Size in bytes. */
CAMLextern void caml_stat_free (void *);
CAMLextern void * caml_stat_resize (void *, asize_t); /* Size in bytes. */
char *caml_alloc_for_heap (asize_t request); /* Size in bytes. */
void caml_free_for_heap (char *mem);
int caml_add_to_heap (char *mem);
color_t caml_allocation_color (void *hp);
CAMLextern int caml_init_alloc_for_heap (void);
CAMLextern char *caml_alloc_for_heap (asize_t request); /* Size in bytes. */
CAMLextern void caml_free_for_heap (char *mem);
CAMLextern int caml_add_to_heap (char *mem);
CAMLextern color_t caml_allocation_color (void *hp);
CAMLextern int caml_huge_fallback_count;
/* void caml_shrink_heap (char *); Only used in compact.c */
/* <private> */
extern uintnat caml_use_huge_pages;
#ifdef HAS_HUGE_PAGES
#include <sys/mman.h>
#define Heap_page_size HUGE_PAGE_SIZE
#define Round_mmap_size(x) \
(((x) + (Heap_page_size - 1)) & ~ (Heap_page_size - 1))
#endif
int caml_page_table_add(int kind, void * start, void * end);
int caml_page_table_remove(int kind, void * start, void * end);
int caml_page_table_initialize(mlsize_t bytesize);
#ifdef DEBUG
#define DEBUG_clear(result, wosize) do{ \
uintnat caml__DEBUG_i; \
@ -68,10 +85,11 @@ color_t caml_allocation_color (void *hp);
CAMLassert ((tag_t) (tag) < 256); \
CAMLassert ((wosize) <= Max_young_wosize); \
caml_young_ptr -= Whsize_wosize (wosize); \
if (caml_young_ptr < caml_young_start){ \
if (caml_young_ptr < caml_young_trigger){ \
caml_young_ptr += Whsize_wosize (wosize); \
CAML_INSTR_INT ("force_minor/alloc_small@", 1); \
Setup_for_gc; \
caml_minor_collection (); \
caml_gc_dispatch (); \
Restore_after_gc; \
caml_young_ptr -= Whsize_wosize (wosize); \
} \

View File

@ -16,9 +16,12 @@
#include "address_class.h"
#include "config.h"
CAMLextern value *caml_young_start, *caml_young_ptr;
CAMLextern value *caml_young_end, *caml_young_limit;
CAMLextern value *caml_young_start, *caml_young_end;
CAMLextern value *caml_young_alloc_start, *caml_young_alloc_end;
CAMLextern value *caml_young_ptr, *caml_young_limit;
CAMLextern value *caml_young_trigger;
extern asize_t caml_minor_heap_wsz;
extern int caml_in_minor_collection;
@ -36,7 +39,7 @@ CAMLextern struct caml_ref_table caml_ref_table, caml_weak_ref_table,
extern void caml_set_minor_heap_size (asize_t); /* size in bytes */
extern void caml_empty_minor_heap (void);
CAMLextern void caml_minor_collection (void);
CAMLextern void caml_gc_dispatch (void);
CAMLextern void garbage_collection (void); /* def in asmrun/signals_asm.c */
extern void caml_realloc_ref_table (struct caml_ref_table *);
extern void caml_alloc_table (struct caml_ref_table *, asize_t, asize_t);
@ -50,4 +53,13 @@ extern void caml_oldify_mopup (void);
} \
}while(0)
static inline void add_to_ref_table (struct caml_ref_table *tbl, value *p)
{
if (tbl->ptr >= tbl->limit){
CAMLassert (tbl->ptr == tbl->limit);
caml_realloc_ref_table (tbl);
}
*tbl->ptr++ = p;
}
#endif /* CAML_MINOR_GC_H */

View File

@ -201,6 +201,104 @@ extern int caml_snprintf(char * buf, size_t size, const char * format, ...);
#define snprintf caml_snprintf
#endif
#ifdef CAML_INSTR
/* Timers and counters for GC latency profiling (Linux-only) */
#include <time.h>
#include <stdio.h>
extern intnat caml_stat_minor_collections;
extern intnat CAML_INSTR_STARTTIME, CAML_INSTR_STOPTIME;
struct CAML_INSTR_BLOCK {
struct timespec ts[10];
char *tag[10];
int index;
struct CAML_INSTR_BLOCK *next;
};
extern struct CAML_INSTR_BLOCK *CAML_INSTR_LOG;
/* Declare a timer/counter name. [t] must be a new variable name. */
#define CAML_INSTR_DECLARE(t) \
struct CAML_INSTR_BLOCK *t = NULL
/* Allocate the data block for a given name.
[t] must have been declared with [CAML_INSTR_DECLARE]. */
#define CAML_INSTR_ALLOC(t) do{ \
if (caml_stat_minor_collections >= CAML_INSTR_STARTTIME \
&& caml_stat_minor_collections < CAML_INSTR_STOPTIME){ \
t = malloc (sizeof (struct CAML_INSTR_BLOCK)); \
t->index = 0; \
t->tag[0] = ""; \
t->next = CAML_INSTR_LOG; \
CAML_INSTR_LOG = t; \
} \
}while(0)
/* Allocate the data block and start the timer.
[t] must have been declared with [CAML_INSTR_DECLARE]
and allocated with [CAML_INSTR_ALLOC]. */
#define CAML_INSTR_START(t, msg) do{ \
if (t != NULL){ \
t->tag[0] = msg; \
clock_gettime (CLOCK_REALTIME, &(t->ts[0])); \
} \
}while(0)
/* Declare a timer, allocate its data, and start it.
[t] must be a new variable name. */
#define CAML_INSTR_SETUP(t, msg) \
CAML_INSTR_DECLARE (t); \
CAML_INSTR_ALLOC (t); \
CAML_INSTR_START (t, msg)
/* Record an intermediate time within a given timer.
[t] must have been declared, allocated, and started. */
#define CAML_INSTR_TIME(t, msg) do{ \
if (t != NULL){ \
++ t->index; \
t->tag[t->index] = (msg); \
clock_gettime (CLOCK_REALTIME, &(t->ts[t->index])); \
} \
}while(0)
/* Record an integer data point.
If [msg] ends with # it will be interpreted as an integer-valued event.
If it ends with @ it will be interpreted as an event counter.
*/
#define CAML_INSTR_INT(msg, data) do{ \
CAML_INSTR_SETUP (__caml_tmp, ""); \
if (__caml_tmp != NULL){ \
__caml_tmp->index = 1; \
__caml_tmp->tag[1] = msg; \
__caml_tmp->ts[1].tv_sec = 0; \
__caml_tmp->ts[1].tv_nsec = (data); \
} \
}while(0)
/* This function is called at the start of the program to set up
the data for the above macros.
*/
extern void CAML_INSTR_INIT (void);
/* This function is automatically called by the runtime to output
the collected data to the dump file. */
extern void CAML_INSTR_ATEXIT (void);
#else /* CAML_INSTR */
#define CAML_INSTR_DECLARE(t) /**/
#define CAML_INSTR_ALLOC(t) /**/
#define CAML_INSTR_START(t, name) /**/
#define CAML_INSTR_SETUP(t, name) /**/
#define CAML_INSTR_TIME(t, msg) /**/
#define CAML_INSTR_INT(msg, c) /**/
#define CAML_INSTR_INIT() /**/
#define CAML_INSTR_ATEXIT() /**/
#endif /* CAML_INSTR */
/* </private> */
#ifdef __cplusplus

View File

@ -217,7 +217,8 @@ CAMLextern value caml_hash_variant(char const * tag);
#define Byte_u(x, i) (((unsigned char *) (x)) [i]) /* Also an l-value. */
/* Abstract things. Their contents is not traced by the GC; therefore they
must not contain any [value].
must not contain any [value]. Must have odd number so that headers with
this tag cannot be mistaken for pointers (see caml_obj_truncate).
*/
#define Abstract_tag 251
@ -304,6 +305,4 @@ CAMLextern value caml_set_oo_id(value obj);
}
#endif
extern intnat caml_stat_top_heap_wsz;
#endif /* CAML_MLVALUES_H */

View File

@ -20,8 +20,10 @@
typedef void (*scanning_action) (value, value *);
void caml_oldify_local_roots (void);
void caml_darken_all_roots (void);
void caml_do_roots (scanning_action);
void caml_darken_all_roots_start (void);
intnat caml_darken_all_roots_slice (intnat);
void caml_do_roots (scanning_action, int);
extern uintnat caml_incremental_roots_count;
#ifndef NATIVE_CODE
CAMLextern void caml_do_local_roots (scanning_action, value *, value *,
struct caml__roots_block *);

View File

@ -28,14 +28,16 @@ extern "C" {
CAMLextern intnat volatile caml_signals_are_pending;
CAMLextern intnat volatile caml_pending_signals[];
CAMLextern int volatile caml_something_to_do;
extern int volatile caml_force_major_slice;
extern int volatile caml_requested_major_slice;
extern int volatile caml_requested_minor_gc;
/* </private> */
CAMLextern void caml_enter_blocking_section (void);
CAMLextern void caml_leave_blocking_section (void);
/* <private> */
void caml_urge_major_slice (void);
void caml_request_major_slice (void);
void caml_request_minor_gc (void);
CAMLextern int caml_convert_signal_number (int);
CAMLextern int caml_rev_convert_signal_number (int);
void caml_execute_signal(int signal_number, int in_signal_handler);

View File

@ -21,6 +21,7 @@ extern uintnat caml_init_minor_heap_wsz;
extern uintnat caml_init_heap_chunk_sz;
extern uintnat caml_init_heap_wsz;
extern uintnat caml_init_max_stack_wsz;
extern uintnat caml_init_major_window;
extern uintnat caml_trace_level;
extern void caml_parse_ocamlrunparam (void);

View File

@ -185,7 +185,7 @@ static void do_compaction (void)
/* Invert roots first because the threads library needs some heap
data structures to find its roots. Fortunately, it doesn't need
the headers (see above). */
caml_do_roots (invert_root);
caml_do_roots (invert_root, 1);
caml_final_do_weak_roots (invert_root);
ch = caml_heap_start;
@ -398,8 +398,14 @@ uintnat caml_percent_max; /* used in gc_ctrl.c and memory.c */
void caml_compact_heap (void)
{
uintnat target_wsz, live;
CAML_INSTR_SETUP(tmr, "compact");
CAMLassert (caml_young_ptr == caml_young_alloc_end);
CAMLassert (caml_ref_table.ptr == caml_ref_table.base);
CAMLassert (caml_weak_ref_table.ptr == caml_weak_ref_table.base);
do_compaction ();
CAML_INSTR_TIME (tmr, "compact/main");
/* Compaction may fail to shrink the heap to a reasonable size
because it deals in complete chunks: if a very large chunk
is at the beginning of the heap, everything gets moved to
@ -428,8 +434,16 @@ void caml_compact_heap (void)
live = caml_stat_heap_wsz - caml_fl_cur_wsz;
target_wsz = live + caml_percent_free * (live / 100 + 1)
+ Wsize_bsize (Page_size);
target_wsz = caml_round_heap_chunk_wsz (target_wsz);
target_wsz = caml_clip_heap_chunk_wsz (target_wsz);
#ifdef HAS_HUGE_PAGES
if (caml_use_huge_pages
&& Bsize_wsize (caml_stat_heap_wsz) <= HUGE_PAGE_SIZE)
return;
#endif
if (target_wsz < caml_stat_heap_wsz / 2){
/* Recompact. */
char *chunk;
caml_gc_message (0x10, "Recompacting heap (target=%luk words)\n",
@ -456,6 +470,7 @@ void caml_compact_heap (void)
Assert (caml_stat_heap_chunks == 1);
Assert (Chunk_next (caml_heap_start) == NULL);
Assert (caml_stat_heap_wsz == Wsize_bsize (Chunk_size (chunk)));
CAML_INSTR_TIME (tmr, "compact/recompact");
}
}
@ -473,7 +488,13 @@ void caml_compact_heap_maybe (void)
Assert (caml_gc_phase == Phase_idle);
if (caml_percent_max >= 1000000) return;
if (caml_stat_major_collections < 3) return;
if (caml_stat_heap_wsz <= 2 * caml_round_heap_chunk_wsz (0)) return;
if (caml_stat_heap_wsz <= 2 * caml_clip_heap_chunk_wsz (0)) return;
#ifdef HAS_HUGE_PAGES
if (caml_use_huge_pages
&& Bsize_wsize (caml_stat_heap_wsz) <= HUGE_PAGE_SIZE)
return;
#endif
fw = 3.0 * caml_fl_cur_wsz - 2.0 * caml_fl_wsz_at_phase_change;
if (fw < 0) fw = caml_fl_cur_wsz;
@ -492,9 +513,9 @@ void caml_compact_heap_maybe (void)
(uintnat) fp);
if (fp >= caml_percent_max){
caml_gc_message (0x200, "Automatic compaction triggered.\n", 0);
caml_empty_minor_heap (); /* minor heap must be empty for compaction */
caml_finish_major_cycle ();
/* We just did a complete GC, so we can measure the overhead exactly. */
fw = caml_fl_cur_wsz;
fp = 100.0 * fw / (caml_stat_heap_wsz - fw);
caml_gc_message (0x200, "Measured overhead: %"

View File

@ -17,6 +17,7 @@
#include <string.h>
#include "caml/alloc.h"
#include "caml/config.h"
#include "caml/custom.h"
#include "caml/fail.h"
#include "caml/gc.h"
@ -28,10 +29,6 @@
#include "caml/mlvalues.h"
#include "caml/reverse.h"
#ifdef _MSC_VER
#define inline _inline
#endif
static uintnat obj_counter; /* Number of objects emitted so far */
static uintnat size_32; /* Size in words of 32-bit block for struct. */
static uintnat size_64; /* Size in words of 64-bit block for struct. */

View File

@ -59,16 +59,15 @@ static void alloc_to_do (int size)
}
}
/* Find white finalisable values, put them in the finalising set, and
/* Find white finalisable values, move them to the finalising set, and
darken them.
The recent set is empty.
*/
void caml_final_update (void)
{
uintnat i, j, k;
uintnat todo_count = 0;
Assert (young == old);
Assert (old <= young);
for (i = 0; i < old; i++){
Assert (Is_block (final_table[i].val));
Assert (Is_in_heap (final_table[i].val));
@ -79,35 +78,25 @@ void caml_final_update (void)
alloc_to_do (todo_count);
j = k = 0;
for (i = 0; i < old; i++){
again:
Assert (Is_block (final_table[i].val));
Assert (Is_in_heap (final_table[i].val));
Assert (Tag_val (final_table[i].val) != Forward_tag);
if (Is_white_val (final_table[i].val)){
if (Tag_val (final_table[i].val) == Forward_tag){
value fv;
Assert (final_table[i].offset == 0);
fv = Forward_val (final_table[i].val);
if (Is_block (fv)
&& (!Is_in_value_area(fv) || Tag_val (fv) == Forward_tag
|| Tag_val (fv) == Lazy_tag || Tag_val (fv) == Double_tag)){
/* Do not short-circuit the pointer. */
}else{
final_table[i].val = fv;
if (Is_block (final_table[i].val)
&& Is_in_heap (final_table[i].val)){
goto again;
}
}
}
to_do_tl->item[k++] = final_table[i];
}else{
final_table[j++] = final_table[i];
}
}
young = old = j;
CAMLassert (i == old);
old = j;
for(;i < young; i++){
final_table[j++] = final_table[i];
}
young = j;
to_do_tl->size = k;
for (i = 0; i < k; i++){
CAMLassert (Is_white_val (to_do_tl->item[i].val));
/* Note that item may already be dark due to multiple entries in
the final table. */
caml_darken (to_do_tl->item[i].val, NULL);
}
}
@ -124,7 +113,7 @@ void caml_final_do_calls (void)
value res;
if (running_finalisation_function) return;
if (caml_finalise_begin_hook != NULL) (*caml_finalise_begin_hook) ();
if (to_do_hd != NULL){
if (caml_finalise_begin_hook != NULL) (*caml_finalise_begin_hook) ();
caml_gc_message (0x80, "Calling finalisation functions.\n", 0);
@ -147,6 +136,7 @@ void caml_final_do_calls (void)
caml_gc_message (0x80, "Done calling finalisation functions.\n", 0);
if (caml_finalise_end_hook != NULL) (*caml_finalise_end_hook) ();
}
if (caml_finalise_end_hook != NULL) (*caml_finalise_end_hook) ();
}
/* Call a scanning_action [f] on [x]. */
@ -154,17 +144,15 @@ void caml_final_do_calls (void)
/* Call [*f] on the closures of the finalisable set and
the closures and values of the finalising set.
The recent set is empty.
This is called by the major GC and the compactor
through [caml_darken_all_roots].
This is called by the major GC through [caml_darken_all_roots].
*/
void caml_final_do_strong_roots (scanning_action f)
{
uintnat i;
struct to_do *todo;
Assert (old == young);
for (i = 0; i < old; i++) Call_action (f, final_table[i].fun);
Assert (old <= young);
for (i = 0; i < young; i++) Call_action (f, final_table[i].fun);
for (todo = to_do_hd; todo != NULL; todo = todo->next){
for (i = 0; i < todo->size; i++){
@ -175,15 +163,14 @@ void caml_final_do_strong_roots (scanning_action f)
}
/* Call [*f] on the values of the finalisable set.
The recent set is empty.
This is called directly by the compactor.
*/
void caml_final_do_weak_roots (scanning_action f)
{
uintnat i;
Assert (old == young);
for (i = 0; i < old; i++) Call_action (f, final_table[i].val);
CAMLassert (old <= young);
for (i = 0; i < young; i++) Call_action (f, final_table[i].val);
}
/* Call [*f] on the closures and values of the recent set.
@ -213,9 +200,10 @@ void caml_final_empty_young (void)
CAMLprim value caml_final_register (value f, value v)
{
if (!Is_block (v)
|| !Is_in_heap_or_young(v)
|| Tag_val (v) == Lazy_tag
|| Tag_val (v) == Double_tag) {
|| !Is_in_heap_or_young(v)
|| Tag_val (v) == Lazy_tag
|| Tag_val (v) == Double_tag
|| Tag_val (v) == Forward_tag) {
caml_invalid_argument ("Gc.finalise");
}
Assert (old <= young);

View File

@ -148,6 +148,35 @@ static header_t *allocate_block (mlsize_t wh_sz, int flpi, value prev,
return (header_t *) &Field (cur, Wosize_hd (h) - wh_sz);
}
#ifdef CAML_INSTR
static uintnat instr_size [20] =
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
static char *instr_name [20] = {
NULL,
"alloc01@",
"alloc02@",
"alloc03@",
"alloc04@",
"alloc05@",
"alloc06@",
"alloc07@",
"alloc08@",
"alloc09@",
"alloc10-19@",
"alloc20-29@",
"alloc30-39@",
"alloc40-49@",
"alloc50-59@",
"alloc60-69@",
"alloc70-79@",
"alloc80-89@",
"alloc90-99@",
"alloc_large@",
};
uintnat caml_instr_alloc_jump = 0;
/* number of pointers followed to allocate from the free list */
#endif /*CAML_INSTR*/
/* [caml_fl_allocate] does not set the header of the newly allocated block.
The calling function must do it before any GC function gets called.
[caml_fl_allocate] returns a head pointer.
@ -160,6 +189,16 @@ header_t *caml_fl_allocate (mlsize_t wo_sz)
mlsize_t sz, prevsz;
Assert (sizeof (char *) == sizeof (value));
Assert (wo_sz >= 1);
#ifdef CAML_INSTR
if (wo_sz < 10){
++instr_size[wo_sz];
}else if (wo_sz < 100){
++instr_size[wo_sz/10 + 9];
}else{
++instr_size[19];
}
#endif /* CAML_INSTR */
switch (policy){
case Policy_next_fit:
Assert (fl_prev != Val_NULL);
@ -172,6 +211,9 @@ header_t *caml_fl_allocate (mlsize_t wo_sz)
}
prev = cur;
cur = Next (prev);
#ifdef CAML_INSTR
++ caml_instr_alloc_jump;
#endif
}
fl_last = prev;
/* Search from the start of the list to [fl_prev]. */
@ -183,6 +225,9 @@ header_t *caml_fl_allocate (mlsize_t wo_sz)
}
prev = cur;
cur = Next (prev);
#ifdef CAML_INSTR
++ caml_instr_alloc_jump;
#endif
}
/* No suitable block was found. */
return NULL;
@ -347,6 +392,13 @@ static header_t *last_fragment;
void caml_fl_init_merge (void)
{
#ifdef CAML_INSTR
int i;
for (i = 1; i < 20; i++){
CAML_INSTR_INT (instr_name[i], instr_size[i]);
instr_size[i] = 0;
}
#endif /* CAML_INSTR */
last_fragment = NULL;
caml_fl_merge = Fl_head;
#ifdef DEBUG

View File

@ -12,21 +12,26 @@
/***********************************************************************/
#include "caml/alloc.h"
#include "caml/backtrace.h"
#include "caml/compact.h"
#include "caml/custom.h"
#include "caml/fail.h"
#include "caml/finalise.h"
#include "caml/freelist.h"
#include "caml/gc.h"
#include "caml/gc_ctrl.h"
#include "caml/major_gc.h"
#include "caml/memory.h"
#include "caml/minor_gc.h"
#include "caml/misc.h"
#include "caml/mlvalues.h"
#include "caml/signals.h"
#ifdef NATIVE_CODE
#include "stack.h"
#else
#include "caml/stacks.h"
#endif
#include "caml/startup_aux.h"
#ifndef NATIVE_CODE
extern uintnat caml_max_stack_size; /* defined in stacks.c */
@ -214,7 +219,7 @@ static value heap_stats (int returnstats)
/* get a copy of these before allocating anything... */
double minwords = caml_stat_minor_words
+ (double) (caml_young_end - caml_young_ptr);
+ (double) (caml_young_alloc_end - caml_young_ptr);
double prowords = caml_stat_promoted_words;
double majwords = caml_stat_major_words + (double) caml_allocated_words;
intnat mincoll = caml_stat_minor_collections;
@ -255,8 +260,12 @@ void caml_heap_check (void)
CAMLprim value caml_gc_stat(value v)
{
value result;
CAML_INSTR_SETUP (tmr, "");
Assert (v == Val_unit);
return heap_stats (1);
result = heap_stats (1);
CAML_INSTR_TIME (tmr, "explicit/gc_stat");
return result;
}
CAMLprim value caml_gc_quick_stat(value v)
@ -266,7 +275,7 @@ CAMLprim value caml_gc_quick_stat(value v)
/* get a copy of these before allocating anything... */
double minwords = caml_stat_minor_words
+ (double) (caml_young_end - caml_young_ptr);
+ (double) (caml_young_alloc_end - caml_young_ptr);
double prowords = caml_stat_promoted_words;
double majwords = caml_stat_major_words + (double) caml_allocated_words;
intnat mincoll = caml_stat_minor_collections;
@ -303,7 +312,7 @@ CAMLprim value caml_gc_counters(value v)
/* get a copy of these before allocating anything... */
double minwords = caml_stat_minor_words
+ (double) (caml_young_end - caml_young_ptr);
+ (double) (caml_young_alloc_end - caml_young_ptr);
double prowords = caml_stat_promoted_words;
double majwords = caml_stat_major_words + (double) caml_allocated_words;
@ -314,12 +323,17 @@ CAMLprim value caml_gc_counters(value v)
CAMLreturn (res);
}
CAMLprim value caml_gc_huge_fallback_count (value v)
{
return Val_long (caml_huge_fallback_count);
}
CAMLprim value caml_gc_get(value v)
{
CAMLparam0 (); /* v is ignored */
CAMLlocal1 (res);
res = caml_alloc_tuple (7);
res = caml_alloc_tuple (8);
Store_field (res, 0, Val_long (caml_minor_heap_wsz)); /* s */
Store_field (res, 1, Val_long (caml_major_heap_increment)); /* i */
Store_field (res, 2, Val_long (caml_percent_free)); /* o */
@ -331,6 +345,7 @@ CAMLprim value caml_gc_get(value v)
Store_field (res, 5, Val_long (0));
#endif
Store_field (res, 6, Val_long (caml_allocation_policy)); /* a */
Store_field (res, 7, Val_long (caml_major_window)); /* w */
CAMLreturn (res);
}
@ -353,12 +368,20 @@ static intnat norm_minsize (intnat s)
return s;
}
static uintnat norm_window (intnat w)
{
if (w < 1) w = 1;
if (w > Max_major_window) w = Max_major_window;
return w;
}
CAMLprim value caml_gc_set(value v)
{
uintnat newpf, newpm;
asize_t newheapincr;
asize_t newminwsz;
uintnat oldpolicy;
CAML_INSTR_SETUP (tmr, "");
caml_verb_gc = Long_val (Field (v, 3));
@ -396,6 +419,16 @@ CAMLprim value caml_gc_set(value v)
caml_allocation_policy);
}
/* This field was added in 4.03.0. */
if (Wosize_val (v) >= 8){
int old_window = caml_major_window;
caml_set_major_window (norm_window (Long_val (Field (v, 7))));
if (old_window != caml_major_window){
caml_gc_message (0x20, "New smoothing window size: %d\n",
caml_major_window);
}
}
/* Minor heap size comes last because it will trigger a minor collection
(thus invalidating [v]) and it can raise [Out_of_memory]. */
newminwsz = norm_minsize (Long_val (Field (v, 0)));
@ -404,12 +437,17 @@ CAMLprim value caml_gc_set(value v)
newminwsz / 1024);
caml_set_minor_heap_size (Bsize_wsize (newminwsz));
}
CAML_INSTR_TIME (tmr, "explicit/gc_set");
return Val_unit;
}
CAMLprim value caml_gc_minor(value v)
{ Assert (v == Val_unit);
caml_minor_collection ();
{
CAML_INSTR_SETUP (tmr, "");
Assert (v == Val_unit);
caml_request_minor_gc ();
caml_gc_dispatch ();
CAML_INSTR_TIME (tmr, "explicit/gc_minor");
return Val_unit;
}
@ -429,17 +467,22 @@ static void test_and_compact (void)
}
CAMLprim value caml_gc_major(value v)
{ Assert (v == Val_unit);
{
CAML_INSTR_SETUP (tmr, "");
Assert (v == Val_unit);
caml_gc_message (0x1, "Major GC cycle requested\n", 0);
caml_empty_minor_heap ();
caml_finish_major_cycle ();
test_and_compact ();
caml_final_do_calls ();
CAML_INSTR_TIME (tmr, "explicit/gc_major");
return Val_unit;
}
CAMLprim value caml_gc_full_major(value v)
{ Assert (v == Val_unit);
{
CAML_INSTR_SETUP (tmr, "");
Assert (v == Val_unit);
caml_gc_message (0x1, "Full major GC cycle requested\n", 0);
caml_empty_minor_heap ();
caml_finish_major_cycle ();
@ -448,18 +491,24 @@ CAMLprim value caml_gc_full_major(value v)
caml_finish_major_cycle ();
test_and_compact ();
caml_final_do_calls ();
CAML_INSTR_TIME (tmr, "explicit/gc_full_major");
return Val_unit;
}
CAMLprim value caml_gc_major_slice (value v)
{
CAML_INSTR_SETUP (tmr, "");
Assert (Is_long (v));
caml_empty_minor_heap ();
return Val_long (caml_major_collection_slice (Long_val (v)));
caml_major_collection_slice (Long_val (v));
CAML_INSTR_TIME (tmr, "explicit/gc_major_slice");
return Val_long (0);
}
CAMLprim value caml_gc_compaction(value v)
{ Assert (v == Val_unit);
{
CAML_INSTR_SETUP (tmr, "");
Assert (v == Val_unit);
caml_gc_message (0x10, "Heap compaction requested\n", 0);
caml_empty_minor_heap ();
caml_finish_major_cycle ();
@ -468,9 +517,35 @@ CAMLprim value caml_gc_compaction(value v)
caml_finish_major_cycle ();
caml_compact_heap ();
caml_final_do_calls ();
CAML_INSTR_TIME (tmr, "explicit/gc_compact");
return Val_unit;
}
CAMLprim value caml_get_minor_free (value v)
{
return Val_int (caml_young_ptr - caml_young_alloc_start);
}
CAMLprim value caml_get_major_bucket (value v)
{
long i = Long_val (v);
if (i < 0) caml_invalid_argument ("Gc.get_bucket");
if (i < caml_major_window){
i += caml_major_ring_index;
if (i >= caml_major_window) i -= caml_major_window;
CAMLassert (0 <= i && i < caml_major_window);
return Val_long ((long) (caml_major_ring[i] * 1e6));
}else{
return Val_long (0);
}
}
CAMLprim value caml_get_major_credit (value v)
{
CAMLassert (v == Val_unit);
return Val_long ((long) (caml_major_work_credit * 1e6));
}
uintnat caml_normalize_heap_increment (uintnat i)
{
if (i < Bsize_wsize (Heap_chunk_min)){
@ -483,11 +558,15 @@ uintnat caml_normalize_heap_increment (uintnat i)
[major_incr] is either a percentage or a number of words */
void caml_init_gc (uintnat minor_size, uintnat major_size,
uintnat major_incr, uintnat percent_fr,
uintnat percent_m)
uintnat percent_m, uintnat window)
{
uintnat major_heap_size =
Bsize_wsize (caml_normalize_heap_increment (major_size));
CAML_INSTR_INIT ();
if (caml_init_alloc_for_heap () != 0){
caml_fatal_error ("cannot initialize heap: mmap failed\n");
}
if (caml_page_table_initialize(Bsize_wsize(minor_size) + major_heap_size)){
caml_fatal_error ("OCaml runtime error: cannot initialize page table\n");
}
@ -496,6 +575,7 @@ void caml_init_gc (uintnat minor_size, uintnat major_size,
caml_percent_free = norm_pfree (percent_fr);
caml_percent_max = norm_pmax (percent_m);
caml_init_major_heap (major_heap_size);
caml_major_window = norm_window (window);
caml_gc_message (0x20, "Initial minor heap size: %luk words\n",
caml_minor_heap_wsz / 1024);
caml_gc_message (0x20, "Initial major heap size: %luk bytes\n",
@ -511,6 +591,54 @@ void caml_init_gc (uintnat minor_size, uintnat major_size,
}
caml_gc_message (0x20, "Initial allocation policy: %d\n",
caml_allocation_policy);
caml_gc_message (0x20, "Initial smoothing window: %d\n",
caml_major_window);
}
/* FIXME After the startup_aux.c unification, move these functions there. */
CAMLprim value caml_runtime_variant (value unit)
{
CAMLassert (unit == Val_unit);
#if defined (DEBUG)
return caml_copy_string ("d");
#elif defined (CAML_INSTR)
return caml_copy_string ("i");
#elif defined (MMAP_INTERVAL)
return caml_copy_string ("m");
#else
return caml_copy_string ("");
#endif
}
extern int caml_parser_trace;
CAMLprim value caml_runtime_parameters (value unit)
{
CAMLassert (unit == Val_unit);
return caml_alloc_sprintf
("a=%d,b=%s,H=%lu,i=%lu,l=%lu,o=%lu,O=%lu,p=%d,s=%lu,t=%d,v=%lu,w=%d,W=%lu",
/* a */ caml_allocation_policy,
/* b */ caml_backtrace_active,
/* h */ /* missing */ /* FIXME add when changed to min_heap_size */
/* H */ caml_use_huge_pages,
/* i */ caml_major_heap_increment,
#ifdef NATIVE_CODE
/* l */ 0,
#else
/* l */ caml_max_stack_size,
#endif
/* o */ caml_percent_free,
/* O */ caml_percent_max,
/* p */ caml_parser_trace,
/* R */ /* missing */
/* s */ caml_minor_heap_wsz,
/* t */ caml_trace_level,
/* v */ caml_verb_gc,
/* w */ caml_major_window,
/* W */ caml_runtime_warnings
);
}
/* Control runtime warnings */

View File

@ -19,6 +19,7 @@
#include <string.h>
#include <ctype.h>
#include "caml/instrtrace.h"
#include "caml/instruct.h"
#include "caml/misc.h"
#include "caml/mlvalues.h"

View File

@ -19,6 +19,7 @@
#include <stdio.h>
#include "caml/alloc.h"
#include "caml/callback.h"
#include "caml/config.h"
#include "caml/custom.h"
#include "caml/fail.h"
#include "caml/gc.h"
@ -30,10 +31,6 @@
#include "caml/misc.h"
#include "caml/reverse.h"
#ifdef _MSC_VER
#define inline _inline
#endif
static unsigned char * intern_src;
/* Reading pointer in block holding input data. */
@ -618,8 +615,7 @@ static void intern_add_to_heap(mlsize_t whsize)
/* Add new heap chunk to heap if needed */
if (intern_extra_block != NULL) {
/* If heap chunk not filled totally, build free block at end */
asize_t request =
((Bsize_wsize(whsize) + Page_size - 1) >> Page_log) << Page_log;
asize_t request = Chunk_size (intern_extra_block);
header_t * end_extra_block =
(header_t *) intern_extra_block + Wsize_bsize(request);
Assert(intern_block == 0);

View File

@ -26,27 +26,6 @@ CAMLextern void caml_expand_command_line (int *, char ***);
int main(int argc, char **argv)
{
#ifdef DEBUG
caml_gc_message (-1, "### OCaml runtime: debug mode ###\n", 0);
#if 0
{
int i;
char *ocp;
char *cp;
caml_gc_message (-1, "### command line:", 0);
for (i = 0; i < argc; i++){
caml_gc_message (-1, " %s", argv[i]);
}
caml_gc_message (-1, "\n", 0);
ocp = getenv ("OCAMLRUNPARAM");
caml_gc_message (-1, "### OCAMLRUNPARAM=%s\n", ocp == NULL ? "" : ocp);
cp = getenv ("CAMLRUNPARAM");
caml_gc_message (-1, "### CAMLRUNPARAM=%s\n", cp == NULL ? "" : cp);
caml_gc_message (-1, "### working dir: %s\n", getcwd (NULL, 0));
}
#endif
#endif
#ifdef _WIN32
/* Expand wildcards and diversions in command line */
caml_expand_command_line(&argc, &argv);

View File

@ -12,6 +12,7 @@
/***********************************************************************/
#include <limits.h>
#include <math.h>
#include "caml/compact.h"
#include "caml/custom.h"
@ -55,6 +56,12 @@ static char *markhp, *chunk, *limit;
int caml_gc_subphase; /* Subphase_{main,weak1,weak2,final} */
static value *weak_prev;
int caml_major_window = 1;
double caml_major_ring[Max_major_window] = { 0. };
int caml_major_ring_index = 0;
double caml_major_work_credit = 0.0;
double caml_gc_clock = 0.0;
#ifdef DEBUG
static unsigned long major_gc_counter = 0;
#endif
@ -91,7 +98,7 @@ static void realloc_gray_vals (void)
void caml_darken (value v, value *p /* not used */)
{
#ifdef NATIVE_CODE_AND_NO_NAKED_POINTERS
if (Is_block (v) && Wosize_val (v) > 0) {
if (Is_block (v) && !Is_young (v) && Wosize_val (v) > 0) {
#else
if (Is_block (v) && Is_in_heap (v)) {
#endif
@ -129,9 +136,9 @@ static void start_cycle (void)
Assert (caml_gc_phase == Phase_idle);
Assert (gray_vals_cur == gray_vals);
caml_gc_message (0x01, "Starting new major GC cycle\n", 0);
caml_darken_all_roots();
caml_darken_all_roots_start ();
caml_gc_phase = Phase_mark;
caml_gc_subphase = Subphase_main;
caml_gc_subphase = Subphase_roots;
markhp = NULL;
#ifdef DEBUG
++ major_gc_counter;
@ -139,35 +146,65 @@ static void start_cycle (void)
#endif
}
/* We may stop the slice inside values, in order to avoid large latencies
on large arrays. In this case, [current_value] is the partially-marked
value and [current_index] is the index of the next field to be marked.
*/
static value current_value = 0;
static mlsize_t current_index = 0;
#ifdef CAML_INSTR
#define INSTR(x) x
#else
#define INSTR(x) /**/
#endif
static void mark_slice (intnat work)
{
value *gray_vals_ptr; /* Local copy of gray_vals_cur */
value *gray_vals_ptr; /* Local copy of [gray_vals_cur] */
value v, child;
header_t hd;
mlsize_t size, i;
header_t hd, chd;
mlsize_t size, i, start, end; /* [start] is a local copy of [current_index] */
#ifdef NATIVE_CODE_AND_NO_NAKED_POINTERS
int marking_closure = 0;
#endif
#ifdef CAML_INSTR
int slice_fields = 0;
int slice_pointers = 0;
#endif
caml_gc_message (0x40, "Marking %ld words\n", work);
caml_gc_message (0x40, "Subphase = %ld\n", caml_gc_subphase);
gray_vals_ptr = gray_vals_cur;
v = current_value;
start = current_index;
while (work > 0){
if (gray_vals_ptr > gray_vals){
if (v == 0 && gray_vals_ptr > gray_vals){
CAMLassert (start == 0);
v = *--gray_vals_ptr;
CAMLassert (Is_gray_val (v));
}
if (v != 0){
hd = Hd_val(v);
#ifdef NATIVE_CODE_AND_NO_NAKED_POINTERS
marking_closure =
(Tag_hd (hd) == Closure_tag || Tag_hd (hd) == Infix_tag);
#endif
Assert (Is_gray_hd (hd));
Hd_val (v) = Blackhd_hd (hd);
size = Wosize_hd (hd);
end = start + work;
if (Tag_hd (hd) < No_scan_tag){
for (i = 0; i < size; i++){
start = size < start ? size : start;
end = size < end ? size : end;
CAMLassert (end > start);
INSTR (slice_fields += end - start;)
INSTR (if (size > end)
CAML_INSTR_INT ("major/mark/slice/remain", size - end);)
for (i = start; i < end; i++){
child = Field (v, i);
#ifdef NATIVE_CODE_AND_NO_NAKED_POINTERS
if (Is_block (child)
&& ! Is_young (child)
&& Wosize_val (child) > 0 /* Atoms never need to be marked. */
/* Closure blocks contain code pointers at offsets that cannot
be reliably determined, so we always use the page table when
@ -176,8 +213,9 @@ static void mark_slice (intnat work)
#else
if (Is_block (child) && Is_in_heap (child)) {
#endif
hd = Hd_val (child);
if (Tag_hd (hd) == Forward_tag){
INSTR (++ slice_pointers;)
chd = Hd_val (child);
if (Tag_hd (chd) == Forward_tag){
value f = Forward_val (child);
if (Is_block (f)
&& (!Is_in_value_area(f) || Tag_val (f) == Forward_tag
@ -185,18 +223,19 @@ static void mark_slice (intnat work)
/* Do not short-circuit the pointer. */
}else{
Field (v, i) = f;
if (Is_block (f) && Is_young (f) && !Is_young (child))
add_to_ref_table (&caml_ref_table, &Field (v, i));
}
}
else if (Tag_hd(hd) == Infix_tag) {
}else if (Tag_hd(chd) == Infix_tag) {
child -= Infix_offset_val(child);
hd = Hd_val(child);
chd = Hd_val(child);
}
#ifdef NATIVE_CODE_AND_NO_NAKED_POINTERS
/* See [caml_darken] for a description of this assertion. */
CAMLassert (Is_in_heap (child) || Is_black_hd (hd));
CAMLassert (Is_in_heap (child) || Is_black_hd (chd));
#endif
if (Is_white_hd (hd)){
Hd_val (child) = Grayhd_hd (hd);
if (Is_white_hd (chd)){
Hd_val (child) = Grayhd_hd (chd);
*gray_vals_ptr++ = child;
if (gray_vals_ptr >= gray_vals_end) {
gray_vals_cur = gray_vals_ptr;
@ -206,8 +245,25 @@ static void mark_slice (intnat work)
}
}
}
if (end < size){
work = 0;
start = end;
/* [v] doesn't change. */
CAMLassert (Is_gray_val (v));
}else{
CAMLassert (end == size);
Hd_val (v) = Blackhd_hd (hd);
work -= Whsize_wosize(end - start);
start = 0;
v = 0;
}
}else{
/* The block doesn't contain any pointers. */
CAMLassert (start == 0);
Hd_val (v) = Blackhd_hd (hd);
work -= Whsize_wosize(size);
v = 0;
}
work -= Whsize_wosize(size);
}else if (markhp != NULL){
if (markhp == limit){
chunk = Chunk_next (chunk);
@ -220,7 +276,8 @@ static void mark_slice (intnat work)
}else{
if (Is_gray_val (Val_hp (markhp))){
Assert (gray_vals_ptr == gray_vals);
*gray_vals_ptr++ = Val_hp (markhp);
CAMLassert (v == 0 && start == 0);
v = Val_hp (markhp);
}
markhp += Bhsize_hp (markhp);
}
@ -231,6 +288,15 @@ static void mark_slice (intnat work)
limit = chunk + Chunk_size (chunk);
}else{
switch (caml_gc_subphase){
case Subphase_roots: {
gray_vals_cur = gray_vals_ptr;
work = caml_darken_all_roots_slice (work);
gray_vals_ptr = gray_vals_cur;
if (work > 0){
caml_gc_subphase = Subphase_main;
}
}
break;
case Subphase_main: {
/* The main marking phase is over. Start removing weak pointers to
dead values. */
@ -251,7 +317,7 @@ static void mark_slice (intnat work)
curfield = Field (cur, i);
weak_again:
if (curfield != caml_weak_none
&& Is_block (curfield) && Is_in_heap (curfield)){
&& Is_block (curfield) && Is_in_heap_or_young (curfield)){
if (Tag_val (curfield) == Forward_tag){
value f = Forward_val (curfield);
if (Is_block (f)) {
@ -260,11 +326,13 @@ static void mark_slice (intnat work)
/* Do not short-circuit the pointer. */
}else{
Field (cur, i) = curfield = f;
if (Is_block (f) && Is_young (f))
add_to_ref_table (&caml_weak_ref_table, &Field (cur, i));
goto weak_again;
}
}
}
if (Is_white_val (curfield)){
if (Is_white_val (curfield) && !Is_young (curfield)){
Field (cur, i) = caml_weak_none;
}
}
@ -277,6 +345,10 @@ static void mark_slice (intnat work)
gray_vals_cur = gray_vals_ptr;
caml_final_update ();
gray_vals_ptr = gray_vals_cur;
if (gray_vals_ptr > gray_vals){
v = *--gray_vals_ptr;
CAMLassert (start == 0);
}
caml_gc_subphase = Subphase_weak2;
weak_prev = &caml_weak_list_head;
}
@ -304,7 +376,6 @@ static void mark_slice (intnat work)
break;
case Subphase_final: {
/* Initialise the sweep phase. */
gray_vals_cur = gray_vals_ptr;
caml_gc_sweep_hp = caml_heap_start;
caml_fl_init_merge ();
caml_gc_phase = Phase_sweep;
@ -321,6 +392,10 @@ static void mark_slice (intnat work)
}
}
gray_vals_cur = gray_vals_ptr;
current_value = v;
current_index = start;
INSTR (CAML_INSTR_INT ("major/mark/slice/fields#", slice_fields);)
INSTR (CAML_INSTR_INT ("major/mark/slice/pointers#", slice_pointers);)
}
static void sweep_slice (intnat work)
@ -368,14 +443,37 @@ static void sweep_slice (intnat work)
}
}
/* The main entry point for the GC. Called after each minor GC.
[howmuch] is the amount of work to do, 0 to let the GC compute it.
Return the computed amount of work to do.
#ifdef CAML_INSTR
static char *mark_slice_name[] = {
/* 0 */ NULL,
/* 1 */ NULL,
/* 2 */ NULL,
/* 3 */ NULL,
/* 4 */ NULL,
/* 5 */ NULL,
/* 6 */ NULL,
/* 7 */ NULL,
/* 8 */ NULL,
/* 9 */ NULL,
/* 10 */ "major/mark_roots",
/* 11 */ "major/mark_main",
/* 12 */ "major/mark_weak1",
/* 13 */ "major/mark_weak2",
/* 14 */ "major/mark_final",
};
#endif
/* The main entry point for the major GC. Called about once for each
minor GC. [howmuch] is the amount of work to do:
-1 if the GC is triggered automatically
0 to let the GC compute the amount of work
[n] to make the GC do enough work to (on average) free [n] words
*/
intnat caml_major_collection_slice (intnat howmuch)
void caml_major_collection_slice (intnat howmuch)
{
double p, dp;
double p, dp, filt_p, spend;
intnat computed_work;
int i;
/*
Free memory at the start of the GC cycle (garbage + free list) (assumed):
FM = caml_stat_heap_wsz * caml_percent_free
@ -395,24 +493,37 @@ intnat caml_major_collection_slice (intnat howmuch)
PE = caml_extra_heap_resources
Proportion of total work to do in this slice:
P = max (PH, PE)
Here, we insert a time-based filter on the P variable to avoid large
latency spikes in the GC, so the P below is a smoothed-out version of
the P above.
Amount of marking work for the GC cycle:
MW = caml_stat_heap_wsz * 100 / (100 + caml_percent_free)
+ caml_incremental_roots_count
Amount of sweeping work for the GC cycle:
SW = caml_stat_heap_wsz
In order to finish marking with a non-empty free list, we will
use 40% of the time for marking, and 60% for sweeping.
If TW is the total work for this cycle,
MW = 40/100 * TW
SW = 60/100 * TW
Let MT be the time spent marking, ST the time spent sweeping, and TT
the total time for this cycle. We have:
MT = 40/100 * TT
ST = 60/100 * TT
Amount of work to do for this slice:
W = P * TW
Amount of time to spend on this slice:
T = P * TT = P * MT / (40/100) = P * ST / (60/100)
Since we must do MW work in MT time or SW work in ST time, the amount
of work for this slice is:
MS = P * MW / (40/100) if marking
SS = P * SW / (60/100) if sweeping
Amount of marking work for a marking slice:
MS = P * MW / (40/100)
MS = P * caml_stat_heap_wsz * 250 / (100 + caml_percent_free)
MS = P * (caml_stat_heap_wsz * 250 / (100 + caml_percent_free)
+ 2.5 * caml_incremental_roots_count)
Amount of sweeping work for a sweeping slice:
SS = P * SW / (60/100)
SS = P * caml_stat_heap_wsz * 5 / 3
@ -421,8 +532,7 @@ intnat caml_major_collection_slice (intnat howmuch)
*/
if (caml_major_slice_begin_hook != NULL) (*caml_major_slice_begin_hook) ();
if (caml_gc_phase == Phase_idle) start_cycle ();
CAML_INSTR_SETUP (tmr, "major");
p = (double) caml_allocated_words * 3.0 * (100 + caml_percent_free)
/ caml_stat_heap_wsz / caml_percent_free / 2.0;
@ -434,51 +544,133 @@ intnat caml_major_collection_slice (intnat howmuch)
}
if (p < dp) p = dp;
if (p < caml_extra_heap_resources) p = caml_extra_heap_resources;
if (p > 0.3) p = 0.3;
CAML_INSTR_INT ("major/work/extra#",
(uintnat) (caml_extra_heap_resources * 1000000));
caml_gc_message (0x40, "ordered work = %ld words\n", howmuch);
caml_gc_message (0x40, "allocated_words = %"
ARCH_INTNAT_PRINTF_FORMAT "u\n",
caml_allocated_words);
caml_gc_message (0x40, "extra_heap_resources = %"
ARCH_INTNAT_PRINTF_FORMAT "uu\n",
(uintnat) (caml_extra_heap_resources * 1000000));
caml_gc_message (0x40, "amount of work to do = %"
ARCH_INTNAT_PRINTF_FORMAT "uu\n",
(uintnat) (p * 1000000));
caml_gc_message (0x40, "raw work-to-do = %"
ARCH_INTNAT_PRINTF_FORMAT "du\n",
(intnat) (p * 1000000));
for (i = 0; i < caml_major_window; i++){
caml_major_ring[i] += p / caml_major_window;
}
if (caml_gc_clock >= 1.0){
caml_gc_clock -= 1.0;
++caml_major_ring_index;
if (caml_major_ring_index >= caml_major_window){
caml_major_ring_index = 0;
}
}
if (howmuch == -1){
/* auto-triggered GC slice: spend work credit on the current bucket,
then do the remaining work, if any */
/* Note that the minor GC guarantees that the major slice is called in
automatic mode (with [howmuch] = -1) at least once per clock tick.
This means we never leave a non-empty bucket behind. */
spend = fmin (caml_major_work_credit,
caml_major_ring[caml_major_ring_index]);
caml_major_work_credit -= spend;
filt_p = caml_major_ring[caml_major_ring_index] - spend;
caml_major_ring[caml_major_ring_index] = 0.0;
}else{
/* forced GC slice: do work and add it to the credit */
if (howmuch == 0){
/* automatic setting: size of next bucket
we do not use the current bucket, as it may be empty */
int i = caml_major_ring_index + 1;
if (i >= caml_major_window) i = 0;
filt_p = caml_major_ring[i];
}else{
/* manual setting */
filt_p = (double) howmuch * 3.0 * (100 + caml_percent_free)
/ caml_stat_heap_wsz / caml_percent_free / 2.0;
}
caml_major_work_credit += filt_p;
}
p = filt_p;
caml_gc_message (0x40, "filtered work-to-do = %"
ARCH_INTNAT_PRINTF_FORMAT "du\n",
(intnat) (p * 1000000));
if (caml_gc_phase == Phase_idle){
if (caml_young_ptr == caml_young_alloc_end){
/* We can only start a major GC cycle if the minor allocation arena
is empty, otherwise we'd have to treat it as a set of roots. */
start_cycle ();
CAML_INSTR_TIME (tmr, "major/roots");
}
p = 0;
goto finished;
}
if (p < 0){
p = 0;
goto finished;
}
if (caml_gc_phase == Phase_mark){
computed_work = (intnat) (p * caml_stat_heap_wsz * 250
/ (100 + caml_percent_free));
computed_work = (intnat) (p * (caml_stat_heap_wsz * 250
/ (100 + caml_percent_free)
+ caml_incremental_roots_count));
}else{
computed_work = (intnat) (p * caml_stat_heap_wsz * 5 / 3);
}
caml_gc_message (0x40, "ordered work = %ld words\n", howmuch);
caml_gc_message (0x40, "computed work = %ld words\n", computed_work);
if (howmuch == 0) howmuch = computed_work;
if (caml_gc_phase == Phase_mark){
mark_slice (howmuch);
CAML_INSTR_INT ("major/work/mark#", computed_work);
mark_slice (computed_work);
CAML_INSTR_TIME (tmr, mark_slice_name[caml_gc_subphase]);
caml_gc_message (0x02, "!", 0);
}else{
Assert (caml_gc_phase == Phase_sweep);
sweep_slice (howmuch);
CAML_INSTR_INT ("major/work/sweep#", computed_work);
sweep_slice (computed_work);
CAML_INSTR_TIME (tmr, "major/sweep");
caml_gc_message (0x02, "$", 0);
}
if (caml_gc_phase == Phase_idle) caml_compact_heap_maybe ();
if (caml_gc_phase == Phase_idle){
caml_compact_heap_maybe ();
CAML_INSTR_TIME (tmr, "major/check_and_compact");
}
finished:
caml_gc_message (0x40, "work-done = %"
ARCH_INTNAT_PRINTF_FORMAT "du\n",
(intnat) (p * 1000000));
/* if some of the work was not done, take it back from the credit
or spread it over the buckets. */
p = filt_p - p;
spend = fmin (p, caml_major_work_credit);
caml_major_work_credit -= spend;
if (p > spend){
p -= spend;
p /= caml_major_window;
for (i = 0; i < caml_major_window; i++) caml_major_ring[i] += p;
}
caml_stat_major_words += caml_allocated_words;
caml_allocated_words = 0;
caml_dependent_allocated = 0;
caml_extra_heap_resources = 0.0;
if (caml_major_slice_end_hook != NULL) (*caml_major_slice_end_hook) ();
return computed_work;
}
/* The minor heap must be empty when this function is called;
the minor heap is empty when this function returns.
*/
/* This does not call caml_compact_heap_maybe because the estimations of
/* This does not call [caml_compact_heap_maybe] because the estimates of
free and live memory are only valid for a cycle done incrementally.
Besides, this function is called by caml_compact_heap_maybe.
Besides, this function itself is called by [caml_compact_heap_maybe].
*/
void caml_finish_major_cycle (void)
{
@ -491,27 +683,12 @@ void caml_finish_major_cycle (void)
caml_allocated_words = 0;
}
/* Make sure the request is at least Heap_chunk_min and round it up
to a multiple of the page size.
The argument and result are both numbers of words.
/* Call this function to make sure [bsz] is greater than or equal
to both [Heap_chunk_min] and the current heap increment.
*/
static asize_t clip_heap_chunk_size (asize_t request)
asize_t caml_clip_heap_chunk_wsz (asize_t wsz)
{
if (request < Heap_chunk_min){
request = Heap_chunk_min;
}
return
Wsize_bsize (((Bsize_wsize (request) + Page_size - 1)
>> Page_log) << Page_log);
}
/* Compute the heap increment, make sure the request is at least that big,
then call clip_heap_chunk_size, then make sure the result is >= request.
The argument and result are both numbers of words.
*/
asize_t caml_round_heap_chunk_wsz (asize_t request)
{
asize_t result = request;
asize_t result = wsz;
uintnat incr;
/* Compute the heap increment as a word size. */
@ -524,11 +701,8 @@ asize_t caml_round_heap_chunk_wsz (asize_t request)
if (result < incr){
result = incr;
}
result = clip_heap_chunk_size (result);
if (result < request){
caml_raise_out_of_memory ();
return 0; /* not reached */
if (result < Heap_chunk_min){
result = Heap_chunk_min;
}
return result;
}
@ -536,21 +710,25 @@ asize_t caml_round_heap_chunk_wsz (asize_t request)
/* [heap_size] is a number of bytes */
void caml_init_major_heap (asize_t heap_size)
{
caml_stat_heap_wsz = Wsize_bsize (clip_heap_chunk_size (heap_size));
int i;
caml_stat_heap_wsz = caml_clip_heap_chunk_wsz (Wsize_bsize (heap_size));
caml_stat_top_heap_wsz = caml_stat_heap_wsz;
Assert (Bsize_wsize (caml_stat_heap_wsz) % Page_size == 0);
caml_heap_start =
(char *) caml_alloc_for_heap (Bsize_wsize (caml_stat_heap_wsz));
if (caml_heap_start == NULL)
caml_fatal_error ("Fatal error: not enough memory for the initial heap.\n");
caml_fatal_error ("Fatal error: cannot allocate initial major heap.\n");
Chunk_next (caml_heap_start) = NULL;
caml_stat_heap_wsz = Wsize_bsize (Chunk_size (caml_heap_start));
caml_stat_heap_chunks = 1;
caml_stat_top_heap_wsz = caml_stat_heap_wsz;
if (caml_page_table_add(In_heap, caml_heap_start,
caml_heap_start + Bsize_wsize (caml_stat_heap_wsz))
!= 0) {
caml_fatal_error ("Fatal error: not enough memory "
"for the initial page table.\n");
caml_fatal_error ("Fatal error: cannot allocate "
"initial page table.\n");
}
caml_fl_init_merge ();
@ -566,4 +744,21 @@ void caml_init_major_heap (asize_t heap_size)
heap_is_pure = 1;
caml_allocated_words = 0;
caml_extra_heap_resources = 0.0;
for (i = 0; i < Max_major_window; i++) caml_major_ring[i] = 0.0;
}
void caml_set_major_window (int w){
uintnat total = 0;
int i;
if (w == caml_major_window) return;
CAMLassert (w <= Max_major_window);
/* Collect the current work-to-do from the buckets. */
for (i = 0; i < caml_major_window; i++){
total += caml_major_ring[i];
}
/* Redistribute to the new buckets. */
for (i = 0; i < w; i++){
caml_major_ring[i] = total / w;
}
caml_major_window = w;
}

View File

@ -14,6 +14,7 @@
#include <stdlib.h>
#include <string.h>
#include "caml/address_class.h"
#include "caml/config.h"
#include "caml/fail.h"
#include "caml/freelist.h"
#include "caml/gc.h"
@ -26,9 +27,17 @@
#include "caml/mlvalues.h"
#include "caml/signals.h"
#ifdef _MSC_VER
#define inline _inline
#endif
int caml_huge_fallback_count = 0;
/* Number of times that mmapping big pages fails and we fell back to small
pages. This counter is available to the program through
[Gc.huge_fallback_count].
*/
uintnat caml_use_huge_pages = 0;
/* True iff the program allocates heap chunks by mmapping huge pages.
This is set when parsing [OCAMLRUNPARAM] and must stay constant
after that.
*/
extern uintnat caml_percent_free; /* major_gc.c */
@ -221,25 +230,56 @@ int caml_page_table_remove(int kind, void * start, void * end)
return 0;
}
/* Initialize the [alloc_for_heap] system.
This function must be called exactly once, and it must be called
before the first call to [alloc_for_heap].
It returns 0 on success and -1 on failure.
*/
int caml_init_alloc_for_heap (void)
{
return 0;
}
/* Allocate a block of the requested size, to be passed to
[caml_add_to_heap] later.
[request] must be a multiple of [Page_size], it is a number of bytes.
[caml_alloc_for_heap] returns NULL if the request cannot be satisfied.
The returned pointer is a hp, but the header must be initialized by
the caller.
[request] will be rounded up to some implementation-dependent size.
The caller must use [Chunk_size] on the result to recover the actual
size.
Return NULL if the request cannot be satisfied. The returned pointer
is a hp, but the header (and the contents) must be initialized by the
caller.
*/
char *caml_alloc_for_heap (asize_t request)
{
char *mem;
void *block;
Assert (request % Page_size == 0);
mem = caml_aligned_malloc (request + sizeof (heap_chunk_head),
sizeof (heap_chunk_head), &block);
if (mem == NULL) return NULL;
mem += sizeof (heap_chunk_head);
Chunk_size (mem) = request;
Chunk_block (mem) = block;
return mem;
if (caml_use_huge_pages){
#ifdef HAS_HUGE_PAGES
uintnat size = Round_mmap_size (sizeof (heap_chunk_head) + request);
void *block;
char *mem;
block = mmap (NULL, size, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB, -1, 0);
if (block == MAP_FAILED) return NULL;
mem = (char *) block + sizeof (heap_chunk_head);
Chunk_size (mem) = size - sizeof (heap_chunk_head);
Chunk_block (mem) = block;
return mem;
#else
return NULL;
#endif
}else{
char *mem;
void *block;
request = ((request + Page_size - 1) >> Page_log) << Page_log;
mem = caml_aligned_malloc (request + sizeof (heap_chunk_head),
sizeof (heap_chunk_head), &block);
if (mem == NULL) return NULL;
mem += sizeof (heap_chunk_head);
Chunk_size (mem) = request;
Chunk_block (mem) = block;
return mem;
}
}
/* Use this function to free a block allocated with [caml_alloc_for_heap]
@ -247,7 +287,15 @@ char *caml_alloc_for_heap (asize_t request)
*/
void caml_free_for_heap (char *mem)
{
free (Chunk_block (mem));
if (caml_use_huge_pages){
#ifdef HAS_HUGE_PAGES
munmap (Chunk_block (mem), Chunk_size (mem) + sizeof (heap_chunk_head));
#else
CAMLassert (0);
#endif
}else{
free (Chunk_block (mem));
}
}
/* Take a chunk of memory as argument, which must be the result of a
@ -263,10 +311,9 @@ void caml_free_for_heap (char *mem)
*/
int caml_add_to_heap (char *m)
{
Assert (Chunk_size (m) % Page_size == 0);
#ifdef DEBUG
/* Should check the contents of the block. */
#endif /* debug */
#endif /* DEBUG */
caml_gc_message (0x04, "Growing heap to %luk bytes\n",
(Bsize_wsize (caml_stat_heap_wsz) + Chunk_size (m)) / 1024);
@ -314,14 +361,14 @@ static value *expand_heap (mlsize_t request)
asize_t over_request, malloc_request, remain;
Assert (request <= Max_wosize);
over_request = Whsize_wosize (request + request / 100 * caml_percent_free);
malloc_request = caml_round_heap_chunk_wsz (over_request);
over_request = request + request / 100 * caml_percent_free;
malloc_request = caml_clip_heap_chunk_wsz (over_request);
mem = (value *) caml_alloc_for_heap (Bsize_wsize (malloc_request));
if (mem == NULL){
caml_gc_message (0x04, "No room for growing heap\n", 0);
return NULL;
}
remain = malloc_request;
remain = Wsize_bsize (Chunk_size (mem));
prev = hp = mem;
/* FIXME find a way to do this with a call to caml_make_free_blocks */
while (Wosize_whsize (remain) > Max_wosize){
@ -451,7 +498,8 @@ static inline value caml_alloc_shr_aux (mlsize_t wosize, tag_t tag,
Assert (Hd_hp (hp) == Make_header (wosize, tag, caml_allocation_color (hp)));
caml_allocated_words += Whsize_wosize (wosize);
if (caml_allocated_words > caml_minor_heap_wsz){
caml_urge_major_slice ();
CAML_INSTR_INT ("request_major/alloc_shr@", 1);
caml_request_major_slice ();
}
#ifdef DEBUG
{
@ -512,13 +560,15 @@ CAMLexport void caml_adjust_gc_speed (mlsize_t res, mlsize_t max)
if (res > max) res = max;
caml_extra_heap_resources += (double) res / (double) max;
if (caml_extra_heap_resources > 1.0){
CAML_INSTR_INT ("request_major/adjust_gc_speed_1@", 1);
caml_extra_heap_resources = 1.0;
caml_urge_major_slice ();
caml_request_major_slice ();
}
if (caml_extra_heap_resources
> (double) caml_minor_heap_wsz / 2.0
/ (double) caml_stat_heap_wsz) {
caml_urge_major_slice ();
CAML_INSTR_INT ("request_major/adjust_gc_speed_2@", 1);
caml_request_major_slice ();
}
}
@ -535,10 +585,7 @@ CAMLexport CAMLweakdef void caml_initialize (value *fp, value val)
CAMLassert(Is_in_heap(fp));
*fp = val;
if (Is_block (val) && Is_young (val)) {
if (caml_ref_table.ptr >= caml_ref_table.limit){
caml_realloc_ref_table (&caml_ref_table);
}
*caml_ref_table.ptr++ = fp;
add_to_ref_table (&caml_ref_table, fp);
}
}
@ -586,12 +633,7 @@ CAMLexport CAMLweakdef void caml_modify (value *fp, value val)
}
/* Check for condition 1. */
if (Is_block(val) && Is_young(val)) {
/* Add [fp] to remembered set */
if (caml_ref_table.ptr >= caml_ref_table.limit){
CAMLassert (caml_ref_table.ptr == caml_ref_table.limit);
caml_realloc_ref_table (&caml_ref_table);
}
*caml_ref_table.ptr++ = fp;
add_to_ref_table (&caml_ref_table, fp);
}
}
}

View File

@ -27,10 +27,36 @@
#include "caml/signals.h"
#include "caml/weak.h"
/* Pointers into the minor heap.
[caml_young_base]
The [malloc] block that contains the heap.
[caml_young_start] ... [caml_young_end]
The whole range of the minor heap: all young blocks are inside
this interval.
[caml_young_alloc_start]...[caml_young_alloc_end]
The allocation arena: newly-allocated blocks are carved from
this interval.
[caml_young_alloc_mid] is the mid-point of this interval.
[caml_young_ptr], [caml_young_trigger], [caml_young_limit]
These pointers are all inside the allocation arena.
- [caml_young_ptr] is where the next allocation will take place.
- [caml_young_trigger] is how far we can allocate before triggering
[caml_gc_dispatch]. Currently, it is either [caml_young_alloc_start]
or the mid-point of the allocation arena.
- [caml_young_limit] is the pointer that is compared to
[caml_young_ptr] for allocation. It is either
[caml_young_alloc_end] if a signal is pending and we are in
native code, or [caml_young_trigger].
*/
asize_t caml_minor_heap_wsz;
static void *caml_young_base = NULL;
CAMLexport value *caml_young_start = NULL, *caml_young_end = NULL;
CAMLexport value *caml_young_alloc_start = NULL,
*caml_young_alloc_mid = NULL,
*caml_young_alloc_end = NULL;
CAMLexport value *caml_young_ptr = NULL, *caml_young_limit = NULL;
CAMLexport value *caml_young_trigger = NULL;
CAMLexport struct caml_ref_table
caml_ref_table = { NULL, NULL, NULL, NULL, NULL, 0, 0},
@ -40,10 +66,6 @@ CAMLexport struct caml_ref_table
int caml_in_minor_collection = 0;
#ifdef DEBUG
static unsigned long minor_gc_counter = 0;
#endif
/* [sz] and [rsv] are numbers of entries */
void caml_alloc_table (struct caml_ref_table *tbl, asize_t sz, asize_t rsv)
{
@ -75,32 +97,73 @@ static void clear_table (struct caml_ref_table *tbl)
tbl->limit = tbl->threshold;
}
/* [size] is a number of bytes */
void caml_set_minor_heap_size (asize_t size)
void caml_set_minor_heap_size (asize_t bsz)
{
char *new_heap;
void *new_heap_base;
Assert (size >= Bsize_wsize(Minor_heap_min));
Assert (size <= Bsize_wsize(Minor_heap_max));
Assert (size % sizeof (value) == 0);
if (caml_young_ptr != caml_young_end) caml_minor_collection ();
Assert (caml_young_ptr == caml_young_end);
new_heap = caml_aligned_malloc(size, 0, &new_heap_base);
Assert (bsz >= Bsize_wsize(Minor_heap_min));
Assert (bsz <= Bsize_wsize(Minor_heap_max));
Assert (bsz % sizeof (value) == 0);
if (caml_young_ptr != caml_young_alloc_end){
CAML_INSTR_INT ("force_minor/set_minor_heap_size@", 1);
caml_requested_minor_gc = 0;
caml_young_trigger = caml_young_alloc_mid;
caml_young_limit = caml_young_trigger;
caml_empty_minor_heap ();
}
CAMLassert (caml_young_ptr == caml_young_alloc_end);
#ifdef MMAP_INTERVAL
{
static uintnat minor_heap_mapped_bsz = 0;
uintnat new_mapped_bsz;
new_mapped_bsz = Round_mmap_size (bsz);
void *block;
CAMLassert (caml_young_start != NULL);
if (new_mapped_bsz > minor_heap_mapped_bsz){
uintnat addbsz = new_mapped_bsz - minor_heap_mapped_bsz;
new_heap = (char *) caml_young_start - addbsz;
block = caml_mmap_heap (new_heap, addbsz, PROT_READ | PROT_WRITE,
MAP_FIXED);
if (block != new_heap){
if (minor_heap_mapped_bsz == 0){
caml_fatal_error ("cannot initialize minor heap: mmap failed\n");
}else{
caml_raise_out_of_memory ();
}
}
new_heap_base = new_heap;
}else if (new_mapped_bsz < minor_heap_mapped_bsz){
uintnat subbsz = minor_heap_mapped_bsz - new_mapped_bsz;
(void) caml_mmap_heap (caml_young_start, subbsz, PROT_NONE,
MAP_FIXED | MAP_NORESERVE);
new_heap_base = new_heap = (char *) caml_young_start + subbsz;
}else{
new_heap_base = new_heap = caml_young_base;
}
}
#else
new_heap = caml_aligned_malloc(bsz, 0, &new_heap_base);
if (new_heap == NULL) caml_raise_out_of_memory();
if (caml_page_table_add(In_young, new_heap, new_heap + size) != 0)
if (caml_page_table_add(In_young, new_heap, new_heap + bsz) != 0)
caml_raise_out_of_memory();
if (caml_young_start != NULL){
caml_page_table_remove(In_young, caml_young_start, caml_young_end);
free (caml_young_base);
}
#endif
caml_young_base = new_heap_base;
caml_young_start = (value *) new_heap;
caml_young_end = (value *) (new_heap + size);
caml_young_limit = caml_young_start;
caml_young_ptr = caml_young_end;
caml_minor_heap_wsz = Wsize_bsize (size);
caml_young_end = (value *) (new_heap + bsz);
caml_young_alloc_start = caml_young_start;
caml_young_alloc_mid = caml_young_alloc_start + Wsize_bsize (bsz) / 2;
caml_young_alloc_end = caml_young_end;
caml_young_trigger = caml_young_alloc_start;
caml_young_limit = caml_young_trigger;
caml_young_ptr = caml_young_alloc_end;
caml_minor_heap_wsz = Wsize_bsize (bsz);
reset_table (&caml_ref_table);
reset_table (&caml_weak_ref_table);
@ -232,16 +295,20 @@ void caml_empty_minor_heap (void)
value **r;
uintnat prev_alloc_words;
if (caml_young_ptr != caml_young_end){
if (caml_young_ptr != caml_young_alloc_end){
if (caml_minor_gc_begin_hook != NULL) (*caml_minor_gc_begin_hook) ();
CAML_INSTR_SETUP (tmr, "minor");
prev_alloc_words = caml_allocated_words;
caml_in_minor_collection = 1;
caml_gc_message (0x02, "<", 0);
caml_oldify_local_roots();
CAML_INSTR_TIME (tmr, "minor/local_roots");
for (r = caml_ref_table.base; r < caml_ref_table.ptr; r++){
caml_oldify_one (**r, *r);
}
CAML_INSTR_TIME (tmr, "minor/ref_table");
caml_oldify_mopup ();
CAML_INSTR_TIME (tmr, "minor/copy");
for (r = caml_weak_ref_table.base; r < caml_weak_ref_table.ptr; r++){
if (Is_block (**r) && Is_young (**r)){
if (Hd_val (**r) == 0){
@ -258,18 +325,22 @@ void caml_empty_minor_heap (void)
final_fun((value)*r);
}
}
if (caml_young_ptr < caml_young_start) caml_young_ptr = caml_young_start;
caml_stat_minor_words += caml_young_end - caml_young_ptr;
caml_young_ptr = caml_young_end;
caml_young_limit = caml_young_start;
CAML_INSTR_TIME (tmr, "minor/update_weak");
CAMLassert (caml_young_ptr >= caml_young_alloc_start);
caml_stat_minor_words += caml_young_alloc_end - caml_young_ptr;
caml_gc_clock += (double) (caml_young_alloc_end - caml_young_ptr)
/ caml_minor_heap_wsz;
caml_young_ptr = caml_young_alloc_end;
clear_table (&caml_ref_table);
clear_table (&caml_weak_ref_table);
clear_table (&caml_finalize_table);
caml_gc_message (0x02, ">", 0);
caml_in_minor_collection = 0;
caml_stat_promoted_words += caml_allocated_words - prev_alloc_words;
++ caml_stat_minor_collections;
caml_final_empty_young ();
CAML_INSTR_TIME (tmr, "minor/finalized");
caml_stat_promoted_words += caml_allocated_words - prev_alloc_words;
CAML_INSTR_INT ("minor/promoted#", caml_allocated_words - prev_alloc_words);
++ caml_stat_minor_collections;
if (caml_minor_gc_end_hook != NULL) (*caml_minor_gc_end_hook) ();
}else{
caml_final_empty_young ();
@ -277,34 +348,83 @@ void caml_empty_minor_heap (void)
#ifdef DEBUG
{
value *p;
for (p = caml_young_start; p < caml_young_end; ++p){
for (p = caml_young_alloc_start; p < caml_young_alloc_end; ++p){
*p = Debug_free_minor;
}
++ minor_gc_counter;
}
#endif
}
/* Do a minor collection and a slice of major collection, call finalisation
#ifdef CAML_INSTR
extern uintnat caml_instr_alloc_jump;
#endif
/* Do a minor collection or a slice of major collection, call finalisation
functions, etc.
Leave the minor heap empty.
Leave enough room in the minor heap to allocate at least one object.
*/
CAMLexport void caml_gc_dispatch (void)
{
value *trigger = caml_young_trigger; /* save old value of trigger */
#ifdef CAML_INSTR
CAML_INSTR_SETUP(tmr, "dispatch");
CAML_INSTR_TIME (tmr, "overhead");
CAML_INSTR_INT ("alloc/jump#", caml_instr_alloc_jump);
caml_instr_alloc_jump = 0;
#endif
if (trigger == caml_young_alloc_start || caml_requested_minor_gc){
/* The minor heap is full, we must do a minor collection. */
/* reset the pointers first because the end hooks might allocate */
caml_requested_minor_gc = 0;
caml_young_trigger = caml_young_alloc_mid;
caml_young_limit = caml_young_trigger;
caml_empty_minor_heap ();
/* The minor heap is empty, we can start a major collection. */
if (caml_gc_phase == Phase_idle) caml_major_collection_slice (-1);
CAML_INSTR_TIME (tmr, "dispatch/minor");
caml_final_do_calls ();
CAML_INSTR_TIME (tmr, "dispatch/finalizers");
while (caml_young_ptr - caml_young_alloc_start < Max_young_whsize){
/* The finalizers or the hooks have filled up the minor heap, we must
repeat the minor collection. */
caml_requested_minor_gc = 0;
caml_young_trigger = caml_young_alloc_mid;
caml_young_limit = caml_young_trigger;
caml_empty_minor_heap ();
/* The minor heap is empty, we can start a major collection. */
if (caml_gc_phase == Phase_idle) caml_major_collection_slice (-1);
CAML_INSTR_TIME (tmr, "dispatch/finalizers_minor");
}
}
if (trigger != caml_young_alloc_start || caml_requested_major_slice){
/* The minor heap is half-full, do a major GC slice. */
caml_requested_major_slice = 0;
caml_young_trigger = caml_young_alloc_start;
caml_young_limit = caml_young_trigger;
caml_major_collection_slice (-1);
CAML_INSTR_TIME (tmr, "dispatch/major");
}
}
/* For backward compatibility with Lablgtk: do a minor collection to
ensure that the minor heap is empty.
*/
CAMLexport void caml_minor_collection (void)
{
caml_empty_minor_heap ();
caml_major_collection_slice (0);
caml_force_major_slice = 0;
caml_final_do_calls ();
caml_empty_minor_heap ();
caml_requested_minor_gc = 1;
caml_gc_dispatch ();
}
CAMLexport value caml_check_urgent_gc (value extra_root)
{
CAMLparam1 (extra_root);
if (caml_force_major_slice) caml_minor_collection();
if (caml_requested_major_slice || caml_requested_minor_gc){
CAML_INSTR_INT ("force_minor/check_urgent_gc@", 1);
caml_gc_dispatch();
}
CAMLreturn (extra_root);
}
@ -316,13 +436,14 @@ void caml_realloc_ref_table (struct caml_ref_table *tbl)
if (tbl->base == NULL){
caml_alloc_table (tbl, caml_minor_heap_wsz / 8, 256);
}else if (tbl->limit == tbl->threshold){
CAML_INSTR_INT ("request_minor/realloc_ref_table@", 1);
caml_gc_message (0x08, "ref_table threshold crossed\n", 0);
tbl->limit = tbl->end;
caml_urge_major_slice ();
}else{ /* This will almost never happen with the bytecode interpreter. */
caml_request_minor_gc ();
}else{
asize_t sz;
asize_t cur_ptr = tbl->ptr - tbl->base;
Assert (caml_force_major_slice);
CAMLassert (caml_requested_minor_gc);
tbl->size *= 2;
sz = (tbl->size + tbl->reserve) * sizeof (value *);

View File

@ -17,6 +17,7 @@
#include "caml/config.h"
#include "caml/misc.h"
#include "caml/memory.h"
#include "caml/version.h"
caml_timing_hook caml_major_slice_begin_hook = NULL;
caml_timing_hook caml_major_slice_end_hook = NULL;
@ -49,7 +50,7 @@ uintnat caml_verb_gc = 0;
void caml_gc_message (int level, char *msg, uintnat arg)
{
if (level < 0 || (caml_verb_gc & level) != 0){
if ((caml_verb_gc & level) != 0){
fprintf (stderr, msg, arg);
fflush (stderr);
}
@ -195,3 +196,81 @@ int caml_runtime_warnings_active(void)
}
return 1;
}
#ifdef CAML_INSTR
/* Timers for profiling GC and allocation (experimental, Linux-only) */
#include <limits.h>
#include <sys/types.h>
#include <unistd.h>
struct CAML_INSTR_BLOCK *CAML_INSTR_LOG = NULL;
intnat CAML_INSTR_STARTTIME, CAML_INSTR_STOPTIME;
#define Get_time(p,i) ((p)->ts[(i)].tv_nsec + 1000000000 * (p)->ts[(i)].tv_sec)
void CAML_INSTR_INIT (void)
{
char *s;
CAML_INSTR_STARTTIME = 0;
s = getenv ("OCAML_INSTR_START");
if (s != NULL) CAML_INSTR_STARTTIME = atol (s);
CAML_INSTR_STOPTIME = LONG_MAX;
s = getenv ("OCAML_INSTR_STOP");
if (s != NULL) CAML_INSTR_STOPTIME = atol (s);
}
void CAML_INSTR_ATEXIT (void)
{
int i;
struct CAML_INSTR_BLOCK *p, *prev, *next;
FILE *f = NULL;
char *fname;
fname = getenv ("OCAML_INSTR_FILE");
if (fname != NULL){
char *mode = "a";
char buf [1000];
char *name = fname;
if (name[0] == '@'){
snprintf (buf, sizeof(buf), "%s.%d", name + 1, getpid ());
name = buf;
}
if (name[0] == '+'){
mode = "a";
name = name + 1;
}else if (name [0] == '>' || name[0] == '-'){
mode = "w";
name = name + 1;
}
f = fopen (name, mode);
}
if (f != NULL){
/* reverse the list */
prev = NULL;
p = CAML_INSTR_LOG;
while (p != NULL){
next = p->next;
p->next = prev;
prev = p;
p = next;
}
CAML_INSTR_LOG = prev;
fprintf (f, "==== OCAML INSTRUMENTATION DATA %s\n", OCAML_VERSION_STRING);
for (p = CAML_INSTR_LOG; p != NULL; p = p->next){
for (i = 0; i < p->index; i++){
fprintf (f, "@@ %19ld %19ld %s\n",
Get_time (p, i), Get_time(p, i+1), p->tag[i+1]);
}
if (p->tag[0][0] != '\000'){
fprintf (f, "@@ %19ld %19ld %s\n",
Get_time (p, 0), Get_time(p, p->index), p->tag[0]);
}
}
fclose (f);
}
}
#endif /* CAML_INSTR */

View File

@ -111,9 +111,13 @@ CAMLprim value caml_obj_dup(value arg)
to 0 or greater than the current size.
algorithm:
Change the length field of the header. Make up a white object
Change the length field of the header. Make up a black object
with the leftover part of the object: this is needed in the major
heap and harmless in the minor heap.
heap and harmless in the minor heap. The object cannot be white
because there may still be references to it in the ref table. By
using a black object we ensure that the ref table will be emptied
before the block is reallocated (since there must be a minor
collection within each major cycle).
[newsize] is a value encoding a number of words.
*/
@ -147,7 +151,7 @@ CAMLprim value caml_obj_truncate (value v, value newsize)
look like a pointer because there may be some references to it in
ref_table. */
Field (v, new_wosize) =
Make_header (Wosize_whsize (wosize-new_wosize), 1, Caml_white);
Make_header (Wosize_whsize (wosize-new_wosize), Abstract_tag, Caml_black);
Hd_val (v) = Make_header (new_wosize, tag, color);
return Val_unit;
}

View File

@ -27,7 +27,7 @@ CAMLexport struct caml__roots_block *caml_local_roots = NULL;
CAMLexport void (*caml_scan_roots_hook) (scanning_action f) = NULL;
/* FIXME should rename to [caml_oldify_young_roots] and synchronise with
/* FIXME should rename to [caml_oldify_minor_roots] and synchronise with
asmrun/roots.c */
/* Call [caml_oldify_one] on (at least) all the roots that point to the minor
heap. */
@ -60,23 +60,38 @@ void caml_oldify_local_roots (void)
/* Call [caml_darken] on all roots */
void caml_darken_all_roots (void)
void caml_darken_all_roots_start (void)
{
caml_do_roots (caml_darken);
caml_do_roots (caml_darken, 1);
}
void caml_do_roots (scanning_action f)
uintnat caml_incremental_roots_count = 1;
intnat caml_darken_all_roots_slice (intnat work)
{
return work;
}
/* Note, in byte-code there is only one global root, so [do_globals] is
ignored and [caml_darken_all_roots_slice] does nothing. */
void caml_do_roots (scanning_action f, int do_globals)
{
CAML_INSTR_SETUP (tmr, "major_roots");
/* Global variables */
f(caml_global_data, &caml_global_data);
CAML_INSTR_TIME (tmr, "major_roots/global");
/* The stack and the local C roots */
caml_do_local_roots(f, caml_extern_sp, caml_stack_high, caml_local_roots);
CAML_INSTR_TIME (tmr, "major_roots/local");
/* Global C roots */
caml_scan_global_roots(f);
CAML_INSTR_TIME (tmr, "major_roots/C");
/* Finalised values */
caml_final_do_strong_roots (f);
CAML_INSTR_TIME (tmr, "major_roots/finalised");
/* Hook */
if (caml_scan_roots_hook != NULL) (*caml_scan_roots_hook)(f);
CAML_INSTR_TIME (tmr, "major_roots/hook");
}
CAMLexport void caml_do_local_roots (scanning_action f, value *stack_low,

View File

@ -67,7 +67,7 @@ void caml_record_signal(int signal_number)
#ifndef NATIVE_CODE
caml_something_to_do = 1;
#else
caml_young_limit = caml_young_end;
caml_young_limit = caml_young_alloc_end;
#endif
}
@ -157,15 +157,16 @@ void caml_execute_signal(int signal_number, int in_signal_handler)
/* Arrange for a garbage collection to be performed as soon as possible */
int volatile caml_force_major_slice = 0;
int volatile caml_requested_major_slice = 0;
int volatile caml_requested_minor_gc = 0;
void caml_urge_major_slice (void)
void caml_request_major_slice (void)
{
caml_force_major_slice = 1;
caml_requested_major_slice = 1;
#ifndef NATIVE_CODE
caml_something_to_do = 1;
#else
caml_young_limit = caml_young_end;
caml_young_limit = caml_young_alloc_end;
/* This is only moderately effective on ports that cache [caml_young_limit]
in a register, since [caml_modify] is called directly, not through
[caml_c_call], so it may take a while before the register is reloaded
@ -173,6 +174,17 @@ void caml_urge_major_slice (void)
#endif
}
void caml_request_minor_gc (void)
{
caml_requested_minor_gc = 1;
#ifndef NATIVE_CODE
caml_something_to_do = 1;
#else
caml_young_limit = caml_young_alloc_end;
/* Same remark as above in [caml_request_major_slice]. */
#endif
}
/* OS-independent numbering of signals */
#ifndef SIGABRT

View File

@ -287,9 +287,13 @@ CAMLexport void caml_main(char **argv)
caml_external_raise = NULL;
/* Determine options and position of bytecode file */
#ifdef DEBUG
caml_verb_gc = 0xBF;
caml_verb_gc = 0x3F;
#endif
caml_parse_ocamlrunparam();
#ifdef DEBUG
caml_gc_message (-1, "### OCaml runtime: debug mode ###\n", 0);
#endif
pos = 0;
/* First, try argv[0] (when ocamlrun is called by a bytecode program) */
@ -326,7 +330,7 @@ CAMLexport void caml_main(char **argv)
/* Initialize the abstract machine */
caml_init_gc (caml_init_minor_heap_wsz, caml_init_heap_wsz,
caml_init_heap_chunk_sz, caml_init_percent_free,
caml_init_max_percent_free);
caml_init_max_percent_free, caml_init_major_window);
caml_init_stack (caml_init_max_stack_wsz);
caml_init_atom_table();
caml_init_backtrace();
@ -410,7 +414,7 @@ CAMLexport void caml_startup_code(
/* Initialize the abstract machine */
caml_init_gc (caml_init_minor_heap_wsz, caml_init_heap_wsz,
caml_init_heap_chunk_sz, caml_init_percent_free,
caml_init_max_percent_free);
caml_init_max_percent_free, caml_init_major_window);
caml_init_stack (caml_init_max_stack_wsz);
caml_init_atom_table();
caml_init_backtrace();

View File

@ -42,6 +42,7 @@ uintnat caml_init_minor_heap_wsz = Minor_heap_def;
uintnat caml_init_heap_chunk_sz = Heap_chunk_def;
uintnat caml_init_heap_wsz = Init_heap_def;
uintnat caml_init_max_stack_wsz = Max_stack_def;
uintnat caml_init_major_window = Major_window_def;
extern int caml_parser_trace;
uintnat caml_trace_level = 0;
@ -73,6 +74,7 @@ void caml_parse_ocamlrunparam(void)
case 'a': scanmult (opt, &p); caml_set_allocation_policy (p); break;
case 'b': scanmult (opt, &p); caml_record_backtrace(Val_bool (p)); break;
case 'h': scanmult (opt, &caml_init_heap_wsz); break;
case 'H': scanmult (opt, &caml_use_huge_pages); break;
case 'i': scanmult (opt, &caml_init_heap_chunk_sz); break;
case 'l': scanmult (opt, &caml_init_max_stack_wsz); break;
case 'o': scanmult (opt, &caml_init_percent_free); break;
@ -82,6 +84,7 @@ void caml_parse_ocamlrunparam(void)
case 's': scanmult (opt, &caml_init_minor_heap_wsz); break;
case 't': scanmult (opt, &caml_trace_level); break;
case 'v': scanmult (opt, &caml_verb_gc); break;
case 'w': scanmult (opt, &caml_init_major_window); break;
case 'W': scanmult (opt, &caml_runtime_warnings); break;
}
while (*opt != '\0'){

View File

@ -44,14 +44,15 @@
#include "caml/alloc.h"
#include "caml/debugger.h"
#include "caml/fail.h"
#include "caml/gc_ctrl.h"
#include "caml/instruct.h"
#include "caml/io.h"
#include "caml/misc.h"
#include "caml/mlvalues.h"
#include "caml/osdeps.h"
#include "caml/signals.h"
#include "caml/stacks.h"
#include "caml/sys.h"
#include "caml/gc_ctrl.h"
#include "caml/io.h"
static char * error_message(void)
{
@ -135,6 +136,7 @@ CAMLprim value caml_sys_exit(value retcode)
#ifndef NATIVE_CODE
caml_debugger(PROGRAM_EXIT);
#endif
CAML_INSTR_ATEXIT ();
exit(Int_val(retcode));
return Val_unit;
}

View File

@ -51,11 +51,7 @@ static void do_set (value ar, mlsize_t offset, value v)
value old = Field (ar, offset);
Field (ar, offset) = v;
if (!(Is_block (old) && Is_young (old))){
if (caml_weak_ref_table.ptr >= caml_weak_ref_table.limit){
CAMLassert (caml_weak_ref_table.ptr == caml_weak_ref_table.limit);
caml_realloc_ref_table (&caml_weak_ref_table);
}
*caml_weak_ref_table.ptr++ = &Field (ar, offset);
add_to_ref_table (&caml_weak_ref_table, &Field (ar, offset));
}
}else{
Field (ar, offset) = v;

View File

@ -0,0 +1,49 @@
/***********************************************************************/
/* */
/* OCaml */
/* */
/* Damien Doligez, Jane Street Group, LLC */
/* */
/* Copyright 2015 Institut National de Recherche en Informatique et */
/* en Automatique. All rights reserved. This file is distributed */
/* under the terms of the GNU Library General Public License, with */
/* the special exception on linking described in file ../../LICENSE. */
/* */
/***********************************************************************/
#include <sys/mman.h>
#include <stdio.h>
#include <stdlib.h>
#define huge_page_size (4 * 1024 * 1024)
/* Test for the possible availability of huge pages. Answer yes
if the OS knows about huge pages, even if they are not available
on the build machine at configure time, because (on Linux) huge
pages can be activated and deactivated easily while the system
is running.
*/
int main (int argc, char *argv[]){
void *block;
char *p;
int i, res;
block = mmap (NULL, huge_page_size, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB,
-1, 0);
if (block == MAP_FAILED){
block = mmap (NULL, huge_page_size, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS,
-1, 0);
}
if (block == MAP_FAILED){
perror ("mmap");
return 3;
}
/*printf ("block = %p\n", block);*/
p = (char *) block;
for (i = 0; i < huge_page_size; i += 4096){
p[i] = (char) i;
}
return 0;
}

18
configure vendored
View File

@ -40,6 +40,7 @@ dl_defs=''
verbose=no
with_curses=yes
debugruntime=noruntimed
with_instrumented_runtime=false
with_sharedlibs=yes
partialld="ld -r"
with_debugger=ocamldebugger
@ -144,6 +145,8 @@ while : ; do
verbose=yes;;
-with-debug-runtime|--with-debug-runtime)
debugruntime=runtimed;;
-with-instrumented-runtime|--with-instrumented-runtime)
with_instrumented_runtime=true;;
-no-debugger|--no-debugger)
with_debugger="";;
-no-ocamldoc|--no-ocamldoc)
@ -1687,6 +1690,16 @@ if $no_naked_pointers; then
echo "#define NO_NAKED_POINTERS" >> m.h
fi
# Check for mmap support for huge pages and contiguous heap
if sh ./runtest mmap-huge.c; then
has_huge_pages=true
echo "#define HAS_HUGE_PAGES" >>s.h
echo "#define HUGE_PAGE_SIZE (4 * 1024 * 1024)" >>s.h
inf "mmap supports huge pages"
else
has_huge_pages=false
fi
# Finish generated files
cclibs="$cclibs $mathlib"
@ -1755,6 +1768,7 @@ if $shared_libraries_supported; then
else
echo "SHARED=noshared" >>Makefile
fi
echo "RUNTIMEI=${with_instrumented_runtime}" >>Makefile
echo "WITH_DEBUGGER=${with_debugger}" >>Makefile
echo "WITH_OCAMLDOC=${with_ocamldoc}" >>Makefile
echo "WITH_OCAMLBUILD=${with_ocamlbuild}" >>Makefile
@ -1845,6 +1859,10 @@ if test "$debugruntime" = "runtimed"; then
inf "Debug runtime will be compiled and installed"
fi
if $with_instrumented_runtime; then
inf "Instrumented runtime will be compiled and installed"
fi
inf "Additional libraries supported:"
inf " $otherlibraries"

View File

@ -16,8 +16,8 @@ int64ops.cmi :
lexer.cmi : parser.cmi
loadprinter.cmi : ../parsing/longident.cmi dynlink.cmi
parameters.cmi :
parser_aux.cmi : primitives.cmi ../parsing/longident.cmi
parser.cmi : parser_aux.cmi ../parsing/longident.cmi
parser_aux.cmi : primitives.cmi ../parsing/longident.cmi
pattern_matching.cmi : ../typing/typedtree.cmi parser_aux.cmi debugcom.cmi
pos.cmi : ../bytecomp/instruct.cmi
primitives.cmi : $(UNIXDIR)/unix.cmi

View File

@ -3,8 +3,8 @@ compact.cmi : lexgen.cmi
cset.cmi :
lexer.cmi : parser.cmi
lexgen.cmi : syntax.cmi
outputbis.cmi : syntax.cmi lexgen.cmi common.cmi
output.cmi : syntax.cmi lexgen.cmi compact.cmi common.cmi
outputbis.cmi : syntax.cmi lexgen.cmi common.cmi
parser.cmi : syntax.cmi
syntax.cmi : cset.cmi
table.cmi :
@ -22,10 +22,10 @@ main.cmo : syntax.cmi parser.cmi outputbis.cmi output.cmi lexgen.cmi \
lexer.cmi cset.cmi compact.cmi common.cmi
main.cmx : syntax.cmx parser.cmx outputbis.cmx output.cmx lexgen.cmx \
lexer.cmx cset.cmx compact.cmx common.cmx
outputbis.cmo : lexgen.cmi common.cmi outputbis.cmi
outputbis.cmx : lexgen.cmx common.cmx outputbis.cmi
output.cmo : lexgen.cmi compact.cmi common.cmi output.cmi
output.cmx : lexgen.cmx compact.cmx common.cmx output.cmi
outputbis.cmo : lexgen.cmi common.cmi outputbis.cmi
outputbis.cmx : lexgen.cmx common.cmx outputbis.cmi
parser.cmo : syntax.cmi cset.cmi parser.cmi
parser.cmx : syntax.cmx cset.cmx parser.cmi
syntax.cmo : cset.cmi syntax.cmi

View File

@ -39,8 +39,10 @@ expr:
| expr '::' expr
| '[' expr { ';' expr } [';'] ']'
| '[|' expr { ';' expr } [';'] '|]'
| '{' field '=' expr { ';' field '=' expr } [';'] '}'
| '{' expr 'with' field '=' expr { ';' field '=' expr } [';'] '}'
| '{' field [':' typexpr] '=' expr%
{ ';' field [':' typexpr] '=' expr } [';'] '}'
| '{' expr 'with' field [':' typexpr] '=' expr%
{ ';' field [':' typexpr] '=' expr } [';'] '}'
| expr {{ argument }}
| prefix-symbol expr
| '-' expr
@ -58,7 +60,7 @@ expr:
| expr ';' expr
| 'match' expr 'with' pattern-matching
| 'function' pattern-matching
| 'fun' {{ parameter }} '->' expr
| 'fun' {{ parameter }} [ ':' typexpr ] '->' expr
| 'try' expr 'with' pattern-matching
| 'let' ['rec'] let-binding { 'and' let-binding } 'in' expr
| 'new' class-path
@ -254,6 +256,26 @@ This expression is equivalent to:
@"fun" parameter_1 "->" \ldots "fun" parameter_n "->" expr@
\end{center}
An optional type constraint @typexpr@ can be added before "->" to enforce
the type of the result to be compatible with the constraint @typexpr@:
\begin{center}
@"fun" parameter_1 \ldots parameter_n ":" typexpr "->" expr@
\end{center}
is equivalent to
\begin{center}
@"fun" parameter_1 "->" \ldots "fun" parameter_n "->" %
(expr ":" typexpr )@
\end{center}
Beware of the small syntactic difference between a type constraint on
the last parameter
\begin{center}
@"fun" parameter_1 \ldots (parameter_n":"typexpr)"->" expr @
\end{center}
and one on the result
\begin{center}
@"fun" parameter_1 \ldots parameter_n":" typexpr "->" expr @
\end{center}
The parameter patterns @"~"lab@ and @"~("lab [":" typ]")"@
are shorthands for respectively @"~"lab":"lab@ and
@"~"lab":("lab [":" typ]")"@, and similarly for their optional
@ -534,7 +556,10 @@ The fields @field_1@ to @field_n@ must all belong to the same record
type; each field of this record type must appear exactly
once in the record expression, though they can appear in any
order. The order in which @expr_1@ to @expr_n@ are evaluated is not
specified.
specified. Optional type constraints can be added after each field
@'{' field_1 ':' typexpr_1 '=' expr_1 ';'%
\ldots ';' field_n ':' typexpr_n '=' expr_n '}'@
to force the type of @field_k@ to be compatible with @typexpr_k@.
The expression
@"{" expr "with" field_1 "=" expr_1 ";" \ldots ";" field_n "=" expr_n "}"@
@ -542,7 +567,11 @@ builds a fresh record with fields @field_1 \ldots field_n@ equal to
@expr_1 \ldots expr_n@, and all other fields having the same value as
in the record @expr@. In other terms, it returns a shallow copy of
the record @expr@, except for the fields @field_1 \ldots field_n@,
which are initialized to @expr_1 \ldots expr_n@.
which are initialized to @expr_1 \ldots expr_n@. As previously, it is
possible to add an optional type constraint on each field being updated
with
@"{" expr "with" field_1 ':' typexpr_1 "=" expr_1 ";" %
\ldots ";" field_n ':' typexpr_n "=" expr_n "}"@.
The expression @expr_1 '.' field@ evaluates @expr_1@ to a record
value, and returns the value associated to @field@ in this record

View File

@ -417,9 +417,9 @@ expr:
When the body of a local open expression is delimited by @'[' ']'@, @'[|' '|]'@, @'{' '}'@, or @'{<' '>}'@, the parentheses can be omitted. For example, @module-path'.['expr']'@ is equivalent to @module-path'.(['expr'])'@, and @module-path'.[|' expr '|]'@ is equivalent to @module-path'.([|' expr '|])'@.
\section{Record notations}
\section{Record and object notations}
(Introduced in OCaml 3.12)
(Introduced in OCaml 3.12, object copy notation added in Ocaml 4.03)
\begin{syntax}
pattern:
@ -430,13 +430,14 @@ expr:
...
| '{' field ['=' expr] { ';' field ['=' expr] } [';'] '}'
| '{' expr 'with' field ['=' expr] { ';' field ['=' expr] } [';'] '}'
| '{' '<' expr 'with' field ['=' expr] { ';' field ['=' expr] } [';'] '>' '}'
\end{syntax}
In a record pattern or a record construction expression, a single
identifier @id@ stands for @id '=' id@, and a qualified identifier
In a record pattern, a record construction expression or an object copy expression,
a single identifier @id@ stands for @id '=' id@, and a qualified identifier
@module-path '.' id@ stands for @module-path '.' id '=' id@.
For example, assuming
the record type
For example, assuming the record type
\begin{verbatim}
type point = { x: float; y: float }
\end{verbatim}
@ -446,6 +447,15 @@ has been declared, the following expressions are equivalent:
let x = 1 and y = 2 in { x; y }
let x = 1 and y = 2 in { x = x; y }
\end{verbatim}
On the object side, all following methods are equivalent:
\begin{verbatim}
object
val x=0. val y=0. val z=0.
method f_0 x y = {< x; y >}
method f_1 x y = {< x = x; y >}
method f_2 x y = {< x=x ; y = y >}
end
\end{verbatim}
Likewise, the following functions are equivalent:
\begin{verbatim}
fun {x = x; y = y} -> x + y
@ -511,12 +521,12 @@ polymorphic.
\ikwd{type\@\texttt{type}}
\ikwd{fun\@\texttt{fun}}
(Introduced in OCaml 3.12)
(Introduced in OCaml 3.12, short syntax added in 4.03)
\begin{syntax}
parameter:
...
| '(' "type" typeconstr-name ')'
| '(' "type" {{typeconstr-name}} ')'
\end{syntax}
The expression @"fun" '(' "type" typeconstr-name ')' "->" expr@ introduces a
@ -535,8 +545,16 @@ and even use the alternative syntax for declaring functions:
\begin{verbatim}
let f (type t) (foo : t list) = ...
\end{verbatim}
If several locally abstract types need to be introduced, it is possible to use
the syntax
@"fun" '(' "type" typeconstr-name_1 \ldots typeconstr-name_n ')' "->" expr@
as syntactic sugar for @"fun" '(' "type" typeconstr-name_1 ')' "->" \ldots "->"
'(' "type" typeconstr-name_n ')' "->" expr@. For instance,
\begin{verbatim}
let f = fun (type t u v) -> (foo : (t * u * v) list) -> ...
\end{verbatim}
This construction is useful because the type constructor it introduces
This construction is useful because the type constructors it introduces
can be used in places where a type variable is not allowed. For
instance, one can use it to define an exception in a local module
within a polymorphic function.

View File

@ -23,6 +23,7 @@ module-type:
modtype-path
| 'sig' { specification [';;'] } 'end'
| 'functor' '(' module-name ':' module-type ')' '->' module-type
| module-type '->' module-type
| module-type 'with' mod-constraint { 'and' mod-constraint }
| '(' module-type ')'
;
@ -245,9 +246,13 @@ is the type of functors (functions from modules to modules) that take
as argument a module of type @module-type_1@ and return as result a
module of type @module-type_2@. The module type @module-type_2@ can
use the name @module-name@ to refer to type components of the actual
argument of the functor. No restrictions are placed on the type of the
functor argument; in particular, a functor may take another functor as
argument (``higher-order'' functor).
argument of the functor. If the type @module-type_2@ does not
depend on type components of @module-name@, the module type expression
can be simplified with the alternative short syntax
@ module-type_1 '->' module-type_2 @.
No restrictions are placed on the type of the functor argument; in
particular, a functor may take another functor as argument
(``higher-order'' functor).
\subsection{The "with" operator}

View File

@ -15,7 +15,8 @@ pattern:
| "`"tag-name pattern
| "#"typeconstr
| pattern {{ ',' pattern }}
| '{' field '=' pattern { ';' field '=' pattern } [ ';' ] '}'
| '{' field [':' typexpr] '=' pattern%
{ ';' field [':' typexpr] '=' pattern } [ ';' ] '}'
| '[' pattern { ';' pattern } [ ';' ] ']'
| pattern '::' pattern
| '[|' pattern { ';' pattern } [ ';' ] '|]'
@ -140,7 +141,10 @@ pattern_n "}"@ matches records that define at least the fields
@field_i@ matches the pattern @pattern_i@, for \fromoneto{i}{n}.
The record value can define more fields than @field_1@ \ldots
@field_n@; the values associated to these extra fields are not taken
into account for matching.
into account for matching. Optional type constraints can be added field
by field with @"{" field_1 ":" typexpr_1 "=" pattern_1 ";"%
\ldots ";"field_n ":" typexpr_n "=" pattern_n "}"@ to force the type
of @field_k@ to be compatible with @typexpr_k@.
\subsubsection*{Array patterns}

View File

@ -47,19 +47,19 @@ in type constraints over patterns and expressions.
\subsubsection*{Type variables}
The type expression @"'" ident@ stands for the type variable named
@ident@. The type expression @"_"@ stands for an anonymous type variable.
In data type definitions, type variables are names for the
data type parameters. In type constraints, they represent unspecified
types that can be instantiated by any type to satisfy the type
constraint. In general the scope of a named type variable is the
whole top-level phrase where it appears, and it can only be
generalized when leaving
this scope. Anonymous variables have no such restriction.
In the following cases, the scope of named type variables is
restricted to the type expression where they appear: 1) for universal
(explicitly polymorphic) type variables; 2) for type variables that
only appear in public method specifications (as those variables will
be made universal, as described in section~\ref{sec-methspec});
@ident@. The type expression @"_"@ stands for either an anonymous type
variable or anonymous type parameters. In data type definitions, type
variables are names for the data type parameters. In type constraints,
they represent unspecified types that can be instantiated by any type
to satisfy the type constraint. In general the scope of a named type
variable is the whole top-level phrase where it appears, and it can
only be generalized when leaving this scope. Anonymous variables have
no such restriction. In the following cases, the scope of named type
variables is restricted to the type expression where they appear:
1) for universal (explicitly polymorphic) type variables;
2) for type variables that only appear in public method specifications
(as those variables will be made universal, as described in
section~\ref{sec-methspec});
3) for variables used as aliases, when the type they are aliased to
would be invalid in the scope of the enclosing definition ({\it i.e.}
when it contains free universal type variables, or locally
@ -104,6 +104,11 @@ The type expression @(typexpr_1,\ldots,typexpr_n) typeconstr@, where
application of the $n$-ary type constructor @typeconstr@ to the types
@typexpr_1@ through @typexpr_n@.
In the type expression @ "_" typeconstr @, the anonymous type expression
@ "_" @ stands in for anonymous type parameters and is equivalent to
@ ("_", \ldots,"_") @ with as many repetitions of "_" as the arity of
@typeconstr@.
\subsubsection*{Aliased and recursive types}
\ikwd{as\@\texttt{as}}

View File

@ -317,10 +317,12 @@ is only used when a more detailed specification is needed.
Variants as presented in section~\ref{s:tut-recvariants} are a
powerful tool to build data structures and algorithms. However they
sometimes lack flexibility when used in modular programming. This is
due to the fact every constructor reserves a name to be used with a
unique type. One cannot use the same name in another type, or consider
a value of some type to belong to some other type with more
constructors.
due to the fact that every constructor is assigned to an unique type
when defined and used. Even if the same name appears in the definition
of multiple types, the constructor itself belongs to only one type.
Therefore, one cannot decide that a given constructor belongs to
multiple types, or consider a value of some type to belong to some
other type with more constructors.
With polymorphic variants, this original assumption is removed. That
is, a variant tag does not belong to any type in particular, the type

View File

@ -8,9 +8,9 @@ exit_codes.cmi :
fda.cmi : slurp.cmi
findlib.cmi : signatures.cmi command.cmi
flags.cmi : tags.cmi command.cmi
glob.cmi : signatures.cmi glob_ast.cmi bool.cmi
glob_ast.cmi : bool.cmi
glob_lexer.cmi : glob_ast.cmi
glob.cmi : signatures.cmi glob_ast.cmi bool.cmi
hooks.cmi :
hygiene.cmi : slurp.cmi
lexers.cmi : loc.cmi glob.cmi
@ -20,17 +20,17 @@ main.cmi :
my_std.cmi : signatures.cmi
my_unix.cmi :
ocaml_arch.cmi : signatures.cmi command.cmi
ocamlbuild_executor.cmi :
ocamlbuildlight.cmi :
ocamlbuild.cmi :
ocamlbuild_plugin.cmi :
ocamlbuild_unix_plugin.cmi :
ocamlbuild_where.cmi :
ocaml_compiler.cmi : tags.cmi rule.cmi pathname.cmi command.cmi
ocaml_dependencies.cmi : pathname.cmi
ocaml_specific.cmi :
ocaml_tools.cmi : tags.cmi rule.cmi pathname.cmi command.cmi
ocaml_utils.cmi : tags.cmi pathname.cmi command.cmi
ocamlbuild.cmi :
ocamlbuild_executor.cmi :
ocamlbuild_plugin.cmi :
ocamlbuild_unix_plugin.cmi :
ocamlbuild_where.cmi :
ocamlbuildlight.cmi :
options.cmi : slurp.cmi signatures.cmi command.cmi
param_tags.cmi : tags.cmi loc.cmi
pathname.cmi : signatures.cmi
@ -75,12 +75,12 @@ findlib.cmx : my_unix.cmx my_std.cmx lexers.cmx const.cmx command.cmx \
findlib.cmi
flags.cmo : tags.cmi param_tags.cmi log.cmi command.cmi bool.cmi flags.cmi
flags.cmx : tags.cmx param_tags.cmx log.cmx command.cmx bool.cmx flags.cmi
glob.cmo : my_std.cmi glob_lexer.cmi glob_ast.cmi bool.cmi glob.cmi
glob.cmx : my_std.cmx glob_lexer.cmx glob_ast.cmx bool.cmx glob.cmi
glob_ast.cmo : bool.cmi glob_ast.cmi
glob_ast.cmx : bool.cmx glob_ast.cmi
glob_lexer.cmo : glob_ast.cmi bool.cmi glob_lexer.cmi
glob_lexer.cmx : glob_ast.cmx bool.cmx glob_lexer.cmi
glob.cmo : my_std.cmi glob_lexer.cmi glob_ast.cmi bool.cmi glob.cmi
glob.cmx : my_std.cmx glob_lexer.cmx glob_ast.cmx bool.cmx glob.cmi
hooks.cmo : hooks.cmi
hooks.cmx : hooks.cmi
hygiene.cmo : slurp.cmi shell.cmi pathname.cmi options.cmi my_std.cmi \
@ -111,22 +111,6 @@ my_unix.cmo : my_std.cmi my_unix.cmi
my_unix.cmx : my_std.cmx my_unix.cmi
ocaml_arch.cmo : pathname.cmi my_std.cmi command.cmi ocaml_arch.cmi
ocaml_arch.cmx : pathname.cmx my_std.cmx command.cmx ocaml_arch.cmi
ocamlbuild_config.cmo :
ocamlbuild_config.cmx :
ocamlbuild_executor.cmo : ocamlbuild_executor.cmi
ocamlbuild_executor.cmx : ocamlbuild_executor.cmi
ocamlbuildlight.cmo : ocamlbuildlight.cmi
ocamlbuildlight.cmx : ocamlbuildlight.cmi
ocamlbuild.cmo : ocamlbuild_unix_plugin.cmi ocamlbuild.cmi
ocamlbuild.cmx : ocamlbuild_unix_plugin.cmx ocamlbuild.cmi
ocamlbuild_plugin.cmo : ocamlbuild_plugin.cmi
ocamlbuild_plugin.cmx : ocamlbuild_plugin.cmi
ocamlbuild_unix_plugin.cmo : ocamlbuild_executor.cmi my_unix.cmi my_std.cmi \
exit_codes.cmi ocamlbuild_unix_plugin.cmi
ocamlbuild_unix_plugin.cmx : ocamlbuild_executor.cmx my_unix.cmx my_std.cmx \
exit_codes.cmx ocamlbuild_unix_plugin.cmi
ocamlbuild_where.cmo : ocamlbuild_config.cmo ocamlbuild_where.cmi
ocamlbuild_where.cmx : ocamlbuild_config.cmx ocamlbuild_where.cmi
ocaml_compiler.cmo : tools.cmi tags.cmi rule.cmi resource.cmi pathname.cmi \
options.cmi ocaml_utils.cmi ocaml_dependencies.cmi ocaml_arch.cmi \
my_std.cmi log.cmi command.cmi ocaml_compiler.cmi
@ -157,6 +141,22 @@ ocaml_utils.cmo : tools.cmi tags.cmi pathname.cmi param_tags.cmi options.cmi \
ocaml_utils.cmx : tools.cmx tags.cmx pathname.cmx param_tags.cmx options.cmx \
my_std.cmx log.cmx lexers.cmx flags.cmx const.cmx command.cmx \
ocaml_utils.cmi
ocamlbuild.cmo : ocamlbuild_unix_plugin.cmi ocamlbuild.cmi
ocamlbuild.cmx : ocamlbuild_unix_plugin.cmx ocamlbuild.cmi
ocamlbuild_config.cmo :
ocamlbuild_config.cmx :
ocamlbuild_executor.cmo : ocamlbuild_executor.cmi
ocamlbuild_executor.cmx : ocamlbuild_executor.cmi
ocamlbuild_plugin.cmo : ocamlbuild_plugin.cmi
ocamlbuild_plugin.cmx : ocamlbuild_plugin.cmi
ocamlbuild_unix_plugin.cmo : ocamlbuild_executor.cmi my_unix.cmi my_std.cmi \
exit_codes.cmi ocamlbuild_unix_plugin.cmi
ocamlbuild_unix_plugin.cmx : ocamlbuild_executor.cmx my_unix.cmx my_std.cmx \
exit_codes.cmx ocamlbuild_unix_plugin.cmi
ocamlbuild_where.cmo : ocamlbuild_config.cmo ocamlbuild_where.cmi
ocamlbuild_where.cmx : ocamlbuild_config.cmx ocamlbuild_where.cmi
ocamlbuildlight.cmo : ocamlbuildlight.cmi
ocamlbuildlight.cmx : ocamlbuildlight.cmi
options.cmo : shell.cmi ocamlbuild_where.cmi ocamlbuild_config.cmo \
my_std.cmi log.cmi lexers.cmi const.cmo command.cmi options.cmi
options.cmx : shell.cmx ocamlbuild_where.cmx ocamlbuild_config.cmx \

View File

@ -1,3 +1,11 @@
odoc.cmo : ../typing/typedtree.cmi odoc_messages.cmo odoc_info.cmi \
odoc_global.cmi odoc_gen.cmi odoc_config.cmi odoc_args.cmi \
odoc_analyse.cmi ../utils/misc.cmi ../utils/config.cmi \
../utils/clflags.cmi
odoc.cmx : ../typing/typedtree.cmx odoc_messages.cmx odoc_info.cmx \
odoc_global.cmx odoc_gen.cmx odoc_config.cmx odoc_args.cmx \
odoc_analyse.cmx ../utils/misc.cmx ../utils/config.cmx \
../utils/clflags.cmx
odoc_analyse.cmo : ../utils/warnings.cmi ../typing/types.cmi \
../typing/typemod.cmi ../typing/typedtree.cmi ../parsing/syntaxerr.cmi \
../driver/pparse.cmi ../parsing/parse.cmi odoc_types.cmi odoc_text.cmi \
@ -44,8 +52,6 @@ odoc_class.cmo : ../typing/types.cmi odoc_value.cmo odoc_types.cmi \
odoc_parameter.cmo odoc_name.cmi
odoc_class.cmx : ../typing/types.cmx odoc_value.cmx odoc_types.cmx \
odoc_parameter.cmx odoc_name.cmx
odoc_comments_global.cmo : odoc_comments_global.cmi
odoc_comments_global.cmx : odoc_comments_global.cmi
odoc_comments.cmo : odoc_types.cmi odoc_text.cmi odoc_see_lexer.cmo \
odoc_parser.cmi odoc_misc.cmi odoc_messages.cmo odoc_merge.cmi \
odoc_lexer.cmo odoc_global.cmi odoc_cross.cmi odoc_comments_global.cmi \
@ -54,6 +60,8 @@ odoc_comments.cmx : odoc_types.cmx odoc_text.cmx odoc_see_lexer.cmx \
odoc_parser.cmx odoc_misc.cmx odoc_messages.cmx odoc_merge.cmx \
odoc_lexer.cmx odoc_global.cmx odoc_cross.cmx odoc_comments_global.cmx \
odoc_comments.cmi
odoc_comments_global.cmo : odoc_comments_global.cmi
odoc_comments_global.cmx : odoc_comments_global.cmi
odoc_config.cmo : ../utils/config.cmi odoc_config.cmi
odoc_config.cmx : ../utils/config.cmx odoc_config.cmi
odoc_control.cmo :
@ -144,14 +152,6 @@ odoc_misc.cmo : ../typing/types.cmi ../typing/predef.cmi ../typing/path.cmi \
odoc_misc.cmx : ../typing/types.cmx ../typing/predef.cmx ../typing/path.cmx \
odoc_types.cmx odoc_messages.cmx ../parsing/longident.cmx \
../typing/ctype.cmx ../typing/btype.cmx odoc_misc.cmi
odoc.cmo : ../typing/typedtree.cmi odoc_messages.cmo odoc_info.cmi \
odoc_global.cmi odoc_gen.cmi odoc_config.cmi odoc_args.cmi \
odoc_analyse.cmi ../utils/misc.cmi ../utils/config.cmi \
../utils/clflags.cmi
odoc.cmx : ../typing/typedtree.cmx odoc_messages.cmx odoc_info.cmx \
odoc_global.cmx odoc_gen.cmx odoc_config.cmx odoc_args.cmx \
odoc_analyse.cmx ../utils/misc.cmx ../utils/config.cmx \
../utils/clflags.cmx
odoc_module.cmo : ../typing/types.cmi odoc_value.cmo odoc_types.cmi \
odoc_type.cmo odoc_name.cmi odoc_extension.cmo odoc_exception.cmo \
odoc_class.cmo
@ -214,12 +214,12 @@ odoc_texi.cmo : ../typing/types.cmi odoc_to_text.cmo odoc_messages.cmo \
odoc_info.cmi ../parsing/asttypes.cmi
odoc_texi.cmx : ../typing/types.cmx odoc_to_text.cmx odoc_messages.cmx \
odoc_info.cmx ../parsing/asttypes.cmi
odoc_text_lexer.cmo : odoc_text_parser.cmi odoc_misc.cmi
odoc_text_lexer.cmx : odoc_text_parser.cmx odoc_misc.cmx
odoc_text.cmo : odoc_types.cmi odoc_text_parser.cmi odoc_text_lexer.cmo \
odoc_text.cmi
odoc_text.cmx : odoc_types.cmx odoc_text_parser.cmx odoc_text_lexer.cmx \
odoc_text.cmi
odoc_text_lexer.cmo : odoc_text_parser.cmi odoc_misc.cmi
odoc_text_lexer.cmx : odoc_text_parser.cmx odoc_misc.cmx
odoc_text_parser.cmo : odoc_types.cmi odoc_misc.cmi odoc_text_parser.cmi
odoc_text_parser.cmx : odoc_types.cmx odoc_misc.cmx odoc_text_parser.cmi
odoc_to_text.cmo : odoc_module.cmo odoc_messages.cmo odoc_info.cmi
@ -238,8 +238,8 @@ odoc_analyse.cmi : odoc_module.cmo odoc_global.cmi
odoc_args.cmi : odoc_gen.cmi
odoc_ast.cmi : ../typing/types.cmi ../typing/typedtree.cmi \
../parsing/parsetree.cmi odoc_sig.cmi odoc_name.cmi odoc_module.cmo
odoc_comments_global.cmi :
odoc_comments.cmi : odoc_types.cmi odoc_module.cmo
odoc_comments_global.cmi :
odoc_config.cmi :
odoc_cross.cmi : odoc_types.cmi odoc_module.cmo
odoc_dag2html.cmi : odoc_info.cmi

View File

@ -1,27 +1,28 @@
bigarray_stubs.o: bigarray_stubs.c ../../byterun/caml/alloc.h \
../../byterun/caml/misc.h ../../byterun/caml/config.h \
../../byterun/caml/../../config/m.h ../../byterun/caml/../../config/s.h \
../../byterun/caml/mlvalues.h bigarray.h ../../byterun/caml/config.h \
../../byterun/caml/mlvalues.h ../../byterun/caml/custom.h \
../../byterun/caml/fail.h ../../byterun/caml/intext.h \
../../byterun/caml/io.h ../../byterun/caml/hash.h \
../../byterun/caml/memory.h ../../byterun/caml/gc.h \
../../byterun/caml/major_gc.h ../../byterun/caml/freelist.h \
../../byterun/caml/minor_gc.h ../../byterun/caml/address_class.h \
../../byterun/caml/signals.h
../../byterun/caml/misc.h ../../byterun/caml/config.h \
../../byterun/caml/../../config/m.h ../../byterun/caml/../../config/s.h \
../../byterun/caml/mlvalues.h bigarray.h ../../byterun/caml/config.h \
../../byterun/caml/mlvalues.h ../../byterun/caml/custom.h \
../../byterun/caml/fail.h ../../byterun/caml/intext.h \
../../byterun/caml/io.h ../../byterun/caml/hash.h \
../../byterun/caml/memory.h ../../byterun/caml/gc.h \
../../byterun/caml/major_gc.h ../../byterun/caml/freelist.h \
../../byterun/caml/minor_gc.h ../../byterun/caml/address_class.h \
../../byterun/caml/signals.h
mmap_unix.o: mmap_unix.c bigarray.h ../../byterun/caml/config.h \
../../byterun/caml/../../config/m.h ../../byterun/caml/../../config/s.h \
../../byterun/caml/mlvalues.h ../../byterun/caml/config.h \
../../byterun/caml/misc.h ../../byterun/caml/custom.h \
../../byterun/caml/mlvalues.h ../../byterun/caml/fail.h \
../../byterun/caml/io.h ../../byterun/caml/sys.h \
../../byterun/caml/signals.h
../../byterun/caml/../../config/m.h ../../byterun/caml/../../config/s.h \
../../byterun/caml/mlvalues.h ../../byterun/caml/config.h \
../../byterun/caml/misc.h ../../byterun/caml/custom.h \
../../byterun/caml/mlvalues.h ../../byterun/caml/fail.h \
../../byterun/caml/io.h ../../byterun/caml/sys.h \
../../byterun/caml/signals.h
mmap_win32.o: mmap_win32.c bigarray.h ../../byterun/caml/config.h \
../../byterun/caml/../../config/m.h ../../byterun/caml/../../config/s.h \
../../byterun/caml/mlvalues.h ../../byterun/caml/config.h \
../../byterun/caml/misc.h ../../byterun/caml/alloc.h \
../../byterun/caml/mlvalues.h ../../byterun/caml/custom.h \
../../byterun/caml/fail.h ../../byterun/caml/sys.h ../unix/unixsupport.h
../../byterun/caml/../../config/m.h ../../byterun/caml/../../config/s.h \
../../byterun/caml/mlvalues.h ../../byterun/caml/config.h \
../../byterun/caml/misc.h ../../byterun/caml/alloc.h \
../../byterun/caml/mlvalues.h ../../byterun/caml/custom.h \
../../byterun/caml/fail.h ../../byterun/caml/sys.h \
../unix/unixsupport.h
bigarray.cmi :
bigarray.cmo : bigarray.cmi
bigarray.cmx : bigarray.cmi

View File

@ -1,74 +1,118 @@
color.o: color.c libgraph.h ../../byterun/caml/mlvalues.h \
../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
../../byterun/caml/../../config/m.h ../../byterun/caml/../../config/s.h \
../../byterun/caml/misc.h ../../byterun/caml/misc.h
draw.o: draw.c libgraph.h ../../byterun/caml/mlvalues.h \
../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
../../byterun/caml/../../config/m.h ../../byterun/caml/../../config/s.h \
../../byterun/caml/misc.h ../../byterun/caml/misc.h \
../../byterun/caml/alloc.h ../../byterun/caml/mlvalues.h
dump_img.o: dump_img.c libgraph.h ../../byterun/caml/mlvalues.h \
../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
../../byterun/caml/../../config/m.h ../../byterun/caml/../../config/s.h \
../../byterun/caml/misc.h ../../byterun/caml/misc.h image.h \
../../byterun/caml/alloc.h ../../byterun/caml/mlvalues.h \
../../byterun/caml/memory.h ../../byterun/caml/gc.h \
../../byterun/caml/major_gc.h ../../byterun/caml/freelist.h \
../../byterun/caml/minor_gc.h ../../byterun/caml/address_class.h
events.o: events.c libgraph.h ../../byterun/caml/mlvalues.h \
../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
../../byterun/caml/../../config/m.h ../../byterun/caml/../../config/s.h \
../../byterun/caml/misc.h ../../byterun/caml/misc.h \
../../byterun/caml/alloc.h ../../byterun/caml/mlvalues.h \
../../byterun/caml/signals.h
fill.o: fill.c libgraph.h ../../byterun/caml/mlvalues.h \
../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
../../byterun/caml/../../config/m.h ../../byterun/caml/../../config/s.h \
../../byterun/caml/misc.h ../../byterun/caml/misc.h \
../../byterun/caml/memory.h ../../byterun/caml/gc.h \
../../byterun/caml/mlvalues.h ../../byterun/caml/major_gc.h \
../../byterun/caml/freelist.h ../../byterun/caml/minor_gc.h \
../../byterun/caml/address_class.h
image.o: image.c libgraph.h ../../byterun/caml/mlvalues.h \
../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
../../byterun/caml/../../config/m.h ../../byterun/caml/../../config/s.h \
../../byterun/caml/misc.h ../../byterun/caml/misc.h image.h \
../../byterun/caml/alloc.h ../../byterun/caml/mlvalues.h \
../../byterun/caml/custom.h
make_img.o: make_img.c libgraph.h ../../byterun/caml/mlvalues.h \
../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
../../byterun/caml/../../config/m.h ../../byterun/caml/../../config/s.h \
../../byterun/caml/misc.h ../../byterun/caml/misc.h image.h \
../../byterun/caml/memory.h ../../byterun/caml/gc.h \
../../byterun/caml/mlvalues.h ../../byterun/caml/major_gc.h \
../../byterun/caml/freelist.h ../../byterun/caml/minor_gc.h \
../../byterun/caml/address_class.h
open.o: open.c libgraph.h ../../byterun/caml/mlvalues.h \
../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
../../byterun/caml/../../config/m.h ../../byterun/caml/../../config/s.h \
../../byterun/caml/misc.h ../../byterun/caml/misc.h \
../../byterun/caml/alloc.h ../../byterun/caml/mlvalues.h \
../../byterun/caml/callback.h ../../byterun/caml/fail.h \
../../byterun/caml/memory.h ../../byterun/caml/gc.h \
../../byterun/caml/major_gc.h ../../byterun/caml/freelist.h \
../../byterun/caml/minor_gc.h ../../byterun/caml/address_class.h
point_col.o: point_col.c libgraph.h ../../byterun/caml/mlvalues.h \
../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
../../byterun/caml/../../config/m.h ../../byterun/caml/../../config/s.h \
../../byterun/caml/misc.h ../../byterun/caml/misc.h
sound.o: sound.c libgraph.h ../../byterun/caml/mlvalues.h \
../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
../../byterun/caml/../../config/m.h ../../byterun/caml/../../config/s.h \
../../byterun/caml/misc.h ../../byterun/caml/misc.h
subwindow.o: subwindow.c libgraph.h ../../byterun/caml/mlvalues.h \
../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
../../byterun/caml/../../config/m.h ../../byterun/caml/../../config/s.h \
../../byterun/caml/misc.h ../../byterun/caml/misc.h
text.o: text.c libgraph.h ../../byterun/caml/mlvalues.h \
../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
../../byterun/caml/../../config/m.h ../../byterun/caml/../../config/s.h \
../../byterun/caml/misc.h ../../byterun/caml/misc.h \
../../byterun/caml/alloc.h ../../byterun/caml/mlvalues.h
color.o: color.c libgraph.h \
\
\
\
../../byterun/caml/mlvalues.h ../../byterun/caml/compatibility.h \
../../byterun/caml/config.h ../../byterun/caml/../../config/m.h \
../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
../../byterun/caml/misc.h
draw.o: draw.c libgraph.h \
\
\
\
../../byterun/caml/mlvalues.h ../../byterun/caml/compatibility.h \
../../byterun/caml/config.h ../../byterun/caml/../../config/m.h \
../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
../../byterun/caml/misc.h ../../byterun/caml/alloc.h \
../../byterun/caml/mlvalues.h
dump_img.o: dump_img.c libgraph.h \
\
\
\
../../byterun/caml/mlvalues.h ../../byterun/caml/compatibility.h \
../../byterun/caml/config.h ../../byterun/caml/../../config/m.h \
../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
../../byterun/caml/misc.h image.h ../../byterun/caml/alloc.h \
../../byterun/caml/mlvalues.h ../../byterun/caml/memory.h \
../../byterun/caml/gc.h ../../byterun/caml/major_gc.h \
../../byterun/caml/freelist.h ../../byterun/caml/minor_gc.h \
../../byterun/caml/address_class.h
events.o: events.c libgraph.h \
\
\
\
../../byterun/caml/mlvalues.h ../../byterun/caml/compatibility.h \
../../byterun/caml/config.h ../../byterun/caml/../../config/m.h \
../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
../../byterun/caml/misc.h ../../byterun/caml/alloc.h \
../../byterun/caml/mlvalues.h ../../byterun/caml/signals.h
fill.o: fill.c libgraph.h \
\
\
\
../../byterun/caml/mlvalues.h ../../byterun/caml/compatibility.h \
../../byterun/caml/config.h ../../byterun/caml/../../config/m.h \
../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
../../byterun/caml/misc.h ../../byterun/caml/memory.h \
../../byterun/caml/gc.h ../../byterun/caml/mlvalues.h \
../../byterun/caml/major_gc.h ../../byterun/caml/freelist.h \
../../byterun/caml/minor_gc.h ../../byterun/caml/address_class.h
image.o: image.c libgraph.h \
\
\
\
../../byterun/caml/mlvalues.h ../../byterun/caml/compatibility.h \
../../byterun/caml/config.h ../../byterun/caml/../../config/m.h \
../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
../../byterun/caml/misc.h image.h ../../byterun/caml/alloc.h \
../../byterun/caml/mlvalues.h ../../byterun/caml/custom.h
make_img.o: make_img.c libgraph.h \
\
\
\
../../byterun/caml/mlvalues.h ../../byterun/caml/compatibility.h \
../../byterun/caml/config.h ../../byterun/caml/../../config/m.h \
../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
../../byterun/caml/misc.h image.h ../../byterun/caml/memory.h \
../../byterun/caml/gc.h ../../byterun/caml/mlvalues.h \
../../byterun/caml/major_gc.h ../../byterun/caml/freelist.h \
../../byterun/caml/minor_gc.h ../../byterun/caml/address_class.h
open.o: open.c libgraph.h \
\
\
\
../../byterun/caml/mlvalues.h ../../byterun/caml/compatibility.h \
../../byterun/caml/config.h ../../byterun/caml/../../config/m.h \
../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
../../byterun/caml/misc.h ../../byterun/caml/alloc.h \
../../byterun/caml/mlvalues.h ../../byterun/caml/callback.h \
../../byterun/caml/fail.h ../../byterun/caml/memory.h \
../../byterun/caml/gc.h ../../byterun/caml/major_gc.h \
../../byterun/caml/freelist.h ../../byterun/caml/minor_gc.h \
../../byterun/caml/address_class.h
point_col.o: point_col.c libgraph.h \
\
\
\
../../byterun/caml/mlvalues.h ../../byterun/caml/compatibility.h \
../../byterun/caml/config.h ../../byterun/caml/../../config/m.h \
../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
../../byterun/caml/misc.h
sound.o: sound.c libgraph.h \
\
\
\
../../byterun/caml/mlvalues.h ../../byterun/caml/compatibility.h \
../../byterun/caml/config.h ../../byterun/caml/../../config/m.h \
../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
../../byterun/caml/misc.h
subwindow.o: subwindow.c libgraph.h \
\
\
\
../../byterun/caml/mlvalues.h ../../byterun/caml/compatibility.h \
../../byterun/caml/config.h ../../byterun/caml/../../config/m.h \
../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
../../byterun/caml/misc.h
text.o: text.c libgraph.h \
\
\
\
../../byterun/caml/mlvalues.h ../../byterun/caml/compatibility.h \
../../byterun/caml/config.h ../../byterun/caml/../../config/m.h \
../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
../../byterun/caml/misc.h ../../byterun/caml/alloc.h \
../../byterun/caml/mlvalues.h
graphics.cmi :
graphicsX11.cmi :
graphics.cmo : graphics.cmi

View File

@ -1,23 +1,23 @@
bng.o: bng.c bng.h ../../byterun/caml/config.h \
../../byterun/caml/../../config/m.h ../../byterun/caml/../../config/s.h \
../../byterun/caml/compatibility.h bng_amd64.c bng_digit.c
bng_amd64.o: bng_amd64.c
bng_arm64.o: bng_arm64.c
bng.o: bng.c bng.h ../../byterun/caml/config.h \
../../byterun/caml/../../config/m.h ../../byterun/caml/../../config/s.h \
../../byterun/caml/compatibility.h bng_amd64.c bng_digit.c
bng_digit.o: bng_digit.c
bng_ia32.o: bng_ia32.c
bng_ppc.o: bng_ppc.c
bng_sparc.o: bng_sparc.c
nat_stubs.o: nat_stubs.c ../../byterun/caml/alloc.h \
../../byterun/caml/compatibility.h ../../byterun/caml/misc.h \
../../byterun/caml/config.h ../../byterun/caml/../../config/m.h \
../../byterun/caml/../../config/s.h ../../byterun/caml/mlvalues.h \
../../byterun/caml/config.h ../../byterun/caml/custom.h \
../../byterun/caml/intext.h ../../byterun/caml/io.h \
../../byterun/caml/fail.h ../../byterun/caml/hash.h \
../../byterun/caml/memory.h ../../byterun/caml/gc.h \
../../byterun/caml/major_gc.h ../../byterun/caml/freelist.h \
../../byterun/caml/minor_gc.h ../../byterun/caml/address_class.h \
../../byterun/caml/mlvalues.h bng.h nat.h
../../byterun/caml/compatibility.h ../../byterun/caml/misc.h \
../../byterun/caml/config.h ../../byterun/caml/../../config/m.h \
../../byterun/caml/../../config/s.h ../../byterun/caml/mlvalues.h \
../../byterun/caml/config.h ../../byterun/caml/custom.h \
../../byterun/caml/intext.h ../../byterun/caml/io.h \
../../byterun/caml/fail.h ../../byterun/caml/hash.h \
../../byterun/caml/memory.h ../../byterun/caml/gc.h \
../../byterun/caml/major_gc.h ../../byterun/caml/freelist.h \
../../byterun/caml/minor_gc.h ../../byterun/caml/address_class.h \
../../byterun/caml/mlvalues.h bng.h nat.h
arith_flags.cmi :
arith_status.cmi :
big_int.cmi : nat.cmi

View File

@ -1,11 +1,11 @@
strstubs.o: strstubs.c ../../byterun/caml/mlvalues.h \
../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
../../byterun/caml/../../config/m.h ../../byterun/caml/../../config/s.h \
../../byterun/caml/misc.h ../../byterun/caml/alloc.h \
../../byterun/caml/mlvalues.h ../../byterun/caml/memory.h \
../../byterun/caml/gc.h ../../byterun/caml/major_gc.h \
../../byterun/caml/freelist.h ../../byterun/caml/minor_gc.h \
../../byterun/caml/address_class.h ../../byterun/caml/fail.h
../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
../../byterun/caml/../../config/m.h ../../byterun/caml/../../config/s.h \
../../byterun/caml/misc.h ../../byterun/caml/alloc.h \
../../byterun/caml/mlvalues.h ../../byterun/caml/memory.h \
../../byterun/caml/gc.h ../../byterun/caml/major_gc.h \
../../byterun/caml/freelist.h ../../byterun/caml/minor_gc.h \
../../byterun/caml/address_class.h ../../byterun/caml/fail.h
str.cmi :
str.cmo : str.cmi
str.cmx : str.cmi

View File

@ -1,18 +1,16 @@
st_stubs.o: st_stubs.c ../../byterun/caml/alloc.h \
../../byterun/caml/compatibility.h ../../byterun/caml/misc.h \
../../byterun/caml/config.h ../../byterun/caml/../../config/m.h \
../../byterun/caml/../../config/s.h ../../byterun/caml/mlvalues.h \
../../byterun/caml/backtrace.h ../../byterun/caml/exec.h \
../../byterun/caml/callback.h ../../byterun/caml/custom.h \
../../byterun/caml/fail.h ../../byterun/caml/io.h \
../../byterun/caml/memory.h ../../byterun/caml/gc.h \
../../byterun/caml/major_gc.h ../../byterun/caml/freelist.h \
../../byterun/caml/minor_gc.h ../../byterun/caml/address_class.h \
../../byterun/caml/misc.h ../../byterun/caml/mlvalues.h \
../../byterun/caml/printexc.h ../../byterun/caml/roots.h \
../../byterun/caml/memory.h ../../byterun/caml/signals.h \
../../byterun/caml/stacks.h ../../byterun/caml/sys.h threads.h \
st_posix.h
../../byterun/caml/compatibility.h ../../byterun/caml/misc.h \
../../byterun/caml/config.h ../../byterun/caml/../../config/m.h \
../../byterun/caml/../../config/s.h ../../byterun/caml/mlvalues.h \
../../byterun/caml/backtrace.h ../../byterun/caml/exec.h \
../../byterun/caml/callback.h ../../byterun/caml/custom.h \
../../byterun/caml/fail.h ../../byterun/caml/io.h \
../../byterun/caml/memory.h ../../byterun/caml/gc.h \
../../byterun/caml/major_gc.h ../../byterun/caml/freelist.h \
../../byterun/caml/minor_gc.h ../../byterun/caml/address_class.h \
../../byterun/caml/printexc.h ../../byterun/caml/roots.h \
../../byterun/caml/signals.h ../../byterun/caml/stacks.h \
../../byterun/caml/sys.h threads.h st_posix.h
condition.cmi : mutex.cmi
event.cmi :
mutex.cmi :

View File

@ -1,17 +1,17 @@
scheduler.o: scheduler.c ../../byterun/caml/alloc.h \
../../byterun/caml/compatibility.h ../../byterun/caml/misc.h \
../../byterun/caml/config.h ../../byterun/caml/../../config/m.h \
../../byterun/caml/../../config/s.h ../../byterun/caml/mlvalues.h \
../../byterun/caml/backtrace.h ../../byterun/caml/exec.h \
../../byterun/caml/callback.h ../../byterun/caml/config.h \
../../byterun/caml/fail.h ../../byterun/caml/io.h \
../../byterun/caml/memory.h ../../byterun/caml/gc.h \
../../byterun/caml/major_gc.h ../../byterun/caml/freelist.h \
../../byterun/caml/minor_gc.h ../../byterun/caml/address_class.h \
../../byterun/caml/misc.h ../../byterun/caml/mlvalues.h \
../../byterun/caml/printexc.h ../../byterun/caml/roots.h \
../../byterun/caml/memory.h ../../byterun/caml/signals.h \
../../byterun/caml/stacks.h ../../byterun/caml/sys.h
../../byterun/caml/compatibility.h ../../byterun/caml/misc.h \
../../byterun/caml/config.h ../../byterun/caml/../../config/m.h \
../../byterun/caml/../../config/s.h ../../byterun/caml/mlvalues.h \
../../byterun/caml/backtrace.h ../../byterun/caml/exec.h \
../../byterun/caml/callback.h ../../byterun/caml/config.h \
../../byterun/caml/fail.h ../../byterun/caml/io.h \
../../byterun/caml/memory.h ../../byterun/caml/gc.h \
../../byterun/caml/major_gc.h ../../byterun/caml/freelist.h \
../../byterun/caml/minor_gc.h ../../byterun/caml/address_class.h \
../../byterun/caml/misc.h ../../byterun/caml/mlvalues.h \
../../byterun/caml/printexc.h ../../byterun/caml/roots.h \
../../byterun/caml/memory.h ../../byterun/caml/signals.h \
../../byterun/caml/stacks.h ../../byterun/caml/sys.h
condition.cmi : mutex.cmi
event.cmi :
marshal.cmi :

File diff suppressed because it is too large Load Diff

View File

@ -93,8 +93,8 @@ format.cmo : string.cmi pervasives.cmi camlinternalFormatBasics.cmi \
camlinternalFormat.cmi buffer.cmi format.cmi
format.cmx : string.cmx pervasives.cmx camlinternalFormatBasics.cmx \
camlinternalFormat.cmx buffer.cmx format.cmi
gc.cmo : sys.cmi printf.cmi gc.cmi
gc.cmx : sys.cmx printf.cmx gc.cmi
gc.cmo : sys.cmi string.cmi printf.cmi gc.cmi
gc.cmx : sys.cmx string.cmx printf.cmx gc.cmi
genlex.cmo : string.cmi stream.cmi list.cmi hashtbl.cmi char.cmi bytes.cmi \
genlex.cmi
genlex.cmx : string.cmx stream.cmx list.cmx hashtbl.cmx char.cmx bytes.cmx \
@ -123,8 +123,8 @@ moreLabels.cmo : set.cmi map.cmi hashtbl.cmi moreLabels.cmi
moreLabels.cmx : set.cmx map.cmx hashtbl.cmx moreLabels.cmi
nativeint.cmo : sys.cmi pervasives.cmi nativeint.cmi
nativeint.cmx : sys.cmx pervasives.cmx nativeint.cmi
obj.cmo : marshal.cmi int32.cmi array.cmi obj.cmi
obj.cmx : marshal.cmx int32.cmx array.cmx obj.cmi
obj.cmo : marshal.cmi int32.cmi obj.cmi
obj.cmx : marshal.cmx int32.cmx obj.cmi
oo.cmo : camlinternalOO.cmi oo.cmi
oo.cmx : camlinternalOO.cmx oo.cmi
parsing.cmo : obj.cmi lexing.cmi array.cmi parsing.cmi
@ -141,14 +141,14 @@ printf.cmx : camlinternalFormatBasics.cmx camlinternalFormat.cmx buffer.cmx \
printf.cmi
queue.cmo : queue.cmi
queue.cmx : queue.cmi
random.cmo : pervasives.cmi nativeint.cmi int64.cmi int32.cmi digest.cmi \
char.cmi array.cmi random.cmi
random.cmx : pervasives.cmx nativeint.cmx int64.cmx int32.cmx digest.cmx \
char.cmx array.cmx random.cmi
scanf.cmo : weak.cmi string.cmi printf.cmi pervasives.cmi hashtbl.cmi \
random.cmo : string.cmi pervasives.cmi nativeint.cmi int64.cmi int32.cmi \
digest.cmi char.cmi array.cmi random.cmi
random.cmx : string.cmx pervasives.cmx nativeint.cmx int64.cmx int32.cmx \
digest.cmx char.cmx array.cmx random.cmi
scanf.cmo : string.cmi printf.cmi pervasives.cmi list.cmi \
camlinternalFormatBasics.cmi camlinternalFormat.cmi bytes.cmi buffer.cmi \
scanf.cmi
scanf.cmx : weak.cmx string.cmx printf.cmx pervasives.cmx hashtbl.cmx \
scanf.cmx : string.cmx printf.cmx pervasives.cmx list.cmx \
camlinternalFormatBasics.cmx camlinternalFormat.cmx bytes.cmx buffer.cmx \
scanf.cmi
set.cmo : list.cmi set.cmi
@ -219,8 +219,8 @@ format.cmo : string.cmi pervasives.cmi camlinternalFormatBasics.cmi \
camlinternalFormat.cmi buffer.cmi format.cmi
format.p.cmx : string.cmx pervasives.cmx camlinternalFormatBasics.cmx \
camlinternalFormat.cmx buffer.cmx format.cmi
gc.cmo : sys.cmi printf.cmi gc.cmi
gc.p.cmx : sys.cmx printf.cmx gc.cmi
gc.cmo : sys.cmi string.cmi printf.cmi gc.cmi
gc.p.cmx : sys.cmx string.cmx printf.cmx gc.cmi
genlex.cmo : string.cmi stream.cmi list.cmi hashtbl.cmi char.cmi bytes.cmi \
genlex.cmi
genlex.p.cmx : string.cmx stream.cmx list.cmx hashtbl.cmx char.cmx bytes.cmx \
@ -249,8 +249,8 @@ moreLabels.cmo : set.cmi map.cmi hashtbl.cmi moreLabels.cmi
moreLabels.p.cmx : set.cmx map.cmx hashtbl.cmx moreLabels.cmi
nativeint.cmo : sys.cmi pervasives.cmi nativeint.cmi
nativeint.p.cmx : sys.cmx pervasives.cmx nativeint.cmi
obj.cmo : marshal.cmi int32.cmi array.cmi obj.cmi
obj.p.cmx : marshal.cmx int32.cmx array.cmx obj.cmi
obj.cmo : marshal.cmi int32.cmi obj.cmi
obj.p.cmx : marshal.cmx int32.cmx obj.cmi
oo.cmo : camlinternalOO.cmi oo.cmi
oo.p.cmx : camlinternalOO.cmx oo.cmi
parsing.cmo : obj.cmi lexing.cmi array.cmi parsing.cmi
@ -267,14 +267,14 @@ printf.p.cmx : camlinternalFormatBasics.cmx camlinternalFormat.cmx buffer.cmx \
printf.cmi
queue.cmo : queue.cmi
queue.p.cmx : queue.cmi
random.cmo : pervasives.cmi nativeint.cmi int64.cmi int32.cmi digest.cmi \
char.cmi array.cmi random.cmi
random.p.cmx : pervasives.cmx nativeint.cmx int64.cmx int32.cmx digest.cmx \
char.cmx array.cmx random.cmi
scanf.cmo : weak.cmi string.cmi printf.cmi pervasives.cmi hashtbl.cmi \
random.cmo : string.cmi pervasives.cmi nativeint.cmi int64.cmi int32.cmi \
digest.cmi char.cmi array.cmi random.cmi
random.p.cmx : string.cmx pervasives.cmx nativeint.cmx int64.cmx int32.cmx \
digest.cmx char.cmx array.cmx random.cmi
scanf.cmo : string.cmi printf.cmi pervasives.cmi list.cmi \
camlinternalFormatBasics.cmi camlinternalFormat.cmi bytes.cmi buffer.cmi \
scanf.cmi
scanf.p.cmx : weak.cmx string.cmx printf.cmx pervasives.cmx hashtbl.cmx \
scanf.p.cmx : string.cmx printf.cmx pervasives.cmx list.cmx \
camlinternalFormatBasics.cmx camlinternalFormat.cmx bytes.cmx buffer.cmx \
scanf.cmi
set.cmo : list.cmi set.cmi

View File

@ -45,16 +45,18 @@ installopt-prof:
stdlib.p.cmxa: $(OBJS:.cmo=.p.cmx)
$(CAMLOPT) -a -o stdlib.p.cmxa $(OBJS:.cmo=.p.cmx)
camlheader target_camlheader camlheaderd target_camlheaderd camlheader_ur: \
camlheader target_camlheader camlheader_ur \
camlheaderd target_camlheaderd \
camlheaderi target_camlheaderi: \
header.c ../config/Makefile
if $(SHARPBANGSCRIPTS); then \
echo '#!$(BINDIR)/ocamlrun' > camlheader && \
echo '#!$(TARGET_BINDIR)/ocamlrun' > target_camlheader && \
echo '#!$(BINDIR)/ocamlrund' > camlheaderd && \
echo '#!$(TARGET_BINDIR)/ocamlrund' > target_camlheaderd && \
for suff in '' d i; do \
echo '#!$(BINDIR)/ocamlrun'$$suff > camlheader$$suff && \
echo '#!$(TARGET_BINDIR)/ocamlrun'$$suff > target_camlheader$$suff; \
done && \
echo '#!' | tr -d '\012' > camlheader_ur; \
else \
for suff in '' d; do \
for suff in '' d i; do \
$(BYTECC) $(BYTECCCOMPOPTS) $(BYTECCLINKOPTS) \
-DRUNTIME_NAME='"$(BINDIR)/ocamlrun'$$suff'"' \
header.c -o tmpheader$(EXE) && \

View File

@ -34,5 +34,11 @@ camlheaderd target_camlheaderd: headernt.c ../config/Makefile
mv tmpheader.exe camlheaderd
cp camlheaderd target_camlheaderd
camlheaderi: headernt.c ../config/Makefile
$(BYTECC) $(BYTECCCOMPOPTS) -c -I../byterun \
-DRUNTIME_NAME='"ocamlruni"' headernt.c
$(MKEXE) -o tmpheader.exe headernt.$(O) $(EXTRALIBS)
mv tmpheader.exe camlheaderi
# TODO: do not call flexlink to build tmpheader.exe (we don't need
# the export table)

View File

@ -25,8 +25,8 @@ CAMLOPT=$(CAMLRUN) $(OPTCOMPILER)
CAMLDEP=$(CAMLRUN) ../tools/ocamldep
OBJS=camlinternalFormatBasics.cmo pervasives.cmo $(OTHERS)
OTHERS=array.cmo list.cmo char.cmo bytes.cmo string.cmo sys.cmo \
sort.cmo marshal.cmo obj.cmo \
OTHERS=list.cmo char.cmo bytes.cmo string.cmo sys.cmo \
sort.cmo marshal.cmo obj.cmo array.cmo \
int32.cmo int64.cmo nativeint.cmo \
lexing.cmo parsing.cmo \
set.cmo map.cmo stack.cmo queue.cmo \
@ -43,20 +43,32 @@ OTHERS=array.cmo list.cmo char.cmo bytes.cmo string.cmo sys.cmo \
all: stdlib.cma std_exit.cmo camlheader target_camlheader camlheader_ur
ifeq "$(RUNTIMED)" "runtimed"
all: camlheaderd
endif
ifeq "$(RUNTIMEI)" "true"
all: camlheaderi
endif
INSTALL_LIBDIR=$(DESTDIR)$(LIBDIR)
install: install-$(RUNTIMED)
install::
cp stdlib.cma std_exit.cmo *.cmi *.cmt *.cmti *.mli *.ml \
camlheader_ur \
$(INSTALL_LIBDIR)
cp target_camlheader $(INSTALL_LIBDIR)/camlheader
install-noruntimed:
.PHONY: install-noruntimed
ifeq "$(RUNTIMED)" "runtimed"
install::
cp target_camlheaderd $(INSTALL_LIBDIR)
endif
ifeq "$(RUNTIMEI)" "true"
install::
cp target_camlheaderi $(INSTALL_LIBDIR)
endif
install-runtimed: target_camlheaderd
cp target_camlheaderd $(INSTALL_LIBDIR)/camlheaderd
.PHONY: install-runtimed
stdlib.cma: $(OBJS)
$(CAMLC) -a -o stdlib.cma $(OBJS)
@ -71,7 +83,7 @@ clean::
rm -f sys.ml
clean::
rm -f camlheader target_camlheader camlheader_ur target_camlheaderd
rm -f camlheader target_camlheader camlheader_ur target_camlheader[di]
.SUFFIXES: .mli .ml .cmi .cmo .cmx .p.cmx
@ -104,6 +116,7 @@ $(OTHERS:.cmo=.p.cmx) std_exit.p.cmx: pervasives.cmx
clean::
rm -f *.cm* *.$(O) *.$(A)
rm -f *~
rm -f camlheader*
include .depend

View File

@ -38,6 +38,7 @@ type control = {
mutable max_overhead : int;
mutable stack_limit : int;
mutable allocation_policy : int;
window_size : int;
};;
external stat : unit -> stat = "caml_gc_stat";;
@ -50,26 +51,35 @@ external major_slice : int -> int = "caml_gc_major_slice";;
external major : unit -> unit = "caml_gc_major";;
external full_major : unit -> unit = "caml_gc_full_major";;
external compact : unit -> unit = "caml_gc_compaction";;
external get_minor_free : unit -> int = "caml_get_minor_free" [@@noalloc]
external get_bucket : int -> int = "caml_get_major_bucket" [@@noalloc]
external get_credit : unit -> int = "caml_get_major_credit" [@@noalloc]
external huge_fallback_count : unit -> int = "caml_gc_huge_fallback_count"
open Printf;;
let print_stat c =
let st = stat () in
fprintf c "minor_words: %.0f\n" st.minor_words;
fprintf c "promoted_words: %.0f\n" st.promoted_words;
fprintf c "major_words: %.0f\n" st.major_words;
fprintf c "minor_collections: %d\n" st.minor_collections;
fprintf c "major_collections: %d\n" st.major_collections;
fprintf c "heap_words: %d\n" st.heap_words;
fprintf c "heap_chunks: %d\n" st.heap_chunks;
fprintf c "top_heap_words: %d\n" st.top_heap_words;
fprintf c "live_words: %d\n" st.live_words;
fprintf c "compactions: %d\n" st.compactions;
fprintf c "\n";
let l1 = String.length (sprintf "%.0f" st.minor_words) in
fprintf c "minor_words: %*.0f\n" l1 st.minor_words;
fprintf c "promoted_words: %*.0f\n" l1 st.promoted_words;
fprintf c "major_words: %*.0f\n" l1 st.major_words;
fprintf c "\n";
let l2 = String.length (sprintf "%d" st.top_heap_words) in
fprintf c "top_heap_words: %*d\n" l2 st.top_heap_words;
fprintf c "heap_words: %*d\n" l2 st.heap_words;
fprintf c "live_words: %*d\n" l2 st.live_words;
fprintf c "free_words: %*d\n" l2 st.free_words;
fprintf c "largest_free: %*d\n" l2 st.largest_free;
fprintf c "fragments: %*d\n" l2 st.fragments;
fprintf c "\n";
fprintf c "live_blocks: %d\n" st.live_blocks;
fprintf c "free_words: %d\n" st.free_words;
fprintf c "free_blocks: %d\n" st.free_blocks;
fprintf c "largest_free: %d\n" st.largest_free;
fprintf c "fragments: %d\n" st.fragments;
fprintf c "compactions: %d\n" st.compactions;
fprintf c "heap_chunks: %d\n" st.heap_chunks;
;;
let allocated_bytes () =

View File

@ -141,6 +141,12 @@ type control =
first-fit policy, which can be slower in some cases but
can be better for programs with fragmentation problems.
Default: 0. @since 3.11.0 *)
window_size : int;
(** The size of the window used by the major GC for smoothing
out variations in its workload. This is an integer between
1 and 50.
Default: 1. @since 4.03.0 *)
}
(** The GC parameters are given as a [control] record. Note that
these parameters can also be initialised by setting the
@ -173,9 +179,13 @@ external minor : unit -> unit = "caml_gc_minor"
(** Trigger a minor collection. *)
external major_slice : int -> int = "caml_gc_major_slice";;
(** Do a minor collection and a slice of major collection. The argument
is the size of the slice, 0 to use the automatically-computed
slice size. In all cases, the result is the computed slice size. *)
(** [major_slice n]
Do a minor collection and a slice of major collection. [n] is the
size of the slice: the GC will do enough work to free (on average)
[n] words of memory. If [n] = 0, the GC will try to do enough work
to ensure that the next slice has no work to do.
Return an approximation of the work that the next slice will have
to do. *)
external major : unit -> unit = "caml_gc_major"
(** Do a minor collection and finish the current major collection cycle. *)
@ -198,6 +208,25 @@ val allocated_bytes : unit -> float
started. It is returned as a [float] to avoid overflow problems
with [int] on 32-bit machines. *)
external get_minor_free : unit -> int = "caml_get_minor_free" [@@noalloc]
(** Return the current size of the free space inside the minor heap. *)
external get_bucket : int -> int = "caml_get_major_bucket" [@@noalloc]
(** [get_bucket n] returns the current size of the [n]-th future bucket
of the GC smoothing system. The unit is one millionth of a full GC.
Raise [Invalid_argument] if [n] is negative, return 0 if n is larger
than the smoothing window. *)
external get_credit : unit -> int = "caml_get_major_credit" [@@noalloc]
(** [get_credit ()] returns the current size of the "work done in advance"
counter of the GC smoothing system. The unit is one millionth of a
full GC. *)
external huge_fallback_count : unit -> int = "caml_gc_huge_fallback_count"
(** Return the number of times we tried to map huge pages and had to fall
back to small pages. This is always 0 if [OCAMLRUNPARAM] contains [H=1].
@since 4.03.0 *)
val finalise : ('a -> unit) -> 'a -> unit
(** [finalise f v] registers [f] as a finalisation function for [v].
[v] must be heap-allocated. [f] will be called with [v] as

View File

@ -25,8 +25,10 @@ external set_tag : t -> int -> unit = "caml_obj_set_tag"
external size : t -> int = "%obj_size"
external field : t -> int -> t = "%obj_field"
external set_field : t -> int -> t -> unit = "%obj_set_field"
let double_field x i = Array.get (obj x : float array) i
let set_double_field x i v = Array.set (obj x : float array) i v
external array_get: 'a array -> int -> 'a = "%array_safe_get"
external array_set: 'a array -> int -> 'a -> unit = "%array_safe_set"
let double_field x i = array_get (obj x : float array) i
let set_double_field x i v = array_set (obj x : float array) i v
external new_block : int -> int -> t = "caml_obj_block"
external dup : t -> t = "caml_obj_dup"
external truncate : t -> int -> unit = "caml_obj_truncate"

View File

@ -119,6 +119,17 @@ val max_array_length : int
array is [max_array_length/2] on 32-bit machines and
[max_array_length] on 64-bit machines. *)
external runtime_variant : unit -> string = "caml_runtime_variant"
(** Return the name of the runtime variant the program is running on.
This is normally the argument given to [-runtime-variant] at compile
time, but for byte-code it can be changed after compilation.
@since 4.03.0 *)
external runtime_parameters : unit -> string = "caml_runtime_parameters"
(** Return the value of the runtime parameters, in the same format
as the contents of the [OCAMLRUNPARAM] environment variable.
@since 4.03.0 *)
(** {6 Signal handling} *)

View File

@ -37,6 +37,8 @@ let win32 = win32 ()
let cygwin = cygwin ()
let max_array_length = max_wosize ()
let max_string_length = word_size / 8 * max_array_length - 1;;
external runtime_variant : unit -> string = "caml_runtime_variant"
external runtime_parameters : unit -> string = "caml_runtime_parameters"
external file_exists: string -> bool = "caml_sys_file_exists"
external is_directory : string -> bool = "caml_sys_is_directory"

View File

@ -13,7 +13,8 @@ val intB : [< `TagB ] -> int = <fun>
^^^^
Error: This expression has type ([< `TagA of 'b ] as 'a) -> 'b
but an expression was expected of type a -> int
Type 'a is not compatible with type a = [< `TagA of int | `TagB ]
Type [< `TagA of 'b ] as 'a is not compatible with type
a = [< `TagA of int | `TagB ]
The first variant type does not allow tag(s) `TagB
# Characters 10-18:
let _ = example6 (WrapPoly AandBTags) `TagB (* This causes a seg fault *)

View File

@ -0,0 +1,14 @@
type 'a t
type a
let f : < .. > t -> unit = fun _ -> ();;
let g : [< `b] t -> unit = fun _ -> ();;
let h : [> `b] t -> unit = fun _ -> ();;
let _ = fun (x : a t) -> f x;;
let _ = fun (x : a t) -> g x;;
let _ = fun (x : a t) -> h x;;

Some files were not shown because too many files have changed in this diff Show More