From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Original-To: caml-list@sympa.inria.fr Delivered-To: caml-list@sympa.inria.fr Received: from mail2-relais-roc.national.inria.fr (mail2-relais-roc.national.inria.fr [192.134.164.83]) by sympa.inria.fr (Postfix) with ESMTPS id 096197FACC for ; Sat, 6 Sep 2014 07:51:27 +0200 (CEST) Received-SPF: None (mail2-smtp-roc.national.inria.fr: no sender authenticity information available from domain of martin.jambon@ens-lyon.org) identity=pra; client-ip=66.111.4.25; receiver=mail2-smtp-roc.national.inria.fr; envelope-from="martin.jambon@ens-lyon.org"; x-sender="martin.jambon@ens-lyon.org"; x-conformance=sidf_compatible Received-SPF: Neutral (mail2-smtp-roc.national.inria.fr: domain of martin.jambon@ens-lyon.org does not assert whether or not 66.111.4.25 is permitted sender) identity=mailfrom; client-ip=66.111.4.25; receiver=mail2-smtp-roc.national.inria.fr; envelope-from="martin.jambon@ens-lyon.org"; x-sender="martin.jambon@ens-lyon.org"; x-conformance=sidf_compatible; x-record-type="v=spf1" Received-SPF: None (mail2-smtp-roc.national.inria.fr: no sender authenticity information available from domain of postmaster@out1-smtp.messagingengine.com) identity=helo; client-ip=66.111.4.25; receiver=mail2-smtp-roc.national.inria.fr; envelope-from="martin.jambon@ens-lyon.org"; x-sender="postmaster@out1-smtp.messagingengine.com"; x-conformance=sidf_compatible X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: Aq8BAASgClRCbwQZnGdsb2JhbABAGoNgV4J8tDeRcodMAYEEFhABAQEBAQYNCQkUKYQEAQUjBBEIOAEBDwsYAgIFFgsCAgkDAgECAUUGDQEFAgEBiD4NNqhReIUIkB8BEQaBLI4hB4J5gVOLOYcLgy+CO4YfhUYakWtMAYJOAQEB X-IPAS-Result: Aq8BAASgClRCbwQZnGdsb2JhbABAGoNgV4J8tDeRcodMAYEEFhABAQEBAQYNCQkUKYQEAQUjBBEIOAEBDwsYAgIFFgsCAgkDAgECAUUGDQEFAgEBiD4NNqhReIUIkB8BEQaBLI4hB4J5gVOLOYcLgy+CO4YfhUYakWtMAYJOAQEB X-IronPort-AV: E=Sophos;i="5.04,478,1406584800"; d="scan'208";a="93280851" Received: from out1-smtp.messagingengine.com ([66.111.4.25]) by mail2-smtp-roc.national.inria.fr with ESMTP/TLS/DHE-RSA-AES256-SHA; 06 Sep 2014 07:51:26 +0200 Received: from compute2.internal (compute2.nyi.internal [10.202.2.42]) by gateway2.nyi.internal (Postfix) with ESMTP id 8344C208F6 for ; Sat, 6 Sep 2014 01:51:24 -0400 (EDT) Received: from frontend2 ([10.202.2.161]) by compute2.internal (MEProxy); Sat, 06 Sep 2014 01:51:24 -0400 DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d= messagingengine.com; h=message-id:date:from:mime-version:to:cc :subject:references:in-reply-to:content-type :content-transfer-encoding; s=smtpout; bh=I2yu3JY5NmlRK427NQr+7B bAbt8=; b=bgcvDNwdKVvibFxIGH8h9dwKPAzQwbjeB8K4NhTcZy9V5W1cNTBfVy CLw+xuCjqUJqnnU4HV496bRVmFoJrHE3Z+1AwnHVhQ2lrPHKT4d8s2emKopRqvS5 NeE6YrIzpPo5eB5zCAZaz9iSYisGv/WE2kfQpoTKaK70SeMNvXdEI= X-Sasl-enc: vyiiFZoYxTDVt0nytRamvdC7HXMxDX5FZd8QG+6WD3tp 1409982684 Received: from [192.168.2.7] (unknown [67.180.86.2]) by mail.messagingengine.com (Postfix) with ESMTPA id 12DB16800B5; Sat, 6 Sep 2014 01:51:23 -0400 (EDT) Message-ID: <540AA0DB.1040202@ens-lyon.org> Date: Fri, 05 Sep 2014 22:51:23 -0700 From: Martin Jambon User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Thunderbird/24.0 MIME-Version: 1.0 To: Jeremy Yallop CC: Caml List References: <20140905215626.GB3416@annexia.org> <20140905221302.GE3099@annexia.org> <20140905221813.GC3416@annexia.org> <540A3B85.6010609@ens-lyon.org> In-Reply-To: Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit Subject: Re: [Caml-list] segfault in simple program with 4.02 native On Fri 05 Sep 2014 05:12:44 PM PDT, Jeremy Yallop wrote: > On 6 September 2014 00:39, Martin Jambon wrote: >> That code is generated by atdgen. What happens is that we have to either >> create an empty record when starting to parse a list of unordered JSON >> fields, or use a bunch `let = ref None in` for each field and >> create the record in the end. While the latter approach is not much more >> work to implement, the resulting code was found to be significantly slower. >> >> The reason why it's using `Obj.magic 0.0` is that it worked in all cases >> (and has been for the past 4 years). Obtaining a well-formed constant value >> for any type is not trivial, so this what we have. >> >> It's very possible that it's now broken with OCaml 4.02. First try a 'make >> test' from atdgen's source directory (https://github.com/mjambon/atdgen) and >> see if it passes. > > It does seem to be broken, and the change in behaviour with 4.0.2 is > apparently due to improved constant propagation > (http://caml.inria.fr/mantis/view.php?id=5779). > > The compiler now takes more advantage of immutability to improve the > memory usage and performance of programs. It's safe (or ought to be > safe) to assume that immutable record fields are never updated, so the > values used to initialize the fields can be propagated to other parts > of the program. Here's a small example that shows the change in > behaviour between 4.01 and 4.02. > > type t = { s : string } > let x = { s = "one" } > let () = Obj.(set_field (repr x) 0 (repr "two")) > let () = print_endline x.s > > Using OCaml 4.01 the third line overwrites the field 's' and the > fourth line reads the updated field and prints "two". Using OCaml > 4.02 the initial value of the field is propagated past the write to > the code in the fourth line, so the program prints "one". > > The code currently generated by atdgen assumes that it's safe to treat > fields as if they were mutable -- that is, it assumes that it's safe > to initialize a field with a value of the wrong type, so long as the > value is overwritten before the field is first read. I don't think > such tricks were ever explicitly guaranteed to work, but they're now > much more likely to fail, leading to the dummy initial value being > accessed at an inappropriate type. Thanks for the explanation, Jeremy. I guess atdgen will have to use "option refs" after all unless someone has a better idea. ATD definition: type t = { ?field0: foo option; ~field1: string; field2: int; } Generated OCaml code: let field0 = ref None in let field1 = ref "" in let field2 = ref None in ... (* parse json fields coming in an unknown order *) ... { field0 = !field0; field1 = !field1; field2 = (match !field2 with None -> error ... | Some x - >x); }