Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug modules recursifs #4008

Closed
vicuna opened this issue Apr 19, 2006 · 3 comments
Closed

Bug modules recursifs #4008

vicuna opened this issue Apr 19, 2006 · 3 comments
Assignees
Labels

Comments

@vicuna
Copy link

vicuna commented Apr 19, 2006

Original bug ID: 4008
Reporter: @alainfrisch
Assigned to: @xavierleroy
Status: closed (set by @xavierleroy on 2006-05-06T07:29:34Z)
Resolution: fixed
Priority: normal
Severity: major
Version: 3.09.1
Category: ~DO NOT USE (was: OCaml general)
Monitored by: "Keiko NAKATA" "Hendrik Tews" @alainfrisch

Bug description

Je rapporte un bug signalé sur la caml-list (en le minimisant un peu plus):

module rec M : (sig val f : int list -> int list end) =
struct let f = List.map succ end
let _ = M.f []

Compilé en byte-code, ça segfaulte. Si on modifie CamlinternalMod pour utiliser toujours le mode "indirection" plutôt que "recopie par-dessus" pour les fonctions, ça marche. Donc j'imagine que CamlinternalMod.overwrite ne marche pas comme il faut pour les fermetures en bytecode.

@vicuna
Copy link
Author

vicuna commented May 2, 2006

Comment author: @alainfrisch

J'ai trouvé l'explication: l'opcode RESTART utilise la taille du bloc
environnement (Wosize_val(env) - 2) pour déterminer le nombre d'arguments suspendus. Or ce bloc peut être trop gros s'il a été créé au départ par CamlinternalMod.init_mod (cas Function).

Une solution pourrait être d'utiliser comme valeur pour les valeurs de padding un pointeur global; RESTART pourrait alors vérifier si le dernier slot du bloc est ce pointeur et dans ce cas décrementer num_args autant de fois qu'il faut (on peut commencer par tester si num_args==8). Ça ajoute quand même un test pour chaque RESTART...

@vicuna
Copy link
Author

vicuna commented May 2, 2006

Comment author: @alainfrisch

Xavier suggère de détecter, dans CamlinternalMod.update_mod si la fermeture pointe en fait vers un opcode RESTART et dans ce cas utiliser l'indirection plutôt que la copie. Le code suivant a l'air de marcher:

let can_copy n =
Obj.tag n = Obj.closure_tag
&& (Obj.size n <= 2 ||
let env = Obj.field n 1 in
Obj.tag env != Obj.closure_tag ||
let code = Obj.magic (Obj.field n 0) in
let env_code = Obj.magic (Obj.field (Obj.field n 1) 0) in
let diff = env_code - code in
diff != 2 && diff != 4
)

let rec update_mod shape o n =
match shape with
| Function ->
if can_copy n && Obj.size n <= Obj.size o
then overwrite o n
else overwrite o (Obj.repr (fun x -> (Obj.obj n : _ -> _) x))
...

@vicuna
Copy link
Author

vicuna commented May 6, 2006

Comment author: @xavierleroy

Fixed in 3.09 bugfix branch.

@vicuna vicuna closed this as completed May 6, 2006
@vicuna vicuna added the bug label Mar 19, 2019
stedolan added a commit to stedolan/ocaml that referenced this issue Apr 1, 2019
CamlinternalMod contains an optimisation for the initialisation
of recursive modules containing closures, where dummy closures
are updated in-place. This optimisation was buggy on bytecode,
since the bytecode interpreter relies on the lengths of blocks
containing closures (see ocaml#4008).

This commit disables the optimisation for bytecode (where it
had much less effect than on native code, and where performance
is of less concern anyway). The optimisation is still applied
on native-code, but without the use of Obj.truncate.

Also adds a test for ocaml#4008 (which introduced the truncate).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants