Merge with trunk; remake dependencies
commit
852efd270e
187
.depend
187
.depend
|
@ -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 \
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
7
Changes
7
Changes
|
@ -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):
|
||||
---------------------------
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 \
|
||||
|
|
2
VERSION
2
VERSION
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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_
|
||||
|
|
@ -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)_
|
|
@ -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_
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -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.)
|
||||
|
|
@ -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)
|
||||
|
||||
|
||||
|
|
@ -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_
|
||||
|
||||
|
||||
|
||||
|
2478
asmrun/.depend
2478
asmrun/.depend
File diff suppressed because it is too large
Load Diff
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -690,3 +690,6 @@ TOCENTRY(caml_young_limit)
|
|||
TOCENTRY(caml_young_ptr)
|
||||
|
||||
#endif
|
||||
|
||||
/* Mark stack as non-executable */
|
||||
.section .note.GNU-stack,"",%progbits
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
../byterun/startup_aux.c
|
BIN
boot/ocamlc
BIN
boot/ocamlc
Binary file not shown.
BIN
boot/ocamldep
BIN
boot/ocamldep
Binary file not shown.
BIN
boot/ocamllex
BIN
boot/ocamllex
Binary file not shown.
|
@ -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 *)
|
||||
|
|
|
@ -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 =
|
||||
|
|
|
@ -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@ "
|
||||
|
|
|
@ -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)
|
||||
| _ -> ()
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
1514
byterun/.depend
1514
byterun/.depend
File diff suppressed because it is too large
Load Diff
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#ifndef CAML_ADDRESS_CLASS_H
|
||||
#define CAML_ADDRESS_CLASS_H
|
||||
|
||||
#include "config.h"
|
||||
#include "misc.h"
|
||||
#include "mlvalues.h"
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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); \
|
||||
} \
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 *);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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: %"
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
114
byterun/memory.c
114
byterun/memory.c
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 *);
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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'){
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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}
|
||||
|
||||
|
|
|
@ -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}
|
||||
|
||||
|
|
|
@ -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}}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 :
|
||||
|
|
|
@ -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
|
@ -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
|
||||
|
|
|
@ -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) && \
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
32
stdlib/gc.ml
32
stdlib/gc.ml
|
@ -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 () =
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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} *)
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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 *)
|
||||
|
|
|
@ -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
Loading…
Reference in New Issue